swarph-cli 0.72.34__tar.gz → 0.72.36__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 (550) hide show
  1. {swarph_cli-0.72.34/src/swarph_cli.egg-info → swarph_cli-0.72.36}/PKG-INFO +1 -1
  2. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/pyproject.toml +1 -1
  3. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/__init__.py +1 -1
  4. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/bench/backends.py +5 -3
  5. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/board.py +53 -35
  6. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/brain_ask.py +2 -1
  7. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/cell_probe.py +3 -1
  8. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/channel.py +6 -3
  9. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/codegraph_hook.py +2 -1
  10. swarph_cli-0.72.36/src/swarph_cli/commands/commander.py +95 -0
  11. swarph_cli-0.72.36/src/swarph_cli/commands/committee.py +247 -0
  12. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/event.py +2 -0
  13. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/group.py +2 -1
  14. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/highlight.py +19 -6
  15. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/mcp_server.py +3 -2
  16. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/memory_emit_hook.py +6 -2
  17. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/memory_sync.py +17 -3
  18. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/mesh.py +16 -7
  19. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/onboard.py +2 -1
  20. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/ratify.py +2 -2
  21. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/roster.py +5 -3
  22. swarph_cli-0.72.36/src/swarph_cli/commit_trailers.py +31 -0
  23. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dreaming/slm.py +4 -2
  24. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/duplicate_session.py +3 -1
  25. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/gateway/server.py +3 -1
  26. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/guide/GUIDE.md +8 -0
  27. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/main.py +3 -0
  28. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/operator/api.py +7 -1
  29. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/peer_service_reply.py +2 -0
  30. swarph_cli-0.72.36/src/swarph_cli/redact.py +417 -0
  31. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/stall_alert.py +2 -1
  32. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/triage/backend.py +6 -0
  33. {swarph_cli-0.72.34 → swarph_cli-0.72.36/src/swarph_cli.egg-info}/PKG-INFO +1 -1
  34. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli.egg-info/SOURCES.txt +9 -0
  35. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1065_release.py +2 -0
  36. swarph_cli-0.72.36/tests/test_1297_commander.py +60 -0
  37. swarph_cli-0.72.36/tests/test_1301_restart_skew.py +64 -0
  38. swarph_cli-0.72.36/tests/test_1320_commit_trailers.py +56 -0
  39. swarph_cli-0.72.36/tests/test_1321_layered_redaction.py +1072 -0
  40. swarph_cli-0.72.36/tests/test_committee_command.py +160 -0
  41. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/LICENSE +0 -0
  42. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/README.md +0 -0
  43. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/setup.cfg +0 -0
  44. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/__main__.py +0 -0
  45. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/bench/__init__.py +0 -0
  46. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/bench/claude_cli.py +0 -0
  47. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/bench/codex_cli.py +0 -0
  48. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/bench/pack.py +0 -0
  49. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/bench/prices.py +0 -0
  50. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/bench/providers.py +0 -0
  51. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/bench/quality.py +0 -0
  52. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/bench/refresh_prices.py +0 -0
  53. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/bench/rules.py +0 -0
  54. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/bench/runner.py +0 -0
  55. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/bench/signal_score.py +0 -0
  56. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/bench/validate.py +0 -0
  57. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/caller.py +0 -0
  58. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/capture/__init__.py +0 -0
  59. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/capture/harden.py +0 -0
  60. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/capture/lineage.py +0 -0
  61. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/capture/liveness.py +0 -0
  62. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/capture/manifest.py +0 -0
  63. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/capture/paths.py +0 -0
  64. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/capture/verify.py +0 -0
  65. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/cell.py +0 -0
  66. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/chain_token.py +0 -0
  67. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/channel.py +0 -0
  68. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/__init__.py +0 -0
  69. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/_content.py +0 -0
  70. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/_display.py +0 -0
  71. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/_gateway_client.py +0 -0
  72. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/add.py +0 -0
  73. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/bench.py +0 -0
  74. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/board_merge_check.py +0 -0
  75. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/brain.py +0 -0
  76. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/cell.py +0 -0
  77. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/cell_selfcheck.py +0 -0
  78. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/chat.py +0 -0
  79. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/codegraph.py +0 -0
  80. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/codex_hook_output.py +0 -0
  81. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/codex_waker.py +0 -0
  82. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/compress.py +0 -0
  83. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/daemon.py +0 -0
  84. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/dreaming.py +0 -0
  85. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/gateway.py +0 -0
  86. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/gh_route.py +0 -0
  87. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/guide.py +0 -0
  88. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/hook_interpreter.py +0 -0
  89. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/hook_output.py +0 -0
  90. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/hooks.py +0 -0
  91. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/import_session.py +0 -0
  92. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/init.py +0 -0
  93. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/install_codex_hooks.py +0 -0
  94. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/install_hook.py +0 -0
  95. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/install_multiplexer.py +0 -0
  96. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/install_opencode_plugin.py +0 -0
  97. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/install_postcompact_hook.py +0 -0
  98. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/install_wake_hook.py +0 -0
  99. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/lane.py +0 -0
  100. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/memory.py +0 -0
  101. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/monitor.py +0 -0
  102. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/okf_links.py +0 -0
  103. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/peer_reply_drain.py +0 -0
  104. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/postcompact_hook_output.py +0 -0
  105. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/protocol_handler.py +0 -0
  106. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/rowclear_hook.py +0 -0
  107. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/schedule.py +0 -0
  108. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/security.py +0 -0
  109. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/service.py +0 -0
  110. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/spawn.py +0 -0
  111. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/sweep.py +0 -0
  112. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/timeline.py +0 -0
  113. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/triage.py +0 -0
  114. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/version.py +0 -0
  115. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/wake_hook_output.py +0 -0
  116. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/commands/watchdog.py +0 -0
  117. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/compress/__init__.py +0 -0
  118. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/compress/levers.py +0 -0
  119. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/compress/marker.py +0 -0
  120. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/compress/verify.py +0 -0
  121. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/console_safe.py +0 -0
  122. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/delivery_queue.py +0 -0
  123. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dm_frame.py +0 -0
  124. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dreaming/__init__.py +0 -0
  125. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dreaming/candidates.py +0 -0
  126. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dreaming/clone.py +0 -0
  127. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dreaming/enrich.py +0 -0
  128. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dreaming/index_check.py +0 -0
  129. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dreaming/notify.py +0 -0
  130. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dreaming/organize.py +0 -0
  131. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dreaming/probes.py +0 -0
  132. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dreaming/report.py +0 -0
  133. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dreaming/run.py +0 -0
  134. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dreaming/transcripts.py +0 -0
  135. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/dreaming/verify.py +0 -0
  136. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/gateway/__init__.py +0 -0
  137. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/gateway/feature_registry.py +0 -0
  138. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/gateway/lanes_control.py +0 -0
  139. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/gateway/schema.sql +0 -0
  140. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/gateway/services_control.py +0 -0
  141. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/gateway_default.py +0 -0
  142. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/gh_identity.py +0 -0
  143. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/identity.py +0 -0
  144. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/launchd/swarph-codex-outbox.plist +0 -0
  145. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/launchd/swarph-codex-outbox.timer.plist +0 -0
  146. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/launchd/swarph-monitor.plist +0 -0
  147. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/launchd/swarph-watchdog.plist +0 -0
  148. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/launchd/swarph-watchdog.timer.plist +0 -0
  149. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/launchd_render.py +0 -0
  150. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/multiplexer.py +0 -0
  151. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/operator/__init__.py +0 -0
  152. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/operator/__main__.py +0 -0
  153. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/operator/cli.py +0 -0
  154. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/operator/config.py +0 -0
  155. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/operator/fmt.py +0 -0
  156. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/orphan_daemons.py +0 -0
  157. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/pane_probe.py +0 -0
  158. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/parsers/__init__.py +0 -0
  159. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/parsers/claude.py +0 -0
  160. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/payloads/opencode/plugin.js +0 -0
  161. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/payloads/postcompact/_shim.cmd +0 -0
  162. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/payloads/postcompact/postcompact-recall-grok.sh +0 -0
  163. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/payloads/postcompact/postcompact-recall.sh +0 -0
  164. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/payloads/postcompact/posttooluse-emit-antigravity.sh +0 -0
  165. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/payloads/postcompact/posttooluse-emit-claude.sh +0 -0
  166. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/payloads/postcompact/posttooluse-emit-grok.sh +0 -0
  167. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/payloads/postcompact/posttooluse-emit.sh +0 -0
  168. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/payloads/postcompact/posttooluse-recall.sh +0 -0
  169. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/payloads/postcompact/precompact-flag.sh +0 -0
  170. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/payloads/postcompact/preinvocation-recall-antigravity.sh +0 -0
  171. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/payloads/postcompact/sessionstart-recall.sh +0 -0
  172. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/peer_executor.py +0 -0
  173. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/peer_executor_windows.py +0 -0
  174. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/peer_reconciliation.py +0 -0
  175. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/peer_reply_outbox.py +0 -0
  176. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/peer_service_host.py +0 -0
  177. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/peer_service_payload.py +0 -0
  178. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/peer_staging.py +0 -0
  179. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/query_filters.py +0 -0
  180. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/quota_sync.py +0 -0
  181. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/rowclear.py +0 -0
  182. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/scripts/__init__.py +0 -0
  183. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/scripts/dm_notify_filter.py +0 -0
  184. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/scripts/ensure_monitor.sh +0 -0
  185. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/scripts/install_codex_waker_windows.ps1 +0 -0
  186. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/scripts/install_monitor_task_windows.ps1 +0 -0
  187. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/scripts/wake_watchdog.py +0 -0
  188. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/scrub.py +0 -0
  189. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/service/__init__.py +0 -0
  190. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/service/app.py +0 -0
  191. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/service/providers.py +0 -0
  192. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/session_bridge.py +0 -0
  193. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/skills/i-have-adhd/LICENSE +0 -0
  194. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/skills/i-have-adhd/SKILL.md +0 -0
  195. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/source_text.py +0 -0
  196. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/codex-waker.default +0 -0
  197. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/peer-reply-drain.default +0 -0
  198. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-codex-outbox@.service +0 -0
  199. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-codex-outbox@.timer +0 -0
  200. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-codex-waker@.service +0 -0
  201. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-codex-waker@.timer +0 -0
  202. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-monitor-reexec.path +0 -0
  203. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-monitor-reexec.service +0 -0
  204. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-monitor@.service +0 -0
  205. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-peer-reply-drain@.service +0 -0
  206. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-peer-reply-drain@.timer +0 -0
  207. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-stuck-sweep.service +0 -0
  208. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-stuck-sweep.timer +0 -0
  209. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-triage.service +0 -0
  210. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-triage.timer +0 -0
  211. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-watchdog.default +0 -0
  212. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-watchdog.service +0 -0
  213. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/systemd/swarph-watchdog.timer +0 -0
  214. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/the_ten.py +0 -0
  215. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/timeline_paths.py +0 -0
  216. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/tokens.py +0 -0
  217. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/triage/__init__.py +0 -0
  218. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/triage/job.py +0 -0
  219. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/triage/owners.json +0 -0
  220. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/triage/router.py +0 -0
  221. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/triage/rows.py +0 -0
  222. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli/triage/sensor.py +0 -0
  223. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli.egg-info/dependency_links.txt +0 -0
  224. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli.egg-info/entry_points.txt +0 -0
  225. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli.egg-info/requires.txt +0 -0
  226. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/src/swarph_cli.egg-info/top_level.txt +0 -0
  227. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1006_board_publisher.py +0 -0
  228. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1006_session_board.py +0 -0
  229. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1010_strand_only.py +0 -0
  230. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1013_spawn_channel.py +0 -0
  231. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1017_muse_tui.py +0 -0
  232. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1034_copy_mode.py +0 -0
  233. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1050_surrogate_wake.py +0 -0
  234. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1052_opencode_deaf.py +0 -0
  235. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1059_watchdog_unread_env.py +0 -0
  236. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1061_roster_cli.py +0 -0
  237. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1064_stuck_sweep.py +0 -0
  238. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1066_quiet_wakes.py +0 -0
  239. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1068_structured_accept_cli.py +0 -0
  240. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1071_quota_sync.py +0 -0
  241. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1073_triage.py +0 -0
  242. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1073_triage_board.py +0 -0
  243. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1073_wheel_install.py +0 -0
  244. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1075_task_cli.py +0 -0
  245. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1083_openai_decisions.py +0 -0
  246. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1144_cell_yaml_github.py +0 -0
  247. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1197_commander_taps.py +0 -0
  248. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1203_swarph_me_refusal.py +0 -0
  249. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1206_offer_question.py +0 -0
  250. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1214_egress.py +0 -0
  251. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1219_egress_probe.py +0 -0
  252. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1221_quota_windows.py +0 -0
  253. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1222_maybe_start_cap.py +0 -0
  254. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1228_quota_reach.py +0 -0
  255. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1243_the_ten.py +0 -0
  256. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1248_ship_price_table.py +0 -0
  257. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_124_register_merge.py +0 -0
  258. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1250_price_cache.py +0 -0
  259. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1256_commander_wake.py +0 -0
  260. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1261_mcp_install.py +0 -0
  261. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1262_wake_followups.py +0 -0
  262. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1265_wake_note.py +0 -0
  263. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1269_triage_label.py +0 -0
  264. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_126_pending_from_complete.py +0 -0
  265. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1278_dreaming_reach.py +0 -0
  266. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_1286_dm_unread_cursor.py +0 -0
  267. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_132_ensure_monitor_state_dir.py +0 -0
  268. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_138_memory_navigate.py +0 -0
  269. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_139_tool_probe.py +0 -0
  270. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_183_card_anchor.py +0 -0
  271. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_184_notify_honesty.py +0 -0
  272. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_201_win32_bash_refusal.py +0 -0
  273. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_243_onboard_per_peer_token.py +0 -0
  274. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_307_task4_ask_reply.py +0 -0
  275. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_312_codegraph_fuzzy_verb.py +0 -0
  276. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_319_refusal_exit_codes.py +0 -0
  277. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_323_mistral_backend.py +0 -0
  278. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_332_report_organize_findings.py +0 -0
  279. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_356_query_filters.py +0 -0
  280. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_397_gh_identity_router.py +0 -0
  281. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_397_router_preflight.py +0 -0
  282. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_402_one_identity_resolver.py +0 -0
  283. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_432_rowclear.py +0 -0
  284. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_467b_onboard_operator_credential.py +0 -0
  285. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_472_register_caller_binding.py +0 -0
  286. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_484_codex_queue_sink.py +0 -0
  287. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_513_duplicate_session.py +0 -0
  288. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_523_guide.py +0 -0
  289. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_524_conftest_hermeticity.py +0 -0
  290. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_532_accept_flag.py +0 -0
  291. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_535_version_capability.py +0 -0
  292. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_538_signal_bench.py +0 -0
  293. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_546_default_gateway.py +0 -0
  294. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_547_verbs_from_registry.py +0 -0
  295. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_548_gateway_remainder.py +0 -0
  296. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_552_codegraph_gateway.py +0 -0
  297. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_555_relay_row_shape.py +0 -0
  298. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_556_relay_freshness.py +0 -0
  299. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_559_edges_truncated.py +0 -0
  300. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_564_bootstrap_first_peer.py +0 -0
  301. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_578_no_machine_specific_host_defaults.py +0 -0
  302. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_579_register_bootstrap_message.py +0 -0
  303. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_591_cli_step_graph.py +0 -0
  304. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_644_monitor_supervision.py +0 -0
  305. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_648_install_unit.py +0 -0
  306. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_654_reexec.py +0 -0
  307. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_656_owned_slm.py +0 -0
  308. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_684_dreaming_verb.py +0 -0
  309. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_689_pkg_version_order.py +0 -0
  310. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_715_grok_wake.py +0 -0
  311. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_716_timeline_one_path.py +0 -0
  312. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_723_grok_0251.py +0 -0
  313. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_724_ps1_ascii_or_bom.py +0 -0
  314. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_725_stdio_reconfigure.py +0 -0
  315. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_726_grok_limit_screen.py +0 -0
  316. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_729_arm_check_delivery_gap.py +0 -0
  317. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_729_dm_once.py +0 -0
  318. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_729_wake_watchdog.py +0 -0
  319. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_734_dreaming_enrich_degrade.py +0 -0
  320. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_735_dm_mcp_tools.py +0 -0
  321. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_739_wake_writer.py +0 -0
  322. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_740_edit_project.py +0 -0
  323. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_762_cards_edit_priority.py +0 -0
  324. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_764_enrich_collapse.py +0 -0
  325. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_801_confirm_flow_cli.py +0 -0
  326. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_802_stage_history.py +0 -0
  327. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_825_codegraph_hook_noise.py +0 -0
  328. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_825_install_posttooluse_only.py +0 -0
  329. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_825_remaining_cap_shred_bind.py +0 -0
  330. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_829_counterfactual_column.py +0 -0
  331. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_830_hook_binding_version.py +0 -0
  332. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_84_cli_labels.py +0 -0
  333. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_866_doctrine_guide.py +0 -0
  334. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_872_identity_refuses_not_warns.py +0 -0
  335. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_874_source_text.py +0 -0
  336. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_888_opencode_data_dir_can_fail.py +0 -0
  337. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_931_board_search.py +0 -0
  338. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_935_deadline_clock.py +0 -0
  339. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_937_dreaming_notify.py +0 -0
  340. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_938_organize_line_limit.py +0 -0
  341. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_941_bench_backends.py +0 -0
  342. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_941_harness_342.py +0 -0
  343. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_945_same_line_pairing.py +0 -0
  344. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_955_prompt_audit.py +0 -0
  345. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_957_auth_http.py +0 -0
  346. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_959_venv_interpreter.py +0 -0
  347. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_960_channel.py +0 -0
  348. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_960_ensure_monitor_heartbeat.py +0 -0
  349. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_961_cursor_grok_footer.py +0 -0
  350. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_961_loud_stop.py +0 -0
  351. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_963_plugin_manifest.py +0 -0
  352. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_964_channel_cell.py +0 -0
  353. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_965_mesh_wait.py +0 -0
  354. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_975_channel_hop.py +0 -0
  355. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_add_security_gate.py +0 -0
  356. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_artifact_add.py +0 -0
  357. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_artifact_hash.py +0 -0
  358. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_artifact_lib.py +0 -0
  359. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_artifact_mcp.py +0 -0
  360. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_artifact_skill.py +0 -0
  361. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_artifact_tool.py +0 -0
  362. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_artifact_uri.py +0 -0
  363. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_bench_backends.py +0 -0
  364. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_bench_claude_cli.py +0 -0
  365. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_bench_codex_cli.py +0 -0
  366. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_bench_command.py +0 -0
  367. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_bench_pack.py +0 -0
  368. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_bench_prices.py +0 -0
  369. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_bench_quality.py +0 -0
  370. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_bench_runner.py +0 -0
  371. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_bench_validate.py +0 -0
  372. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_board_card_thread.py +0 -0
  373. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_board_command.py +0 -0
  374. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_board_merge_check.py +0 -0
  375. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_board_obligation_close.py +0 -0
  376. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_brain_ask_command.py +0 -0
  377. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_brain_ask_env_diagnosis.py +0 -0
  378. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_brain_ask_identity_explicitness.py +0 -0
  379. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_brain_command.py +0 -0
  380. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_caller_meta_guard.py +0 -0
  381. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_capture_lineage.py +0 -0
  382. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_capture_liveness.py +0 -0
  383. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_capture_manifest.py +0 -0
  384. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_capture_paths.py +0 -0
  385. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_capture_security.py +0 -0
  386. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_cell_command_dispatch.py +0 -0
  387. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_cell_harden.py +0 -0
  388. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_cell_loader.py +0 -0
  389. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_cell_selfcheck.py +0 -0
  390. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_cell_verify.py +0 -0
  391. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_chain_token.py +0 -0
  392. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_channel_command.py +0 -0
  393. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_channel_poll_never_breaks_dms.py +0 -0
  394. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_channel_post.py +0 -0
  395. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_channel_wake_policy_filter.py +0 -0
  396. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_chat_command.py +0 -0
  397. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_claude_parser.py +0 -0
  398. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_claude_tmux_template.py +0 -0
  399. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_codegraph_caller_scope.py +0 -0
  400. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_codegraph_command.py +0 -0
  401. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_codegraph_hook.py +0 -0
  402. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_codegraph_mcp.py +0 -0
  403. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_codex_waker.py +0 -0
  404. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_compress_caller_convention.py +0 -0
  405. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_compress_command.py +0 -0
  406. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_compress_levers.py +0 -0
  407. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_compress_marker.py +0 -0
  408. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_compress_verify.py +0 -0
  409. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_console_encoding_e2e.py +0 -0
  410. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_content_composition.py +0 -0
  411. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_copilot_membrane.py +0 -0
  412. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_copilot_pane_reader.py +0 -0
  413. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_cursor_membrane.py +0 -0
  414. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_daemon_command.py +0 -0
  415. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_daemon_console_encoding.py +0 -0
  416. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_daemon_delivery.py +0 -0
  417. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_delivery_queue.py +0 -0
  418. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_display_sanitize.py +0 -0
  419. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_ensure_monitor_no_peer_default.py +0 -0
  420. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_event_emit.py +0 -0
  421. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_feature_to_uri.py +0 -0
  422. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_gateway_brain.py +0 -0
  423. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_gateway_client.py +0 -0
  424. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_gateway_command.py +0 -0
  425. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_gateway_message_idempotency.py +0 -0
  426. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_gh_route_doctor_mesh_name.py +0 -0
  427. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_group_command.py +0 -0
  428. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_guide_commands_parse.py +0 -0
  429. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_guide_selfcheck.py +0 -0
  430. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_heartbeat_check.py +0 -0
  431. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_highlight_command.py +0 -0
  432. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_hook_output.py +0 -0
  433. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_hooks_activity_marker.py +0 -0
  434. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_hooks_add.py +0 -0
  435. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_hooks_bundle.py +0 -0
  436. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_hooks_init.py +0 -0
  437. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_hooks_legacy_generation_removal.py +0 -0
  438. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_hooks_lifecycle.py +0 -0
  439. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_hooks_merge.py +0 -0
  440. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_hooks_verify.py +0 -0
  441. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_hooks_win32_bash_wrapper.py +0 -0
  442. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_hooks_win32_command_path.py +0 -0
  443. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_import_command.py +0 -0
  444. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_inbox_identity_provenance.py +0 -0
  445. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_init_command.py +0 -0
  446. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_init_provider_menu.py +0 -0
  447. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_install_codex_hooks.py +0 -0
  448. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_install_hook.py +0 -0
  449. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_install_multiplexer_command.py +0 -0
  450. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_install_postcompact_hook.py +0 -0
  451. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_install_wake_hook.py +0 -0
  452. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_lane_command.py +0 -0
  453. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_launchd_units.py +0 -0
  454. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_main.py +0 -0
  455. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_main_unknown_verb_guard.py +0 -0
  456. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_mcp_missing_hint.py +0 -0
  457. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_mcp_server.py +0 -0
  458. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_memory_command.py +0 -0
  459. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_memory_emit_snippet.py +0 -0
  460. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_memory_gateway.py +0 -0
  461. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_memory_sync.py +0 -0
  462. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_memory_sync_membrane.py +0 -0
  463. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_mesh_command.py +0 -0
  464. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_mesh_inbox_mark_read.py +0 -0
  465. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_mesh_inbox_sanitize.py +0 -0
  466. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_mesh_originate_thread_623.py +0 -0
  467. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_mesh_send_unknown_peer.py +0 -0
  468. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_mesh_sidecar.py +0 -0
  469. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_mesh_sidecar_cursor_decoupled.py +0 -0
  470. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_mesh_sidecar_muse_sink.py +0 -0
  471. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_mesh_sidecar_wake_survives_read.py +0 -0
  472. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_meta_edge_identity.py +0 -0
  473. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_monitor_channel_poll.py +0 -0
  474. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_monitor_cli.py +0 -0
  475. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_monitor_daemon_collision.py +0 -0
  476. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_monitor_self_name_verification.py +0 -0
  477. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_monitor_state_split.py +0 -0
  478. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_multiplexer.py +0 -0
  479. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_muse_membrane.py +0 -0
  480. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_muse_own_cli.py +0 -0
  481. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_obligation_close_is_surfaced.py +0 -0
  482. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_okf_links.py +0 -0
  483. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_onboard_command.py +0 -0
  484. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_opencode_membrane.py +0 -0
  485. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_opencode_plugin.py +0 -0
  486. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_operator_me.py +0 -0
  487. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_orphan_daemons.py +0 -0
  488. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_packaged_artifacts_exist.py +0 -0
  489. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_packaged_skills.py +0 -0
  490. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_peer_executor.py +0 -0
  491. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_peer_executor_windows.py +0 -0
  492. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_peer_reply_drain_command.py +0 -0
  493. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_peer_reply_drain_supervisor.py +0 -0
  494. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_peer_reply_outbox.py +0 -0
  495. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_peer_reply_transport.py +0 -0
  496. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_peer_service_e2e.py +0 -0
  497. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_peer_service_host.py +0 -0
  498. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_peer_service_payload.py +0 -0
  499. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_peer_service_reply.py +0 -0
  500. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_postcompact_recall.py +0 -0
  501. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_process_liveness.py +0 -0
  502. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_protocol_handler.py +0 -0
  503. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_providers_isolation.py +0 -0
  504. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_ratify_command.py +0 -0
  505. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_readme_claims_no_gateway_default.py +0 -0
  506. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_repl_caller_convention.py +0 -0
  507. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_schedule_command.py +0 -0
  508. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_schedule_create_contract.py +0 -0
  509. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_scrub.py +0 -0
  510. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_security.py +0 -0
  511. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_service_app.py +0 -0
  512. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_service_command.py +0 -0
  513. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_service_providers.py +0 -0
  514. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_session_bridge_inject.py +0 -0
  515. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_session_bridge_probe.py +0 -0
  516. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_session_bridge_resolve.py +0 -0
  517. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_session_path_role_gate.py +0 -0
  518. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_shipped_units_match_the_cli.py +0 -0
  519. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_smoke_chat.py +0 -0
  520. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_smoke_one_shot.py +0 -0
  521. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_smoke_phase_5_5.py +0 -0
  522. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_spawn_base_hoist.py +0 -0
  523. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_spawn_command.py +0 -0
  524. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_spawn_identity_stamp.py +0 -0
  525. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_spawn_live_pin.py +0 -0
  526. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_spawn_mitosis_lineage.py +0 -0
  527. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_spawn_tmux_session.py +0 -0
  528. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_spawn_windows_relaunch.py +0 -0
  529. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_stall_alert.py +0 -0
  530. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_subprocess_decode_encoding.py +0 -0
  531. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_timeline_command.py +0 -0
  532. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_tmux_wake_runstate_defer.py +0 -0
  533. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_tmux_wake_session_reanchor.py +0 -0
  534. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_tmux_wake_stale.py +0 -0
  535. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_tmux_wake_submit_verify.py +0 -0
  536. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_token_file_one_parser.py +0 -0
  537. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_token_precedence_explicit_first.py +0 -0
  538. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_unified_token_resolver.py +0 -0
  539. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_version_command.py +0 -0
  540. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_version_consistency.py +0 -0
  541. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_vibe_membrane.py +0 -0
  542. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_watchdog.py +0 -0
  543. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_watchdog_dm_wake.py +0 -0
  544. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_watchdog_dm_wake_cooldown.py +0 -0
  545. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_watchdog_dm_wake_wiring.py +0 -0
  546. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_watchdog_emit_health.py +0 -0
  547. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_watchdog_install_flags.py +0 -0
  548. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_watchdog_model_rung.py +0 -0
  549. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/tests/test_watchdog_stale_peers.py +0 -0
  550. {swarph_cli-0.72.34 → swarph_cli-0.72.36}/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.72.34
3
+ Version: 0.72.36
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.72.34"
7
+ version = "0.72.36"
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.72.34"
19
+ __version__ = "0.72.36"
20
20
 
21
21
  __all__ = ["__version__"]
@@ -38,6 +38,8 @@ import urllib.request
38
38
  from dataclasses import dataclass
39
39
  from typing import Any, Callable, Optional, Protocol
40
40
 
41
+ from swarph_cli.redact import encode_outbound_json
42
+
41
43
 
42
44
  @dataclass
43
45
  class BackendResult:
@@ -510,7 +512,7 @@ class TypedHttpBackend:
510
512
  body = _request_body(prompt, system)
511
513
  req = urllib.request.Request(
512
514
  endpoint,
513
- data=json.dumps(body).encode(),
515
+ data=encode_outbound_json(body, caller="bench.SystemOneBackend.generate"),
514
516
  headers={"Content-Type": "application/json"},
515
517
  method="POST",
516
518
  )
@@ -626,7 +628,7 @@ class HttpBackend:
626
628
  scheme = self.auth.get("scheme") or ""
627
629
  token = f"{scheme} {value}".strip() if scheme else value
628
630
  headers[self.auth["header"]] = token
629
- raw_body = json.dumps(body).encode()
631
+ raw_body = encode_outbound_json(body, caller="bench.HttpBackend.generate")
630
632
  self.calls += 1
631
633
  if self.transport is not None:
632
634
  status, reason, raw = self.transport(endpoint, headers, raw_body)
@@ -919,7 +921,7 @@ class DecisionsBackend:
919
921
  scheme = self.auth.get("scheme") or ""
920
922
  token = f"{scheme} {value}".strip() if scheme else value
921
923
  headers[self.auth["header"]] = token
922
- raw_body = json.dumps(body).encode()
924
+ raw_body = encode_outbound_json(body, caller="bench.DecisionsBackend.generate")
923
925
  self.calls += 1
924
926
  if self.transport is not None:
925
927
  status, reason, raw = self.transport(endpoint, headers, raw_body)
@@ -43,6 +43,7 @@ from swarph_cli.commands.mesh import (
43
43
  _resolve_self_name,
44
44
  _resolve_token,
45
45
  )
46
+ from swarph_cli.redact import redact_text, redact_value, encode_outbound_json
46
47
 
47
48
 
48
49
  _SENTINEL = object()
@@ -51,7 +52,7 @@ _SENTINEL = object()
51
52
  # ── HTTP: PATCH (mesh.py has GET + POST; the board needs PATCH for move/link) ──
52
53
 
53
54
  def _patch_json(url: str, body: dict, token: str, *, timeout: float = 10.0) -> tuple[int, dict]:
54
- data = json.dumps(body).encode("utf-8")
55
+ data = encode_outbound_json(body, caller="board._patch_json")
55
56
  req = urllib.request.Request(
56
57
  url, data=data, method="PATCH",
57
58
  headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"},
@@ -89,11 +90,12 @@ def _normalize_due_at(value: str) -> str:
89
90
 
90
91
 
91
92
  def _card_add_payload(actor, project_id, title, *, body=None, ai2=False, priority=0,
92
- labels=None, due_at=None) -> dict:
93
+ labels=None, due_at=None, opt_out=False) -> dict:
94
+ title = redact_text(title, opt_out=opt_out, caller="board.cards.add")
93
95
  p = {"actor": actor, "project_id": int(project_id), "title": title,
94
96
  "ai2": bool(ai2), "priority": int(priority)}
95
97
  if body:
96
- p["body"] = body
98
+ p["body"] = redact_text(body, opt_out=opt_out, caller="board.cards.add")
97
99
  if labels:
98
100
  p["labels"] = list(labels)
99
101
  if due_at is not None:
@@ -151,7 +153,7 @@ def _format_obligations(data: dict) -> str:
151
153
 
152
154
 
153
155
  def _card_edit_payload(actor, title, body, *, due_at=_SENTINEL, project_id=None,
154
- priority=None) -> dict:
156
+ priority=None, opt_out=False) -> dict:
155
157
  """#191: the edit patch — title and/or body, the two fields that made a
156
158
  card's text write-once until the gateway grew them (BoardCardPatch).
157
159
 
@@ -173,9 +175,9 @@ def _card_edit_payload(actor, title, body, *, due_at=_SENTINEL, project_id=None,
173
175
  """
174
176
  patch = {"actor": actor}
175
177
  if title is not None:
176
- patch["title"] = title
178
+ patch["title"] = redact_text(title, opt_out=opt_out, caller="board.cards.edit")
177
179
  if body is not None:
178
- patch["body"] = body
180
+ patch["body"] = redact_text(body, opt_out=opt_out, caller="board.cards.edit")
179
181
  if due_at is not _SENTINEL:
180
182
  # "" is the gateway's CLEAR sentinel; None means "not mentioned" and the
181
183
  # write is skipped while the old date is echoed back (#901).
@@ -190,7 +192,7 @@ def _card_edit_payload(actor, title, body, *, due_at=_SENTINEL, project_id=None,
190
192
  return patch
191
193
 
192
194
 
193
- def _write_card_preimage(actor, gateway, card_id, card, patch) -> Path:
195
+ def _write_card_preimage(actor, gateway, card_id, card, patch, *, opt_out=False) -> Path:
194
196
  """Append the card's CURRENT title and body to a local log BEFORE an edit
195
197
  replaces them. Returns the path written.
196
198
 
@@ -213,10 +215,10 @@ def _write_card_preimage(actor, gateway, card_id, card, patch) -> Path:
213
215
  "gateway": gateway,
214
216
  "card": card_id,
215
217
  "body_version": card.get("body_version"),
216
- "prev_title": card.get("title"),
217
- "prev_body": card.get("body"),
218
- "new_title": patch.get("title"),
219
- "new_body": patch.get("body"),
218
+ "prev_title": redact_text(card.get("title"), opt_out=opt_out, caller="board.cards.edit"),
219
+ "prev_body": redact_text(card.get("body"), opt_out=opt_out, caller="board.cards.edit"),
220
+ "new_title": redact_text(patch.get("title"), opt_out=opt_out, caller="board.cards.edit"),
221
+ "new_body": redact_text(patch.get("body"), opt_out=opt_out, caller="board.cards.edit"),
220
222
  }
221
223
  path = card_preimage_path()
222
224
  path.parent.mkdir(parents=True, exist_ok=True)
@@ -251,10 +253,11 @@ def _apply_label(current: list, action: str, label: str) -> list:
251
253
  return [x for x in cur if x != lab]
252
254
 
253
255
 
254
- def _project_add_payload(actor, slug, title, *, goal=None) -> dict:
256
+ def _project_add_payload(actor, slug, title, *, goal=None, opt_out: bool = False) -> dict:
257
+ title = redact_text(title, opt_out=opt_out, caller="board.projects")
255
258
  p = {"actor": actor, "slug": slug, "title": title}
256
259
  if goal:
257
- p["goal"] = goal
260
+ p["goal"] = redact_text(goal, opt_out=opt_out, caller="board.projects")
258
261
  return p
259
262
 
260
263
 
@@ -546,7 +549,8 @@ def _say_line(resp: dict, card_id, to_node: str, *, reason: Optional[str] = None
546
549
 
547
550
 
548
551
  def _card_say_payload(from_node: str, to_node: str, kind: str, content: str,
549
- thread_uuid: str) -> dict:
552
+ thread_uuid: str, *, opt_out=False) -> dict:
553
+ content = redact_text(content, opt_out=opt_out, caller="board.cards.say")
550
554
  return {
551
555
  "from_node": from_node,
552
556
  "to_node": to_node,
@@ -726,7 +730,7 @@ def _json_flag(flag: str, value: str):
726
730
 
727
731
  def _ask_payload(self_name, what, *, holder=None, step=None, needs=None, hours=None,
728
732
  done=None, accept=None, accept_json=None, kind="action",
729
- timeout_hours=None, task=None, task_needs=None) -> dict:
733
+ timeout_hours=None, task=None, task_needs=None, opt_out=False) -> dict:
730
734
  """POST /board/cards/{id}/ask body. None = not mentioned = key ABSENT (#191's
731
735
  rule; test_532 pins that a null `accept` on the wire would overwrite the
732
736
  gateway's own normalization). No holder → `requested`; `me` → the caller's
@@ -736,6 +740,7 @@ def _ask_payload(self_name, what, *, holder=None, step=None, needs=None, hours=N
736
740
  if accept is not None and accept_json is not None:
737
741
  raise ValueError("pass --accept or --accept-json, not both — "
738
742
  "one check per row")
743
+ what = redact_text(what, opt_out=opt_out, caller="board.cards.ask")
739
744
  p = {"what": what, "created_by": self_name, "kind": kind}
740
745
  if holder is not None:
741
746
  p["holder"] = self_name if holder == "me" else holder
@@ -746,11 +751,11 @@ def _ask_payload(self_name, what, *, holder=None, step=None, needs=None, hours=N
746
751
  if hours is not None:
747
752
  p["hours"] = hours
748
753
  if done is not None:
749
- p["done"] = done
754
+ p["done"] = redact_text(done, opt_out=opt_out, caller="board.cards.ask")
750
755
  if accept is not None:
751
- p["accept"] = accept
756
+ p["accept"] = redact_text(accept, opt_out=opt_out, caller="board.cards.ask")
752
757
  if accept_json is not None:
753
- p["accept_json"] = accept_json
758
+ p["accept_json"] = redact_value(accept_json, opt_out=opt_out, caller="board.cards.ask")
754
759
  if timeout_hours is not None:
755
760
  p["timeout_hours"] = timeout_hours
756
761
  if task is not None:
@@ -830,7 +835,7 @@ def _ask_line(d) -> str:
830
835
  return line
831
836
 
832
837
 
833
- def _confirm_flow_payload(actor: str, holders, what=None) -> dict:
838
+ def _confirm_flow_payload(actor: str, holders, what=None, *, opt_out=False) -> dict:
834
839
  """#801: {actor, holders: {step: peer}, what}. `--holder STEP=PEER` is parsed here so a
835
840
  malformed override is refused before the request, naming the form."""
836
841
  body = {"actor": actor}
@@ -844,7 +849,7 @@ def _confirm_flow_payload(actor: str, holders, what=None) -> dict:
844
849
  out[step] = peer
845
850
  body["holders"] = out
846
851
  if what:
847
- body["what"] = what
852
+ body["what"] = redact_text(what, opt_out=opt_out, caller="board.cards.confirm-flow")
848
853
  return body
849
854
 
850
855
 
@@ -924,7 +929,7 @@ def _move_line(x) -> str:
924
929
  return line
925
930
 
926
931
 
927
- def _close_payload(outcome, evidence=None, evidence_json=None) -> dict:
932
+ def _close_payload(outcome, evidence=None, evidence_json=None, *, opt_out=False) -> dict:
928
933
  """POST /board/obligations/{id}/close body (#1068): --evidence and/or
929
934
  --evidence-json, at least one. The CLI cannot know the row's stored
930
935
  accept, so it sends what it was given — the gateway requires the map
@@ -934,15 +939,15 @@ def _close_payload(outcome, evidence=None, evidence_json=None) -> dict:
934
939
  "--evidence-json")
935
940
  p = {"outcome": outcome}
936
941
  if evidence is not None:
937
- p["evidence"] = evidence
942
+ p["evidence"] = redact_text(evidence, opt_out=opt_out, caller="board.obligations.close")
938
943
  if evidence_json is not None:
939
- p["evidence_json"] = evidence_json
944
+ p["evidence_json"] = redact_value(evidence_json, opt_out=opt_out, caller="board.obligations.close")
940
945
  return p
941
946
 
942
947
 
943
948
  def _amend_payload(step=None, holder=None, accept=None, hours=None,
944
949
  needs_add=None, needs_remove=None, needs=None,
945
- accept_json=None) -> dict:
950
+ accept_json=None, *, opt_out=False) -> dict:
946
951
  """PATCH /board/obligations/{id}/amend body. None = not mentioned; an empty
947
952
  `holder` is a REAL value (clears → `requested`), so the test is
948
953
  `is not None`, never truthiness (#191). `needs` is the contract's signed
@@ -953,6 +958,10 @@ def _amend_payload(step=None, holder=None, accept=None, hours=None,
953
958
  if accept is not None and accept_json is not None:
954
959
  raise ValueError("pass --accept or --accept-json, not both — "
955
960
  "one check per row")
961
+ if accept is not None:
962
+ accept = redact_text(accept, opt_out=opt_out, caller="board.obligations")
963
+ if accept_json is not None:
964
+ accept_json = redact_value(accept_json, opt_out=opt_out, caller="board.obligations")
956
965
  signed = _step_list(needs)
957
966
  add = _step_list(needs_add) + [x for x in signed if not x.startswith("-")]
958
967
  rem = _step_list(needs_remove) + [x[1:] for x in signed if x.startswith("-")]
@@ -1313,7 +1322,7 @@ def run_board(argv: list[str]) -> int:
1313
1322
  st, d = _http_get_json(f"{gw}/board/projects", token)
1314
1323
  return _out(st, d, _format_projects, aj)
1315
1324
  if args.command == "add":
1316
- st, d = _post_json(f"{gw}/board/projects", _project_add_payload(self_name, args.slug, args.title, goal=args.goal), token)
1325
+ st, d = _post_json(f"{gw}/board/projects", _project_add_payload(self_name, args.slug, args.title, goal=args.goal, opt_out=getattr(args, "no_redact", False)), token)
1317
1326
  return _out(st, d, lambda x: f"created project #{x.get('id')} ({x.get('slug')})", aj)
1318
1327
 
1319
1328
  if args.group == "obligations":
@@ -1332,7 +1341,8 @@ def run_board(argv: list[str]) -> int:
1332
1341
  try:
1333
1342
  evidence_json = (_json_flag("--evidence-json", args.evidence_json)
1334
1343
  if args.evidence_json is not None else None)
1335
- payload = _close_payload(args.outcome, evidence, evidence_json)
1344
+ payload = _close_payload(args.outcome, evidence, evidence_json,
1345
+ opt_out=getattr(args, "no_redact", False))
1336
1346
  except ValueError as exc:
1337
1347
  print(f"swarph board obligations close: {exc}", file=sys.stderr)
1338
1348
  return 2
@@ -1362,8 +1372,9 @@ def run_board(argv: list[str]) -> int:
1362
1372
  st, d = _post_json(f"{gw}/board/obligations/{args.id}/take", {}, token)
1363
1373
  return _out(st, d, _obligation_act_line, aj)
1364
1374
  if args.command == "decline":
1375
+ why = redact_text(args.why, opt_out=getattr(args, "no_redact", False), caller="board.obligations")
1365
1376
  st, d = _post_json(f"{gw}/board/obligations/{args.id}/decline",
1366
- {"why": args.why}, token)
1377
+ {"why": why}, token)
1367
1378
  return _out(st, d, _obligation_act_line, aj)
1368
1379
  if args.command == "amend":
1369
1380
  try:
@@ -1373,7 +1384,8 @@ def run_board(argv: list[str]) -> int:
1373
1384
  accept=args.accept, hours=args.hours,
1374
1385
  needs_add=args.needs_add,
1375
1386
  needs_remove=args.needs_remove, needs=args.needs,
1376
- accept_json=accept_json)
1387
+ accept_json=accept_json,
1388
+ opt_out=getattr(args, "no_redact", False))
1377
1389
  except ValueError as exc:
1378
1390
  print(f"swarph board obligations amend: {exc}", file=sys.stderr)
1379
1391
  return 2
@@ -1385,6 +1397,7 @@ def run_board(argv: list[str]) -> int:
1385
1397
  print("swarph board obligations withdraw: --reason is "
1386
1398
  "whitespace-only", file=sys.stderr)
1387
1399
  return 2
1400
+ reason = redact_text(reason, opt_out=getattr(args, "no_redact", False), caller="board.obligations")
1388
1401
  st, d = _post_json(
1389
1402
  f"{gw}/board/obligations/{args.id}/withdraw",
1390
1403
  {"reason": reason}, token)
@@ -1441,7 +1454,7 @@ def run_board(argv: list[str]) -> int:
1441
1454
  st, d = _post_json(f"{gw}/board/cards", _card_add_payload(
1442
1455
  self_name, pid, title, body=body, ai2=args.ai2,
1443
1456
  priority=args.priority, labels=getattr(args, "labels", None),
1444
- due_at=args.due), token)
1457
+ due_at=args.due, opt_out=getattr(args, "no_redact", False)), token)
1445
1458
  return _out(st, d, lambda x: f"created card #{x.get('id')} [{x.get('stage')}] (stage defaults to proposed — use `cards move` to advance)", aj)
1446
1459
  if args.command == "label":
1447
1460
  # READ the current set before replacing it. If the GET fails we must
@@ -1491,7 +1504,8 @@ def run_board(argv: list[str]) -> int:
1491
1504
  try:
1492
1505
  patch = _card_edit_payload(
1493
1506
  self_name, title_text, body_text, due_at=args.due,
1494
- project_id=project_id, priority=args.priority)
1507
+ project_id=project_id, priority=args.priority,
1508
+ opt_out=getattr(args, "no_redact", False))
1495
1509
  except ValueError as exc:
1496
1510
  print(f"swarph board cards edit: {exc}", file=sys.stderr)
1497
1511
  return 2
@@ -1508,7 +1522,8 @@ def run_board(argv: list[str]) -> int:
1508
1522
  f"an unrecoverable one", file=sys.stderr)
1509
1523
  return 1
1510
1524
  try:
1511
- pre = _write_card_preimage(self_name, gw, args.id, cur, patch)
1525
+ pre = _write_card_preimage(self_name, gw, args.id, cur, patch,
1526
+ opt_out=getattr(args, "no_redact", False))
1512
1527
  except OSError as exc:
1513
1528
  print(f"swarph board cards edit: cannot write the pre-image log "
1514
1529
  f"({exc}) — refusing to write, for the same reason: the "
@@ -1541,7 +1556,7 @@ def run_board(argv: list[str]) -> int:
1541
1556
  # the row in one gateway call, or neither.
1542
1557
  if args.holder is not None and args.holder_flag is not None:
1543
1558
  print("swarph board cards ask: holder given twice (positional and "
1544
- "--holder) — pass one", file=sys.stderr)
1559
+ "--holder) — pass one", file=sys.stderr)
1545
1560
  return 2
1546
1561
  holder = args.holder_flag or args.holder
1547
1562
  if holder is None and args.step is None:
@@ -1562,7 +1577,8 @@ def run_board(argv: list[str]) -> int:
1562
1577
  done=args.done, accept=args.accept,
1563
1578
  accept_json=accept_json, kind=args.kind,
1564
1579
  timeout_hours=args.timeout_hours,
1565
- task=args.task, task_needs=args.task_needs)
1580
+ task=args.task, task_needs=args.task_needs,
1581
+ opt_out=getattr(args, "no_redact", False))
1566
1582
  except ValueError as exc:
1567
1583
  print(f"swarph board cards ask: {exc}", file=sys.stderr)
1568
1584
  return 2
@@ -1570,7 +1586,8 @@ def run_board(argv: list[str]) -> int:
1570
1586
  return _out(st, d, _ask_line, args.json)
1571
1587
  if args.command == "confirm-flow":
1572
1588
  try:
1573
- body = _confirm_flow_payload(self_name, args.holder, args.what)
1589
+ body = _confirm_flow_payload(self_name, args.holder, args.what,
1590
+ opt_out=getattr(args, "no_redact", False))
1574
1591
  except ValueError as e:
1575
1592
  print(f"swarph board cards confirm-flow: {e}", file=sys.stderr)
1576
1593
  return 2
@@ -1614,7 +1631,8 @@ def run_board(argv: list[str]) -> int:
1614
1631
  return 1
1615
1632
  st, d = _post_json(
1616
1633
  f"{gw}/messages",
1617
- _card_say_payload(self_name, to_node, args.kind, content, thread_uuid),
1634
+ _card_say_payload(self_name, to_node, args.kind, content, thread_uuid,
1635
+ opt_out=getattr(args, "no_redact", False)),
1618
1636
  token,
1619
1637
  )
1620
1638
  # A 403 here carries the gateway's explanation that attaching PUBLISHES
@@ -33,6 +33,7 @@ import urllib.request
33
33
 
34
34
  from swarph_cli import identity
35
35
  from swarph_cli import tokens
36
+ from swarph_cli.redact import encode_outbound_json
36
37
  from pathlib import Path
37
38
  from typing import Optional
38
39
 
@@ -204,7 +205,7 @@ def _resolve_token(token_file: Optional[str], self_name: str) -> Optional[str]:
204
205
  def _http_post(url: str, body: dict, token: str,
205
206
  accept: str = "application/json, text/event-stream",
206
207
  timeout: int = 30) -> str:
207
- data = json.dumps(body).encode("utf-8")
208
+ data = encode_outbound_json(body, caller="brain_ask._http_post")
208
209
  req = urllib.request.Request(url, data=data, method="POST")
209
210
  req.add_header("Content-Type", "application/json")
210
211
  req.add_header("Accept", accept)
@@ -145,9 +145,11 @@ def gateway_memory_list(gateway: str, token: str, timeout: int = 15) -> list[str
145
145
  gateway; :8792 is gbrain itself and speaks MCP at /mcp, where POST /memory is
146
146
  correctly refused. A route named without its coordinate cost a peer a
147
147
  measurement on 2026-09-05."""
148
+ from swarph_cli.redact import encode_outbound_json
149
+
148
150
  req = urllib.request.Request(
149
151
  gateway.rstrip("/") + "/memory",
150
- data=json.dumps({"op": "list", "arguments": {}}).encode(),
152
+ data=encode_outbound_json({"op": "list", "arguments": {}}, caller="cell_probe.gateway_memory_list"),
151
153
  headers={"Authorization": "Bearer " + token,
152
154
  "Content-Type": "application/json"})
153
155
  doc = json.loads(urllib.request.urlopen(req, timeout=timeout).read())
@@ -18,6 +18,7 @@ from ._gateway_client import (
18
18
  resolve_token,
19
19
  )
20
20
  from swarph_cli.console_safe import print_safe
21
+ from swarph_cli.redact import redact_text
21
22
 
22
23
 
23
24
  def _build_parser() -> argparse.ArgumentParser:
@@ -74,9 +75,10 @@ def _build_parser() -> argparse.ArgumentParser:
74
75
 
75
76
  # ── pure helpers (unit-tested) ────────────────────────────────────────────────
76
77
 
77
- def _post_payload(self_name: str, channel: str, kind: str, content: str) -> dict:
78
+ def _post_payload(self_name: str, channel: str, kind: str, content: str, *, opt_out: bool = False) -> dict:
78
79
  """A channel post carries ``channel`` and NEVER ``to_node`` — the gateway
79
80
  rejects a message with both ("exactly one of {to_node, channel} required")."""
81
+ content = redact_text(content, opt_out=opt_out, caller="channel.post")
80
82
  return {"from_node": self_name, "channel": channel, "kind": kind, "content": content}
81
83
 
82
84
 
@@ -120,7 +122,7 @@ def _run_create(args: argparse.Namespace) -> int:
120
122
  if args.visibility is not None:
121
123
  body["visibility"] = args.visibility
122
124
  if args.description is not None:
123
- body["description"] = args.description
125
+ body["description"] = redact_text(args.description, opt_out=getattr(args, "no_redact", False), caller="channel.create")
124
126
  status, payload = post_json(f"{base}/channels", body, token)
125
127
  if not _ok(status):
126
128
  return _fail("create", status, payload)
@@ -178,9 +180,10 @@ def _run_post(args: argparse.Namespace) -> int:
178
180
  except ContentError as exc:
179
181
  print(f"swarph channel post: {exc}", file=sys.stderr)
180
182
  return 1
183
+ content = redact_text(content, opt_out=getattr(args, "no_redact", False), caller="channel.post") or ""
181
184
  self_name, token, base = _ctx(args)
182
185
  status, payload = post_json(
183
- f"{base}/messages", _post_payload(self_name, args.name, args.kind, content), token
186
+ f"{base}/messages", _post_payload(self_name, args.name, args.kind, content, opt_out=getattr(args, "no_redact", False)), token
184
187
  )
185
188
  if not _ok(status):
186
189
  return _fail("post", status, payload)
@@ -35,6 +35,7 @@ from pathlib import Path
35
35
  from typing import Optional
36
36
  from swarph_cli import identity
37
37
  from swarph_cli.gateway_default import env_gateway
38
+ from swarph_cli.redact import encode_outbound_json
38
39
 
39
40
  TIMEOUT_S = 6
40
41
  MAX_ROWS = 6
@@ -326,7 +327,7 @@ def query_gateway(term: str, gateway: str, token: str,
326
327
  "gateway host (#578) — the graph was never asked"}
327
328
  req = urllib.request.Request(
328
329
  f"{gateway.rstrip('/')}/codegraph",
329
- data=json.dumps({"query": term, "limit": limit}).encode(),
330
+ data=encode_outbound_json({"query": term, "limit": limit}, caller="codegraph_hook.query_gateway"),
330
331
  headers={"Authorization": f"Bearer {token}",
331
332
  "Content-Type": "application/json"},
332
333
  method="POST",
@@ -0,0 +1,95 @@
1
+ """``swarph commander`` — propose a decision or an action. Card #1297.
2
+
3
+ The cell asks. The commander decides, from the desktop, with a credential
4
+ this command never holds. ``ask`` posts a decision. ``request`` posts
5
+ ``merge_pr`` or ``release_finish``. An MCP tool for the same queue is a
6
+ later card.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import argparse
11
+ import sys
12
+
13
+ from swarph_cli.commands import mesh as mesh_cmd
14
+
15
+
16
+ def ask_body(question: str, options: list[str], card: int | None) -> dict:
17
+ body: dict = {"type": "decision", "question": question, "options": options}
18
+ if card is not None:
19
+ body["card_id"] = card
20
+ return body
21
+
22
+
23
+ def request_body(kind: str, *, repo: str | None, pr: int | None,
24
+ head: str | None, version: str | None, card: int | None) -> dict:
25
+ body: dict = {"type": kind, "pr": pr, "head_sha": head}
26
+ if kind == "merge_pr":
27
+ body["repo"] = repo
28
+ if kind == "release_finish":
29
+ body["version"] = version
30
+ if card is not None:
31
+ body["card_id"] = card
32
+ return body
33
+
34
+
35
+ def _build_parser() -> argparse.ArgumentParser:
36
+ p = argparse.ArgumentParser(prog="swarph commander")
37
+ sub = p.add_subparsers(dest="command", required=True)
38
+
39
+ ask = sub.add_parser("ask", help="propose a decision")
40
+ mesh_cmd._add_common(ask)
41
+ ask.add_argument("--question", required=True)
42
+ ask.add_argument("--options", default=None,
43
+ help="comma-separated choices, e.g. yes,no")
44
+ ask.add_argument("--card", type=int, default=None)
45
+
46
+ req = sub.add_parser("request", help="propose merge_pr or release_finish")
47
+ mesh_cmd._add_common(req)
48
+ req.add_argument("type", choices=["merge_pr", "release_finish"])
49
+ req.add_argument("--repo", default=None)
50
+ req.add_argument("--pr", type=int, default=None)
51
+ req.add_argument("--head", default=None)
52
+ req.add_argument("--version", default=None)
53
+ req.add_argument("--card", type=int, default=None)
54
+ return p
55
+
56
+
57
+ def _options(raw: str | None) -> list[str]:
58
+ if not raw:
59
+ return []
60
+ return [part.strip() for part in raw.split(",") if part.strip()]
61
+
62
+
63
+ def run_commander(argv: list[str]) -> int:
64
+ args = _build_parser().parse_args(argv)
65
+ try:
66
+ self_name = mesh_cmd._resolve_self_name(args.self_name)
67
+ token = mesh_cmd._resolve_token(self_name, args.token_file)
68
+ except RuntimeError as exc:
69
+ print(f"swarph commander: {exc}", file=sys.stderr)
70
+ return 1
71
+ gw = args.gateway.rstrip("/")
72
+ if args.command == "ask":
73
+ body = ask_body(args.question, _options(args.options), args.card)
74
+ else:
75
+ if args.pr is None or not args.head:
76
+ print("swarph commander request: --pr and --head are required",
77
+ file=sys.stderr)
78
+ return 2
79
+ if args.type == "merge_pr" and not args.repo:
80
+ print("swarph commander request: merge_pr requires --repo",
81
+ file=sys.stderr)
82
+ return 2
83
+ if args.type == "release_finish" and not args.version:
84
+ print("swarph commander request: release_finish requires --version",
85
+ file=sys.stderr)
86
+ return 2
87
+ body = request_body(args.type, repo=args.repo, pr=args.pr, head=args.head,
88
+ version=args.version, card=args.card)
89
+ status, payload = mesh_cmd._post_json(f"{gw}/commander/requests", body, token)
90
+ if status in (200, 201):
91
+ print(f"commander request #{payload.get('id')} {payload.get('status')}")
92
+ return 0
93
+ detail = payload.get("detail") if isinstance(payload, dict) else payload
94
+ print(f"swarph commander: {detail}", file=sys.stderr)
95
+ return 1