swarph-cli 0.68.2__tar.gz → 0.69.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 (445) hide show
  1. {swarph_cli-0.68.2/src/swarph_cli.egg-info → swarph_cli-0.69.1}/PKG-INFO +1 -1
  2. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/pyproject.toml +1 -1
  3. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/__init__.py +1 -1
  4. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/channel.py +4 -3
  5. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/brain_ask.py +33 -22
  6. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/codegraph.py +7 -8
  7. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/codegraph_hook.py +2 -1
  8. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/daemon.py +5 -8
  9. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/gh_route.py +3 -2
  10. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/highlight.py +14 -7
  11. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/hooks.py +2 -5
  12. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/install_postcompact_hook.py +2 -2
  13. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/mcp_server.py +6 -3
  14. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/memory.py +5 -0
  15. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/memory_emit_hook.py +12 -3
  16. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/mesh.py +187 -21
  17. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/monitor.py +2 -1
  18. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/onboard.py +4 -3
  19. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/wake_hook_output.py +2 -1
  20. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/watchdog.py +8 -5
  21. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/gateway/server.py +11 -0
  22. swarph_cli-0.69.1/src/swarph_cli/identity.py +85 -0
  23. {swarph_cli-0.68.2 → swarph_cli-0.69.1/src/swarph_cli.egg-info}/PKG-INFO +1 -1
  24. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli.egg-info/SOURCES.txt +3 -0
  25. swarph_cli-0.69.1/tests/test_402_one_identity_resolver.py +229 -0
  26. swarph_cli-0.69.1/tests/test_472_register_caller_binding.py +101 -0
  27. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_brain_ask_env_diagnosis.py +12 -9
  28. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_brain_ask_identity_explicitness.py +12 -12
  29. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_mesh_sidecar.py +1 -0
  30. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_postcompact_recall.py +3 -3
  31. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_tmux_wake_runstate_defer.py +2 -0
  32. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_tmux_wake_submit_verify.py +197 -4
  33. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_watchdog.py +8 -6
  34. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/LICENSE +0 -0
  35. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/README.md +0 -0
  36. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/setup.cfg +0 -0
  37. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/__main__.py +0 -0
  38. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/bench/__init__.py +0 -0
  39. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/bench/backends.py +0 -0
  40. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/bench/pack.py +0 -0
  41. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/bench/prices.py +0 -0
  42. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/bench/providers.py +0 -0
  43. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/bench/quality.py +0 -0
  44. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/bench/refresh_prices.py +0 -0
  45. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/bench/rules.py +0 -0
  46. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/bench/runner.py +0 -0
  47. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/bench/validate.py +0 -0
  48. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/caller.py +0 -0
  49. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/capture/__init__.py +0 -0
  50. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/capture/harden.py +0 -0
  51. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/capture/lineage.py +0 -0
  52. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/capture/liveness.py +0 -0
  53. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/capture/manifest.py +0 -0
  54. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/capture/paths.py +0 -0
  55. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/capture/verify.py +0 -0
  56. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/cell.py +0 -0
  57. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/chain_token.py +0 -0
  58. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/__init__.py +0 -0
  59. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/_content.py +0 -0
  60. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/_display.py +0 -0
  61. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/_gateway_client.py +0 -0
  62. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/add.py +0 -0
  63. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/bench.py +0 -0
  64. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/board.py +0 -0
  65. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/board_merge_check.py +0 -0
  66. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/brain.py +0 -0
  67. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/cell.py +0 -0
  68. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/cell_probe.py +0 -0
  69. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/cell_selfcheck.py +0 -0
  70. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/channel.py +0 -0
  71. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/chat.py +0 -0
  72. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/codex_hook_output.py +0 -0
  73. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/codex_waker.py +0 -0
  74. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/compress.py +0 -0
  75. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/dreaming.py +0 -0
  76. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/event.py +0 -0
  77. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/gateway.py +0 -0
  78. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/group.py +0 -0
  79. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/guide.py +0 -0
  80. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/hook_interpreter.py +0 -0
  81. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/hook_output.py +0 -0
  82. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/import_session.py +0 -0
  83. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/init.py +0 -0
  84. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/install_codex_hooks.py +0 -0
  85. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/install_hook.py +0 -0
  86. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/install_multiplexer.py +0 -0
  87. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/install_opencode_plugin.py +0 -0
  88. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/install_wake_hook.py +0 -0
  89. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/lane.py +0 -0
  90. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/memory_sync.py +0 -0
  91. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/okf_links.py +0 -0
  92. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/peer_reply_drain.py +0 -0
  93. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/postcompact_hook_output.py +0 -0
  94. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/protocol_handler.py +0 -0
  95. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/ratify.py +0 -0
  96. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/schedule.py +0 -0
  97. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/security.py +0 -0
  98. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/service.py +0 -0
  99. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/spawn.py +0 -0
  100. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/timeline.py +0 -0
  101. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/commands/version.py +0 -0
  102. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/compress/__init__.py +0 -0
  103. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/compress/levers.py +0 -0
  104. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/compress/marker.py +0 -0
  105. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/compress/verify.py +0 -0
  106. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/console_safe.py +0 -0
  107. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/delivery_queue.py +0 -0
  108. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dm_frame.py +0 -0
  109. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dreaming/__init__.py +0 -0
  110. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dreaming/candidates.py +0 -0
  111. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dreaming/clone.py +0 -0
  112. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dreaming/enrich.py +0 -0
  113. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dreaming/index_check.py +0 -0
  114. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dreaming/notify.py +0 -0
  115. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dreaming/organize.py +0 -0
  116. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dreaming/probes.py +0 -0
  117. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dreaming/report.py +0 -0
  118. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dreaming/run.py +0 -0
  119. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dreaming/slm.py +0 -0
  120. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dreaming/transcripts.py +0 -0
  121. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/dreaming/verify.py +0 -0
  122. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/gateway/__init__.py +0 -0
  123. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/gateway/feature_registry.py +0 -0
  124. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/gateway/lanes_control.py +0 -0
  125. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/gateway/schema.sql +0 -0
  126. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/gateway/services_control.py +0 -0
  127. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/gateway_default.py +0 -0
  128. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/gh_identity.py +0 -0
  129. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/guide/GUIDE.md +0 -0
  130. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/main.py +0 -0
  131. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/multiplexer.py +0 -0
  132. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/orphan_daemons.py +0 -0
  133. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/pane_probe.py +0 -0
  134. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/parsers/__init__.py +0 -0
  135. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/parsers/claude.py +0 -0
  136. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/payloads/opencode/plugin.js +0 -0
  137. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/payloads/postcompact/_shim.cmd +0 -0
  138. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/payloads/postcompact/postcompact-recall-grok.sh +0 -0
  139. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/payloads/postcompact/postcompact-recall.sh +0 -0
  140. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/payloads/postcompact/posttooluse-emit-antigravity.sh +0 -0
  141. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/payloads/postcompact/posttooluse-emit-claude.sh +0 -0
  142. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/payloads/postcompact/posttooluse-emit-grok.sh +0 -0
  143. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/payloads/postcompact/posttooluse-emit.sh +0 -0
  144. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/payloads/postcompact/posttooluse-recall.sh +0 -0
  145. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/payloads/postcompact/precompact-flag.sh +0 -0
  146. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/payloads/postcompact/preinvocation-recall-antigravity.sh +0 -0
  147. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/payloads/postcompact/sessionstart-recall.sh +0 -0
  148. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/peer_executor.py +0 -0
  149. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/peer_executor_windows.py +0 -0
  150. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/peer_reconciliation.py +0 -0
  151. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/peer_reply_outbox.py +0 -0
  152. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/peer_service_host.py +0 -0
  153. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/peer_service_payload.py +0 -0
  154. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/peer_service_reply.py +0 -0
  155. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/peer_staging.py +0 -0
  156. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/query_filters.py +0 -0
  157. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/scripts/__init__.py +0 -0
  158. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/scripts/dm_notify_filter.py +0 -0
  159. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/scripts/ensure_monitor.sh +0 -0
  160. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/scripts/install_codex_waker_windows.ps1 +0 -0
  161. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/scripts/install_monitor_task_windows.ps1 +0 -0
  162. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/scripts/wake_watchdog.py +0 -0
  163. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/service/__init__.py +0 -0
  164. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/service/app.py +0 -0
  165. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/service/providers.py +0 -0
  166. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/session_bridge.py +0 -0
  167. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/skills/i-have-adhd/LICENSE +0 -0
  168. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/skills/i-have-adhd/SKILL.md +0 -0
  169. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/source_text.py +0 -0
  170. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/stall_alert.py +0 -0
  171. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/codex-waker.default +0 -0
  172. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/peer-reply-drain.default +0 -0
  173. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/swarph-codex-outbox@.service +0 -0
  174. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/swarph-codex-outbox@.timer +0 -0
  175. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/swarph-codex-waker@.service +0 -0
  176. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/swarph-codex-waker@.timer +0 -0
  177. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/swarph-monitor-reexec.path +0 -0
  178. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/swarph-monitor-reexec.service +0 -0
  179. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/swarph-monitor@.service +0 -0
  180. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/swarph-peer-reply-drain@.service +0 -0
  181. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/swarph-peer-reply-drain@.timer +0 -0
  182. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/swarph-watchdog.default +0 -0
  183. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/swarph-watchdog.service +0 -0
  184. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/systemd/swarph-watchdog.timer +0 -0
  185. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/timeline_paths.py +0 -0
  186. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli/tokens.py +0 -0
  187. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli.egg-info/dependency_links.txt +0 -0
  188. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli.egg-info/entry_points.txt +0 -0
  189. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli.egg-info/requires.txt +0 -0
  190. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/src/swarph_cli.egg-info/top_level.txt +0 -0
  191. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_124_register_merge.py +0 -0
  192. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_126_pending_from_complete.py +0 -0
  193. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_132_ensure_monitor_state_dir.py +0 -0
  194. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_138_memory_navigate.py +0 -0
  195. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_139_tool_probe.py +0 -0
  196. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_183_card_anchor.py +0 -0
  197. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_184_notify_honesty.py +0 -0
  198. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_201_win32_bash_refusal.py +0 -0
  199. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_243_onboard_per_peer_token.py +0 -0
  200. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_307_task4_ask_reply.py +0 -0
  201. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_312_codegraph_fuzzy_verb.py +0 -0
  202. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_319_refusal_exit_codes.py +0 -0
  203. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_323_mistral_backend.py +0 -0
  204. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_332_report_organize_findings.py +0 -0
  205. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_356_query_filters.py +0 -0
  206. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_397_gh_identity_router.py +0 -0
  207. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_397_router_preflight.py +0 -0
  208. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_467b_onboard_operator_credential.py +0 -0
  209. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_523_guide.py +0 -0
  210. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_524_conftest_hermeticity.py +0 -0
  211. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_532_accept_flag.py +0 -0
  212. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_535_version_capability.py +0 -0
  213. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_546_default_gateway.py +0 -0
  214. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_547_verbs_from_registry.py +0 -0
  215. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_548_gateway_remainder.py +0 -0
  216. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_552_codegraph_gateway.py +0 -0
  217. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_555_relay_row_shape.py +0 -0
  218. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_556_relay_freshness.py +0 -0
  219. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_559_edges_truncated.py +0 -0
  220. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_564_bootstrap_first_peer.py +0 -0
  221. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_578_no_machine_specific_host_defaults.py +0 -0
  222. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_579_register_bootstrap_message.py +0 -0
  223. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_591_cli_step_graph.py +0 -0
  224. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_644_monitor_supervision.py +0 -0
  225. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_648_install_unit.py +0 -0
  226. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_654_reexec.py +0 -0
  227. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_656_owned_slm.py +0 -0
  228. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_684_dreaming_verb.py +0 -0
  229. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_689_pkg_version_order.py +0 -0
  230. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_716_timeline_one_path.py +0 -0
  231. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_724_ps1_ascii_or_bom.py +0 -0
  232. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_725_stdio_reconfigure.py +0 -0
  233. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_729_dm_once.py +0 -0
  234. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_729_wake_watchdog.py +0 -0
  235. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_734_dreaming_enrich_degrade.py +0 -0
  236. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_735_dm_mcp_tools.py +0 -0
  237. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_740_edit_project.py +0 -0
  238. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_762_cards_edit_priority.py +0 -0
  239. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_764_enrich_collapse.py +0 -0
  240. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_801_confirm_flow_cli.py +0 -0
  241. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_802_stage_history.py +0 -0
  242. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_825_codegraph_hook_noise.py +0 -0
  243. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_825_install_posttooluse_only.py +0 -0
  244. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_825_remaining_cap_shred_bind.py +0 -0
  245. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_829_counterfactual_column.py +0 -0
  246. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_830_hook_binding_version.py +0 -0
  247. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_84_cli_labels.py +0 -0
  248. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_866_doctrine_guide.py +0 -0
  249. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_872_identity_refuses_not_warns.py +0 -0
  250. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_874_source_text.py +0 -0
  251. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_888_opencode_data_dir_can_fail.py +0 -0
  252. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_937_dreaming_notify.py +0 -0
  253. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_938_organize_line_limit.py +0 -0
  254. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_941_bench_backends.py +0 -0
  255. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_941_harness_342.py +0 -0
  256. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_945_same_line_pairing.py +0 -0
  257. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_955_prompt_audit.py +0 -0
  258. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_957_auth_http.py +0 -0
  259. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_959_venv_interpreter.py +0 -0
  260. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_960_channel.py +0 -0
  261. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_963_plugin_manifest.py +0 -0
  262. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_964_channel_cell.py +0 -0
  263. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_965_mesh_wait.py +0 -0
  264. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_975_channel_hop.py +0 -0
  265. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_add_security_gate.py +0 -0
  266. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_artifact_add.py +0 -0
  267. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_artifact_hash.py +0 -0
  268. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_artifact_lib.py +0 -0
  269. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_artifact_mcp.py +0 -0
  270. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_artifact_skill.py +0 -0
  271. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_artifact_tool.py +0 -0
  272. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_artifact_uri.py +0 -0
  273. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_bench_backends.py +0 -0
  274. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_bench_command.py +0 -0
  275. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_bench_pack.py +0 -0
  276. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_bench_prices.py +0 -0
  277. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_bench_quality.py +0 -0
  278. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_bench_runner.py +0 -0
  279. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_bench_validate.py +0 -0
  280. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_board_card_thread.py +0 -0
  281. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_board_command.py +0 -0
  282. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_board_merge_check.py +0 -0
  283. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_board_obligation_close.py +0 -0
  284. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_brain_ask_command.py +0 -0
  285. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_brain_command.py +0 -0
  286. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_caller_meta_guard.py +0 -0
  287. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_capture_lineage.py +0 -0
  288. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_capture_liveness.py +0 -0
  289. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_capture_manifest.py +0 -0
  290. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_capture_paths.py +0 -0
  291. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_capture_security.py +0 -0
  292. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_cell_command_dispatch.py +0 -0
  293. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_cell_harden.py +0 -0
  294. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_cell_loader.py +0 -0
  295. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_cell_selfcheck.py +0 -0
  296. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_cell_verify.py +0 -0
  297. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_chain_token.py +0 -0
  298. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_channel_command.py +0 -0
  299. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_channel_poll_never_breaks_dms.py +0 -0
  300. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_channel_post.py +0 -0
  301. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_channel_wake_policy_filter.py +0 -0
  302. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_chat_command.py +0 -0
  303. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_claude_parser.py +0 -0
  304. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_claude_tmux_template.py +0 -0
  305. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_codegraph_caller_scope.py +0 -0
  306. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_codegraph_command.py +0 -0
  307. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_codegraph_hook.py +0 -0
  308. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_codegraph_mcp.py +0 -0
  309. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_codex_waker.py +0 -0
  310. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_compress_caller_convention.py +0 -0
  311. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_compress_command.py +0 -0
  312. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_compress_levers.py +0 -0
  313. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_compress_marker.py +0 -0
  314. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_compress_verify.py +0 -0
  315. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_console_encoding_e2e.py +0 -0
  316. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_content_composition.py +0 -0
  317. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_cursor_membrane.py +0 -0
  318. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_daemon_command.py +0 -0
  319. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_daemon_console_encoding.py +0 -0
  320. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_daemon_delivery.py +0 -0
  321. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_delivery_queue.py +0 -0
  322. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_display_sanitize.py +0 -0
  323. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_ensure_monitor_no_peer_default.py +0 -0
  324. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_event_emit.py +0 -0
  325. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_feature_to_uri.py +0 -0
  326. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_gateway_brain.py +0 -0
  327. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_gateway_client.py +0 -0
  328. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_gateway_command.py +0 -0
  329. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_gateway_message_idempotency.py +0 -0
  330. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_gh_route_doctor_mesh_name.py +0 -0
  331. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_group_command.py +0 -0
  332. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_guide_commands_parse.py +0 -0
  333. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_guide_selfcheck.py +0 -0
  334. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_heartbeat_check.py +0 -0
  335. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_highlight_command.py +0 -0
  336. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_hook_output.py +0 -0
  337. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_hooks_activity_marker.py +0 -0
  338. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_hooks_add.py +0 -0
  339. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_hooks_bundle.py +0 -0
  340. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_hooks_init.py +0 -0
  341. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_hooks_legacy_generation_removal.py +0 -0
  342. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_hooks_lifecycle.py +0 -0
  343. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_hooks_merge.py +0 -0
  344. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_hooks_verify.py +0 -0
  345. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_hooks_win32_bash_wrapper.py +0 -0
  346. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_hooks_win32_command_path.py +0 -0
  347. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_import_command.py +0 -0
  348. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_inbox_identity_provenance.py +0 -0
  349. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_init_command.py +0 -0
  350. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_init_provider_menu.py +0 -0
  351. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_install_codex_hooks.py +0 -0
  352. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_install_hook.py +0 -0
  353. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_install_multiplexer_command.py +0 -0
  354. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_install_postcompact_hook.py +0 -0
  355. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_install_wake_hook.py +0 -0
  356. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_lane_command.py +0 -0
  357. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_main.py +0 -0
  358. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_main_unknown_verb_guard.py +0 -0
  359. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_mcp_missing_hint.py +0 -0
  360. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_mcp_server.py +0 -0
  361. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_memory_command.py +0 -0
  362. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_memory_emit_snippet.py +0 -0
  363. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_memory_gateway.py +0 -0
  364. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_memory_sync.py +0 -0
  365. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_memory_sync_membrane.py +0 -0
  366. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_mesh_command.py +0 -0
  367. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_mesh_inbox_mark_read.py +0 -0
  368. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_mesh_inbox_sanitize.py +0 -0
  369. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_mesh_originate_thread_623.py +0 -0
  370. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_mesh_send_unknown_peer.py +0 -0
  371. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_mesh_sidecar_cursor_decoupled.py +0 -0
  372. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_mesh_sidecar_wake_survives_read.py +0 -0
  373. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_meta_edge_identity.py +0 -0
  374. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_monitor_channel_poll.py +0 -0
  375. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_monitor_cli.py +0 -0
  376. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_monitor_daemon_collision.py +0 -0
  377. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_monitor_self_name_verification.py +0 -0
  378. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_monitor_state_split.py +0 -0
  379. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_multiplexer.py +0 -0
  380. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_muse_membrane.py +0 -0
  381. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_muse_own_cli.py +0 -0
  382. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_obligation_close_is_surfaced.py +0 -0
  383. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_okf_links.py +0 -0
  384. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_onboard_command.py +0 -0
  385. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_opencode_membrane.py +0 -0
  386. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_opencode_plugin.py +0 -0
  387. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_orphan_daemons.py +0 -0
  388. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_packaged_artifacts_exist.py +0 -0
  389. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_packaged_skills.py +0 -0
  390. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_peer_executor.py +0 -0
  391. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_peer_executor_windows.py +0 -0
  392. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_peer_reply_drain_command.py +0 -0
  393. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_peer_reply_drain_supervisor.py +0 -0
  394. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_peer_reply_outbox.py +0 -0
  395. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_peer_reply_transport.py +0 -0
  396. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_peer_service_e2e.py +0 -0
  397. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_peer_service_host.py +0 -0
  398. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_peer_service_payload.py +0 -0
  399. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_peer_service_reply.py +0 -0
  400. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_process_liveness.py +0 -0
  401. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_protocol_handler.py +0 -0
  402. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_providers_isolation.py +0 -0
  403. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_ratify_command.py +0 -0
  404. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_readme_claims_no_gateway_default.py +0 -0
  405. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_repl_caller_convention.py +0 -0
  406. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_schedule_command.py +0 -0
  407. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_schedule_create_contract.py +0 -0
  408. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_security.py +0 -0
  409. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_service_app.py +0 -0
  410. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_service_command.py +0 -0
  411. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_service_providers.py +0 -0
  412. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_session_bridge_inject.py +0 -0
  413. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_session_bridge_probe.py +0 -0
  414. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_session_bridge_resolve.py +0 -0
  415. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_session_path_role_gate.py +0 -0
  416. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_shipped_units_match_the_cli.py +0 -0
  417. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_smoke_chat.py +0 -0
  418. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_smoke_one_shot.py +0 -0
  419. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_smoke_phase_5_5.py +0 -0
  420. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_spawn_base_hoist.py +0 -0
  421. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_spawn_command.py +0 -0
  422. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_spawn_identity_stamp.py +0 -0
  423. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_spawn_live_pin.py +0 -0
  424. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_spawn_mitosis_lineage.py +0 -0
  425. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_spawn_tmux_session.py +0 -0
  426. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_spawn_windows_relaunch.py +0 -0
  427. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_stall_alert.py +0 -0
  428. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_subprocess_decode_encoding.py +0 -0
  429. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_timeline_command.py +0 -0
  430. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_tmux_wake_session_reanchor.py +0 -0
  431. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_tmux_wake_stale.py +0 -0
  432. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_token_file_one_parser.py +0 -0
  433. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_token_precedence_explicit_first.py +0 -0
  434. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_unified_token_resolver.py +0 -0
  435. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_version_command.py +0 -0
  436. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_version_consistency.py +0 -0
  437. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_vibe_membrane.py +0 -0
  438. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_watchdog_dm_wake.py +0 -0
  439. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_watchdog_dm_wake_cooldown.py +0 -0
  440. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_watchdog_dm_wake_wiring.py +0 -0
  441. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_watchdog_emit_health.py +0 -0
  442. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_watchdog_install_flags.py +0 -0
  443. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_watchdog_model_rung.py +0 -0
  444. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_watchdog_stale_peers.py +0 -0
  445. {swarph_cli-0.68.2 → swarph_cli-0.69.1}/tests/test_windows_waker_installer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: swarph-cli
3
- Version: 0.68.2
3
+ Version: 0.69.1
4
4
  Summary: The `swarph` binary — a multi-LLM CLI and mesh-gateway client + bundled server (`swarph gateway`): one-shot prompts across providers, interactive `chat`, multi-provider `spawn` (claude/codex/antigravity via a ProviderMembrane with subprocess billing-scrub), `mesh` send/inbox/register, `brain-ask` over the swarph-brain (gbrain) semantic memory, git-backed `assisted_memory`, per-invocation `gh` identity routing, a silent DM-wake hook, session `import`, and a stranded-session `watchdog`.
5
5
  Author: Pierre Samson, Claude Opus
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "swarph-cli"
7
- version = "0.68.2"
7
+ version = "0.69.1"
8
8
  description = "The `swarph` binary — a multi-LLM CLI and mesh-gateway client + bundled server (`swarph gateway`): one-shot prompts across providers, interactive `chat`, multi-provider `spawn` (claude/codex/antigravity via a ProviderMembrane with subprocess billing-scrub), `mesh` send/inbox/register, `brain-ask` over the swarph-brain (gbrain) semantic memory, git-backed `assisted_memory`, per-invocation `gh` identity routing, a silent DM-wake hook, session `import`, and a stranded-session `watchdog`."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -16,6 +16,6 @@ The architecture splits CLI from substrate so:
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- __version__ = "0.68.2"
19
+ __version__ = "0.69.1"
20
20
 
21
21
  __all__ = ["__version__"]
@@ -13,6 +13,7 @@ import threading
13
13
  import time
14
14
  from pathlib import Path
15
15
 
16
+ from swarph_cli import identity
16
17
  from swarph_cli.dm_frame import FIRST_START_GRACE_S, created_within, frame_text, rows
17
18
  from swarph_cli.scripts.dm_notify_filter import is_real_dm
18
19
 
@@ -35,8 +36,8 @@ def channel_opted_in() -> bool:
35
36
 
36
37
  def channel_serves() -> bool:
37
38
  """Only the cell spawn named in SWARPH_CHANNEL_CELL may poll."""
38
- self_name = os.environ.get("SWARPH_SELF") or ""
39
- named = os.environ.get("SWARPH_CHANNEL_CELL") or ""
39
+ self_name = identity.declared(env=identity.SELF_ONLY)[0] or ""
40
+ named = (os.environ.get("SWARPH_CHANNEL_CELL") or "").strip()
40
41
  return channel_opted_in() and bool(named) and named == self_name
41
42
 
42
43
 
@@ -290,7 +291,7 @@ def serve(chan: Channel) -> None:
290
291
 
291
292
 
292
293
  def main(argv: list[str] | None = None) -> int:
293
- cell = os.environ.get("SWARPH_SELF") or ""
294
+ cell = identity.declared(env=identity.SELF_ONLY)[0] or ""
294
295
  if not cell:
295
296
  print("swarph channel: SWARPH_SELF is unset; refusing to start", file=sys.stderr)
296
297
  return 2
@@ -31,6 +31,7 @@ import os
31
31
  import sys
32
32
  import urllib.request
33
33
 
34
+ from swarph_cli import identity
34
35
  from swarph_cli import tokens
35
36
  from pathlib import Path
36
37
  from typing import Optional
@@ -108,22 +109,27 @@ def _peer_token_path(self_name: str) -> Path:
108
109
  return Path.home() / ".config" / "swarph" / f"{self_name}.peer_token"
109
110
 
110
111
 
111
- # The fallback is ANOTHER CELL'S NAME. Harmless on lab-ovh, silently wrong everywhere
112
- # else — and it is what made the cold-env failure report a TOKEN fault: with SWARPH_SELF
113
- # unset the cell hunts lab-ovh.peer_token, finds nothing, and blames the credential.
114
- # MEASURED 2026-07-29 on 6 of 6 cells (droplet isolated it: adding ONLY the two env vars,
115
- # changing NO token, turned exit 2 into exit 0 at 1.00).
116
- # The default is KEPT (removing it would break callers that rely on it) and ANNOUNCED.
117
- _DEFAULT_SELF = "lab-ovh"
112
+ # card #402: there is NO default identity. The old fallback was ANOTHER CELL'S NAME
113
+ # ("lab-ovh"): harmless on lab-ovh, silently wrong everywhere else, and it made the
114
+ # cold-env failure report a TOKEN fault (with SWARPH_SELF unset the cell hunted
115
+ # lab-ovh.peer_token, found nothing and blamed the credential; measured 2026-07-29 on
116
+ # 6 of 6 cells). An undeclared cell now does no peer-token lookup at all: brain reads
117
+ # still work from GBRAIN_TOKEN / SWARPH_BRAIN_TOKEN / --token-file, and the gateway
118
+ # path, which needs the cell's own peer token, refuses with the missing variable named.
119
+ # The identity picks a CREDENTIAL file here, so this verb reads SWARPH_SELF (and its
120
+ # legacy SWARPH_NODE alias) only, like the mesh verbs: an ambient SWARPH_CELL, which
121
+ # psmux leaks from the spawning environment (#538), must not select another cell's
122
+ # peer token.
123
+ _IDENTITY_ENV = identity.SELF_ONLY + identity.NODE_ALIAS
118
124
 
119
125
 
120
- def _self_name() -> str:
121
- return os.environ.get("SWARPH_SELF") or os.environ.get("SWARPH_NODE") or _DEFAULT_SELF
126
+ def _self_name() -> Optional[str]:
127
+ return identity.declared(env=_IDENTITY_ENV)[0]
122
128
 
123
129
 
124
- def _self_name_is_defaulted() -> bool:
125
- """True when no env named this cell and we fell back to _DEFAULT_SELF."""
126
- return not (os.environ.get("SWARPH_SELF") or os.environ.get("SWARPH_NODE"))
130
+ def _self_name_is_undeclared() -> bool:
131
+ """True when no flag or env names this cell. There is no fallback name."""
132
+ return _self_name() is None
127
133
 
128
134
 
129
135
  def env_diagnosis() -> str:
@@ -135,10 +141,9 @@ def env_diagnosis() -> str:
135
141
  a sourced profile, a bashrc or a settings.json `env` block never applies.
136
142
  """
137
143
  bits = []
138
- if _self_name_is_defaulted():
139
- bits.append(f"SWARPH_SELF unset — defaulting to {_DEFAULT_SELF!r}, which is "
140
- f"probably NOT this cell (so any peer-token lookup will hunt the "
141
- f"wrong file)")
144
+ if _self_name_is_undeclared():
145
+ bits.append("SWARPH_SELF unset — no cell identity is declared, so no peer-token "
146
+ "lookup is attempted (there is no default identity; card #402)")
142
147
  if not os.environ.get("SWARPH_BRAIN_GATEWAY"):
143
148
  bits.append("SWARPH_BRAIN_GATEWAY unset — falling back to a direct brain "
144
149
  "connection, which only works where the brain service is reachable "
@@ -167,8 +172,8 @@ def _resolve_token(token_file: Optional[str], self_name: str) -> Optional[str]:
167
172
  reviewing #190, and it is the sharpest kind of catch: I had noticed the
168
173
  hazard, written a comment about it, and not handled it.
169
174
 
170
- `_self_name()` NEVER returns empty — it falls back to _DEFAULT_SELF
171
- ("lab-ovh"). So `bool(self_name)` is always true here, and passing that as
175
+ `_self_name()` used to NEVER return empty — it fell back to a default peer
176
+ name ("lab-ovh"; removed by card #402). So `bool(self_name)` was always true, and passing that as
172
177
  identity_is_explicit would promote `lab-ovh.peer_token` — ANOTHER CELL'S
173
178
  CREDENTIAL — above GBRAIN_TOKEN on every invocation where nothing named the
174
179
  cell. The comment above already says why that fallback is dangerous
@@ -183,15 +188,15 @@ def _resolve_token(token_file: Optional[str], self_name: str) -> Optional[str]:
183
188
  rather than the resolver, because a unit test at the resolver cannot see
184
189
  what the caller makes reachable.
185
190
 
186
- Explicitness therefore comes from `_self_name_is_defaulted()`, not from
187
- truthiness: a guessed name keeps the old env-first order exactly, and only a
188
- name the operator actually supplied earns precedence over ambient values.
191
+ Explicitness therefore comes from whether a name was DECLARED, not from
192
+ truthiness. Since card #402 nothing is ever guessed, so a declared name is
193
+ the only kind there is, and an undeclared cell gets the env-first order.
189
194
  """
190
195
  res = tokens.resolve_token(
191
196
  self_name or None,
192
197
  token_file,
193
198
  env_keys=("GBRAIN_TOKEN", "SWARPH_BRAIN_TOKEN"),
194
- identity_is_explicit=bool(self_name) and not _self_name_is_defaulted(),
199
+ identity_is_explicit=self_name is not None,
195
200
  )
196
201
  return res.token if res is not None else None
197
202
 
@@ -262,6 +267,12 @@ def run_brain_ask(argv: list) -> int:
262
267
  gw = os.environ.get("SWARPH_BRAIN_GATEWAY")
263
268
  if gw:
264
269
  self_name = _self_name()
270
+ if self_name is None:
271
+ sys.stderr.write(env_diagnosis())
272
+ sys.stderr.write(
273
+ "swarph brain-ask: SWARPH_BRAIN_GATEWAY set but no cell identity is "
274
+ "declared, so there is no peer token to present (set SWARPH_SELF)\n")
275
+ return 2
265
276
  try:
266
277
  peer_token = _peer_token_path(self_name).read_text(encoding="utf-8").strip()
267
278
  except OSError:
@@ -34,6 +34,7 @@ import re
34
34
  import sqlite3
35
35
  import sys
36
36
 
37
+ from swarph_cli import identity
37
38
  from swarph_cli.commands.codegraph_hook import _match_quality
38
39
 
39
40
  DEFAULT_INDEX = os.path.expanduser("~/.swarph/codegraph/index.db")
@@ -68,8 +69,8 @@ DEFAULT_INDEX = os.path.expanduser("~/.swarph/codegraph/index.db")
68
69
  IDENTITY_UNSET = object() # sentinel: argparse default when --caller-cell is omitted
69
70
 
70
71
 
71
- class IdentityNotDeclared(RuntimeError):
72
- """No caller identity was declared and there is no default to fall back to."""
72
+ # card #402: one exception class for "nobody declared this cell", shared by every verb.
73
+ IdentityNotDeclared = identity.IdentityNotDeclared
73
74
 
74
75
 
75
76
  def require_caller_cell(explicit=None, *, verb: str) -> str:
@@ -80,12 +81,10 @@ def require_caller_cell(explicit=None, *, verb: str) -> str:
80
81
  The refusal names the verb and every way to satisfy it, because an error that
81
82
  says only "identity unset" moves the work to the reader.
82
83
  """
83
- if explicit not in (None, IDENTITY_UNSET) and str(explicit).strip():
84
- return str(explicit).strip()
85
- for var in ("SWARPH_SELF", "SWARPH_CELL"):
86
- v = (os.environ.get(var) or "").strip()
87
- if v:
88
- return v
84
+ # card #402: the order lives in swarph_cli.identity, once, for every verb.
85
+ name, _ = identity.declared(None if explicit is IDENTITY_UNSET else explicit)
86
+ if name is not None:
87
+ return name
89
88
  raise IdentityNotDeclared(
90
89
  f"swarph {verb}: NO CALLER IDENTITY DECLARED, and there is no default.\n"
91
90
  f" This used to fall back to 'lab-ovh', which meant an undeclared caller\n"
@@ -33,6 +33,7 @@ import urllib.request
33
33
  from datetime import datetime, timezone
34
34
  from pathlib import Path
35
35
  from typing import Optional
36
+ from swarph_cli import identity
36
37
  from swarph_cli.gateway_default import env_gateway
37
38
 
38
39
  TIMEOUT_S = 6
@@ -477,7 +478,7 @@ def supported_hook_events() -> frozenset:
477
478
  def run_codegraph_hook(argv: Optional[list] = None) -> int:
478
479
  """ALWAYS exits 0 — must never fail a turn."""
479
480
  argv = list(argv or [])
480
- self_name = os.environ.get("SWARPH_SELF", "").strip()
481
+ self_name = identity.declared(env=identity.SELF_ONLY)[0] or ""
481
482
  gateway = env_gateway()
482
483
  for i, a in enumerate(argv):
483
484
  if a == "--as" and i + 1 < len(argv):
@@ -49,6 +49,7 @@ from contextlib import suppress
49
49
  from pathlib import Path
50
50
  from typing import Optional
51
51
 
52
+ from swarph_cli import identity
52
53
  from swarph_cli import session_bridge, stall_alert
53
54
  from swarph_cli.console_safe import print_safe
54
55
  from swarph_cli.delivery_queue import DeliveryQueue
@@ -115,18 +116,14 @@ def _build_parser() -> argparse.ArgumentParser:
115
116
 
116
117
 
117
118
  def _resolve_self_name(arg: Optional[str], state_dir: Path) -> str:
118
- if arg:
119
- return arg
120
- env = os.environ.get("SWARPH_SELF")
121
- if env:
122
- return env
123
- return state_dir.name
119
+ name, _ = identity.declared(arg, env=identity.SELF_ONLY)
120
+ return name if name is not None else state_dir.name
124
121
 
125
122
 
126
123
  def _resolve_state_dir(arg: Optional[str], self_name_arg: Optional[str]) -> Path:
127
124
  if arg:
128
125
  return Path(arg).expanduser()
129
- self_name = self_name_arg or os.environ.get("SWARPH_SELF")
126
+ self_name = identity.declared(self_name_arg, env=identity.SELF_ONLY)[0]
130
127
  if self_name:
131
128
  return Path.home() / "swarph_state" / self_name
132
129
  # Last resort — a self_name is needed to disambiguate; surface error.
@@ -550,7 +547,7 @@ def run_daemon(argv: list[str]) -> int:
550
547
  args = _build_parser().parse_args(argv)
551
548
 
552
549
  # Resolve identity + state path
553
- self_name = args.self_name or os.environ.get("SWARPH_SELF")
550
+ self_name = identity.declared(args.self_name, env=identity.SELF_ONLY)[0]
554
551
  if args.state_dir:
555
552
  state_dir = Path(args.state_dir).expanduser()
556
553
  if not self_name:
@@ -24,6 +24,7 @@ import os
24
24
  import sys
25
25
  from typing import Optional
26
26
 
27
+ from swarph_cli import identity
27
28
  from swarph_cli import gh_identity as ghid
28
29
  from swarph_cli.cell import cells_dir
29
30
  from swarph_cli.console_safe import print_safe
@@ -69,7 +70,7 @@ def run_hook(stdin_text: Optional[str] = None) -> int:
69
70
  # The caller named a credential. #332: an explicit argument is a decision.
70
71
  return _allow_unchanged()
71
72
 
72
- peer = os.environ.get("SWARPH_SELF", "").strip()
73
+ peer = identity.declared(env=identity.SELF_ONLY)[0] or ""
73
74
  try:
74
75
  res = ghid.resolve(peer or None)
75
76
  except ghid.RouterRefusal as exc:
@@ -93,7 +94,7 @@ def run_hook(stdin_text: Optional[str] = None) -> int:
93
94
 
94
95
 
95
96
  def run_show() -> int:
96
- peer = os.environ.get("SWARPH_SELF", "").strip()
97
+ peer = identity.declared(env=identity.SELF_ONLY)[0] or ""
97
98
  try:
98
99
  res = ghid.resolve(peer or None)
99
100
  except ghid.RouterRefusal as exc:
@@ -31,6 +31,7 @@ import sys
31
31
  from datetime import datetime, timezone
32
32
  from pathlib import Path
33
33
 
34
+ from swarph_cli import identity
34
35
  from swarph_cli.commands.mesh import _post_json, _resolve_token
35
36
  from swarph_cli.timeline_paths import timeline_dir
36
37
 
@@ -177,7 +178,12 @@ def _log_via_gateway(gateway: str, cell: str, highlight: str,
177
178
  if memory:
178
179
  body["memory"] = memory
179
180
  try:
180
- token = _resolve_token(cell, token_file)
181
+ # card #402: only a DECLARED identity may select its own peer token over the
182
+ # ambient one. A name guessed from git user.name or the hostname is
183
+ # attribution only: on a shared box it can be ANOTHER cell's name, and its
184
+ # peer token must not be presented as this caller's.
185
+ token = _resolve_token(cell, token_file,
186
+ identity_is_explicit=cell_source in _DECLARED_SOURCES)
181
187
  except RuntimeError as exc:
182
188
  print(_credential_error(cell, cell_source, exc), file=sys.stderr)
183
189
  return 1
@@ -247,6 +253,10 @@ def _is_git_repo(repo: Path) -> bool:
247
253
  return r.returncode == 0 and r.stdout.strip() == "true"
248
254
 
249
255
 
256
+ # Sources that DECLARE an identity (as opposed to guessing one), card #402.
257
+ _DECLARED_SOURCES = ("--cell", "$SWARPH_SELF", "$SWARPH_CELL")
258
+
259
+
250
260
  def _resolve_cell(arg, repo: Path) -> tuple[str, str]:
251
261
  """Return ``(cell, source)``.
252
262
 
@@ -257,12 +267,9 @@ def _resolve_cell(arg, repo: Path) -> tuple[str, str]:
257
267
  """
258
268
  if arg:
259
269
  return _collapse(arg), "--cell"
260
- self_env = os.environ.get("SWARPH_SELF")
261
- if self_env:
262
- return _collapse(self_env), "$SWARPH_SELF"
263
- cell_env = os.environ.get("SWARPH_CELL")
264
- if cell_env:
265
- return _collapse(cell_env), "$SWARPH_CELL"
270
+ name, source = identity.declared()
271
+ if name is not None:
272
+ return _collapse(name), source
266
273
  if _is_git_repo(repo):
267
274
  r = _git(repo, "config", "user.name")
268
275
  if r.returncode == 0 and r.stdout.strip():
@@ -47,6 +47,7 @@ import tempfile
47
47
  from dataclasses import dataclass
48
48
  from pathlib import Path
49
49
 
50
+ from swarph_cli import identity
50
51
  from swarph_cli import __version__ as _SWARPH_CLI_VERSION
51
52
 
52
53
  # Placeholder substituted at install time into generated scripts (#830).
@@ -309,11 +310,7 @@ def touch_activity(argv: list[str] | None = None) -> int:
309
310
  from swarph_cli.cell import discover_cell_in_cwd, load_cell
310
311
  from swarph_cli.commands.watchdog import _resolve_activity_marker_path
311
312
 
312
- role = (
313
- os.environ.get("SWARPH_SELF")
314
- or os.environ.get("SWARPH_CELL")
315
- or "unidentified-cell"
316
- )
313
+ role = identity.or_sentinel()
317
314
  cell_marker = None
318
315
  cell_path = discover_cell_in_cwd()
319
316
  if cell_path is not None:
@@ -59,6 +59,7 @@ from importlib import resources
59
59
  from pathlib import Path
60
60
  from typing import Any, Optional
61
61
 
62
+ from swarph_cli import identity
62
63
  from swarph_cli.cell import _atomic_write_text
63
64
  from swarph_cli.commands.hook_interpreter import hook_interpreter, refuse_unless_importable
64
65
  from swarph_cli.commands.install_wake_hook import _detect_harness
@@ -392,8 +393,7 @@ def run_install_postcompact_hook(argv: Optional[list[str]] = None) -> int:
392
393
  )
393
394
  return 2
394
395
 
395
- cell = args.cell or os.environ.get("SWARPH_SELF") \
396
- or os.environ.get("SWARPH_CELL") or None
396
+ cell = identity.declared(args.cell)[0]
397
397
  memory_dir: Optional[Path] = None
398
398
  if args.memory_dir:
399
399
  memory_dir = Path(os.path.expanduser(args.memory_dir))
@@ -39,6 +39,7 @@ import os
39
39
  import urllib.error
40
40
  import urllib.request
41
41
 
42
+ from swarph_cli import identity
42
43
  from swarph_cli.commands import add
43
44
  from swarph_cli.commands import codegraph
44
45
  from swarph_cli.commands import brain_ask, memory, timeline
@@ -152,7 +153,7 @@ def _codegraph_query(query: str, *, limit: int = 8) -> list[dict]:
152
153
  """Structural code search over the local codegraph index (Task 1).
153
154
 
154
155
  Delegates to :func:`codegraph.structural_query` against the module-level
155
- ``_CODEGRAPH_INDEX`` path, using ``SWARPH_CELL`` (else
156
+ ``_CODEGRAPH_INDEX`` path, using the house identity order (``SWARPH_SELF``, then ``SWARPH_CELL``; else
156
157
  ``codegraph.require_caller_cell``, which REFUSES rather than defaulting) as
157
158
  the A8 caller identity and the
158
159
  default operate-what-you-own allowlist (``allowlist=None``).
@@ -170,8 +171,10 @@ def _codegraph_query(query: str, *, limit: int = 8) -> list[dict]:
170
171
  # authority. require_caller_cell raises IdentityNotDeclared, which the
171
172
  # NEVER-RAISES contract below turns into an empty result — FAIL-CLOSED: the
172
173
  # MCP host gets nothing rather than somebody else's answer.
173
- caller_cell = codegraph.require_caller_cell(
174
- os.environ.get("SWARPH_CELL"), verb="mcp codegraph_query")
174
+ # card #402: SWARPH_CELL used to be passed as the EXPLICIT identity here,
175
+ # so it outranked SWARPH_SELF, the CELL-first order #538 measured posting
176
+ # under another cell's name. The house order now decides.
177
+ caller_cell = codegraph.require_caller_cell(None, verb="mcp codegraph_query")
175
178
  rows = codegraph.structural_query(
176
179
  query,
177
180
  index_path=_CODEGRAPH_INDEX,
@@ -85,6 +85,11 @@ def _via_gateway(op: str, arguments: dict):
85
85
  if not gw:
86
86
  return False, None
87
87
  self_name = brain_ask._self_name()
88
+ if self_name is None:
89
+ # card #402: no default identity, so no peer token to present. OSError keeps
90
+ # run_memory's CLI fail-safe; the text names the variable to set.
91
+ raise OSError("SWARPH_BRAIN_GATEWAY is set but no cell identity is declared, "
92
+ "so there is no peer token to present (set SWARPH_SELF)")
88
93
  peer_token = brain_ask._peer_token_path(self_name).read_text(encoding="utf-8").strip()
89
94
  return True, _gateway_call(gw, peer_token, op, arguments)
90
95
 
@@ -36,6 +36,7 @@ import tempfile
36
36
  from pathlib import Path
37
37
  from typing import Optional
38
38
 
39
+ from swarph_cli import identity
39
40
  from swarph_cli.commands.highlight import _log_via_gateway, _resolve_gateway
40
41
 
41
42
  _SUPPRESS_WINDOW = dt.timedelta(minutes=30)
@@ -137,8 +138,14 @@ def _cell() -> str:
137
138
  # leaks SWARPH_CELL from the spawning environment, so a CELL-first order
138
139
  # posts this cell's highlight under ANOTHER cell's name and token
139
140
  # (measured by cursor-win on the Windows membrane, 2026-08-22).
140
- return (os.environ.get("SWARPH_SELF") or os.environ.get("SWARPH_CELL")
141
- or socket.gethostname())
141
+ return _cell_with_source()[0]
142
+
143
+
144
+ def _cell_with_source() -> tuple:
145
+ name, source = identity.declared()
146
+ if name is not None:
147
+ return name, source
148
+ return socket.gethostname(), "hostname"
142
149
 
143
150
 
144
151
  def run_memory_emit_hook(argv: list[str] | None = None) -> int:
@@ -167,7 +174,9 @@ def run_memory_emit_hook(argv: list[str] | None = None) -> int:
167
174
  gateway = _resolve_gateway(None)
168
175
  if not gateway:
169
176
  return 0 # no gateway configured -> nowhere to emit; silent by design
170
- rc = _log_via_gateway(gateway, _cell(), text, f"[[{slug}]]", None, None)
177
+ cell, cell_source = _cell_with_source()
178
+ rc = _log_via_gateway(gateway, cell, text, f"[[{slug}]]", None, None,
179
+ cell_source=cell_source)
171
180
  if rc == 0:
172
181
  _mark_emitted(slug)
173
182
  except Exception: