swarph-cli 0.72.20__tar.gz → 0.72.22__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 (521) hide show
  1. {swarph_cli-0.72.20/src/swarph_cli.egg-info → swarph_cli-0.72.22}/PKG-INFO +1 -1
  2. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/pyproject.toml +2 -2
  3. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/__init__.py +1 -1
  4. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/board.py +1 -0
  5. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/gh_route.py +51 -8
  6. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/init.py +26 -0
  7. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/mesh.py +2 -1
  8. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/spawn.py +4 -0
  9. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/gh_identity.py +149 -11
  10. swarph_cli-0.72.22/src/swarph_cli/launchd/swarph-codex-outbox.plist +33 -0
  11. swarph_cli-0.72.22/src/swarph_cli/launchd/swarph-codex-outbox.timer.plist +35 -0
  12. swarph_cli-0.72.22/src/swarph_cli/launchd/swarph-monitor.plist +39 -0
  13. swarph_cli-0.72.22/src/swarph_cli/launchd/swarph-watchdog.plist +21 -0
  14. swarph_cli-0.72.22/src/swarph_cli/launchd/swarph-watchdog.timer.plist +23 -0
  15. swarph_cli-0.72.22/src/swarph_cli/launchd_render.py +230 -0
  16. swarph_cli-0.72.22/src/swarph_cli/stall_alert.py +289 -0
  17. {swarph_cli-0.72.20 → swarph_cli-0.72.22/src/swarph_cli.egg-info}/PKG-INFO +1 -1
  18. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli.egg-info/SOURCES.txt +10 -0
  19. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1006_board_publisher.py +7 -9
  20. swarph_cli-0.72.22/tests/test_1144_cell_yaml_github.py +331 -0
  21. swarph_cli-0.72.22/tests/test_1197_commander_taps.py +203 -0
  22. swarph_cli-0.72.22/tests/test_1206_offer_question.py +262 -0
  23. swarph_cli-0.72.22/tests/test_launchd_units.py +70 -0
  24. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_opencode_membrane.py +13 -0
  25. swarph_cli-0.72.22/tests/test_stall_alert.py +568 -0
  26. swarph_cli-0.72.20/src/swarph_cli/stall_alert.py +0 -152
  27. swarph_cli-0.72.20/tests/test_stall_alert.py +0 -151
  28. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/LICENSE +0 -0
  29. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/README.md +0 -0
  30. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/setup.cfg +0 -0
  31. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/__main__.py +0 -0
  32. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/bench/__init__.py +0 -0
  33. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/bench/backends.py +0 -0
  34. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/bench/claude_cli.py +0 -0
  35. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/bench/codex_cli.py +0 -0
  36. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/bench/pack.py +0 -0
  37. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/bench/prices.py +0 -0
  38. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/bench/providers.py +0 -0
  39. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/bench/quality.py +0 -0
  40. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/bench/refresh_prices.py +0 -0
  41. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/bench/rules.py +0 -0
  42. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/bench/runner.py +0 -0
  43. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/bench/signal_score.py +0 -0
  44. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/bench/validate.py +0 -0
  45. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/caller.py +0 -0
  46. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/capture/__init__.py +0 -0
  47. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/capture/harden.py +0 -0
  48. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/capture/lineage.py +0 -0
  49. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/capture/liveness.py +0 -0
  50. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/capture/manifest.py +0 -0
  51. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/capture/paths.py +0 -0
  52. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/capture/verify.py +0 -0
  53. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/cell.py +0 -0
  54. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/chain_token.py +0 -0
  55. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/channel.py +0 -0
  56. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/__init__.py +0 -0
  57. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/_content.py +0 -0
  58. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/_display.py +0 -0
  59. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/_gateway_client.py +0 -0
  60. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/add.py +0 -0
  61. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/bench.py +0 -0
  62. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/board_merge_check.py +0 -0
  63. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/brain.py +0 -0
  64. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/brain_ask.py +0 -0
  65. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/cell.py +0 -0
  66. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/cell_probe.py +0 -0
  67. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/cell_selfcheck.py +0 -0
  68. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/channel.py +0 -0
  69. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/chat.py +0 -0
  70. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/codegraph.py +0 -0
  71. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/codegraph_hook.py +0 -0
  72. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/codex_hook_output.py +0 -0
  73. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/codex_waker.py +0 -0
  74. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/compress.py +0 -0
  75. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/daemon.py +0 -0
  76. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/dreaming.py +0 -0
  77. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/event.py +0 -0
  78. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/gateway.py +0 -0
  79. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/group.py +0 -0
  80. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/guide.py +0 -0
  81. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/highlight.py +0 -0
  82. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/hook_interpreter.py +0 -0
  83. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/hook_output.py +0 -0
  84. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/hooks.py +0 -0
  85. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/import_session.py +0 -0
  86. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/install_codex_hooks.py +0 -0
  87. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/install_hook.py +0 -0
  88. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/install_multiplexer.py +0 -0
  89. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/install_opencode_plugin.py +0 -0
  90. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/install_postcompact_hook.py +0 -0
  91. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/install_wake_hook.py +0 -0
  92. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/lane.py +0 -0
  93. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/mcp_server.py +0 -0
  94. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/memory.py +0 -0
  95. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/memory_emit_hook.py +0 -0
  96. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/memory_sync.py +0 -0
  97. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/monitor.py +0 -0
  98. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/okf_links.py +0 -0
  99. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/onboard.py +0 -0
  100. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/peer_reply_drain.py +0 -0
  101. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/postcompact_hook_output.py +0 -0
  102. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/protocol_handler.py +0 -0
  103. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/ratify.py +0 -0
  104. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/roster.py +0 -0
  105. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/rowclear_hook.py +0 -0
  106. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/schedule.py +0 -0
  107. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/security.py +0 -0
  108. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/service.py +0 -0
  109. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/sweep.py +0 -0
  110. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/timeline.py +0 -0
  111. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/triage.py +0 -0
  112. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/version.py +0 -0
  113. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/wake_hook_output.py +0 -0
  114. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/commands/watchdog.py +0 -0
  115. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/compress/__init__.py +0 -0
  116. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/compress/levers.py +0 -0
  117. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/compress/marker.py +0 -0
  118. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/compress/verify.py +0 -0
  119. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/console_safe.py +0 -0
  120. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/delivery_queue.py +0 -0
  121. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dm_frame.py +0 -0
  122. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dreaming/__init__.py +0 -0
  123. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dreaming/candidates.py +0 -0
  124. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dreaming/clone.py +0 -0
  125. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dreaming/enrich.py +0 -0
  126. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dreaming/index_check.py +0 -0
  127. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dreaming/notify.py +0 -0
  128. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dreaming/organize.py +0 -0
  129. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dreaming/probes.py +0 -0
  130. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dreaming/report.py +0 -0
  131. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dreaming/run.py +0 -0
  132. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dreaming/slm.py +0 -0
  133. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dreaming/transcripts.py +0 -0
  134. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/dreaming/verify.py +0 -0
  135. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/gateway/__init__.py +0 -0
  136. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/gateway/feature_registry.py +0 -0
  137. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/gateway/lanes_control.py +0 -0
  138. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/gateway/schema.sql +0 -0
  139. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/gateway/server.py +0 -0
  140. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/gateway/services_control.py +0 -0
  141. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/gateway_default.py +0 -0
  142. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/guide/GUIDE.md +0 -0
  143. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/identity.py +0 -0
  144. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/main.py +0 -0
  145. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/multiplexer.py +0 -0
  146. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/operator/__init__.py +0 -0
  147. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/operator/__main__.py +0 -0
  148. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/operator/api.py +0 -0
  149. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/operator/cli.py +0 -0
  150. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/operator/config.py +0 -0
  151. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/operator/fmt.py +0 -0
  152. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/orphan_daemons.py +0 -0
  153. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/pane_probe.py +0 -0
  154. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/parsers/__init__.py +0 -0
  155. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/parsers/claude.py +0 -0
  156. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/payloads/opencode/plugin.js +0 -0
  157. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/payloads/postcompact/_shim.cmd +0 -0
  158. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/payloads/postcompact/postcompact-recall-grok.sh +0 -0
  159. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/payloads/postcompact/postcompact-recall.sh +0 -0
  160. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/payloads/postcompact/posttooluse-emit-antigravity.sh +0 -0
  161. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/payloads/postcompact/posttooluse-emit-claude.sh +0 -0
  162. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/payloads/postcompact/posttooluse-emit-grok.sh +0 -0
  163. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/payloads/postcompact/posttooluse-emit.sh +0 -0
  164. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/payloads/postcompact/posttooluse-recall.sh +0 -0
  165. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/payloads/postcompact/precompact-flag.sh +0 -0
  166. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/payloads/postcompact/preinvocation-recall-antigravity.sh +0 -0
  167. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/payloads/postcompact/sessionstart-recall.sh +0 -0
  168. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/peer_executor.py +0 -0
  169. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/peer_executor_windows.py +0 -0
  170. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/peer_reconciliation.py +0 -0
  171. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/peer_reply_outbox.py +0 -0
  172. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/peer_service_host.py +0 -0
  173. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/peer_service_payload.py +0 -0
  174. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/peer_service_reply.py +0 -0
  175. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/peer_staging.py +0 -0
  176. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/query_filters.py +0 -0
  177. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/quota_sync.py +0 -0
  178. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/rowclear.py +0 -0
  179. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/scripts/__init__.py +0 -0
  180. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/scripts/dm_notify_filter.py +0 -0
  181. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/scripts/ensure_monitor.sh +0 -0
  182. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/scripts/install_codex_waker_windows.ps1 +0 -0
  183. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/scripts/install_monitor_task_windows.ps1 +0 -0
  184. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/scripts/wake_watchdog.py +0 -0
  185. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/scrub.py +0 -0
  186. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/service/__init__.py +0 -0
  187. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/service/app.py +0 -0
  188. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/service/providers.py +0 -0
  189. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/session_bridge.py +0 -0
  190. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/skills/i-have-adhd/LICENSE +0 -0
  191. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/skills/i-have-adhd/SKILL.md +0 -0
  192. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/source_text.py +0 -0
  193. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/codex-waker.default +0 -0
  194. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/peer-reply-drain.default +0 -0
  195. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-codex-outbox@.service +0 -0
  196. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-codex-outbox@.timer +0 -0
  197. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-codex-waker@.service +0 -0
  198. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-codex-waker@.timer +0 -0
  199. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-monitor-reexec.path +0 -0
  200. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-monitor-reexec.service +0 -0
  201. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-monitor@.service +0 -0
  202. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-peer-reply-drain@.service +0 -0
  203. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-peer-reply-drain@.timer +0 -0
  204. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-stuck-sweep.service +0 -0
  205. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-stuck-sweep.timer +0 -0
  206. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-triage.service +0 -0
  207. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-triage.timer +0 -0
  208. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-watchdog.default +0 -0
  209. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-watchdog.service +0 -0
  210. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/systemd/swarph-watchdog.timer +0 -0
  211. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/timeline_paths.py +0 -0
  212. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/tokens.py +0 -0
  213. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/triage/__init__.py +0 -0
  214. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/triage/backend.py +0 -0
  215. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/triage/job.py +0 -0
  216. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/triage/owners.json +0 -0
  217. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/triage/router.py +0 -0
  218. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/triage/rows.py +0 -0
  219. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli/triage/sensor.py +0 -0
  220. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli.egg-info/dependency_links.txt +0 -0
  221. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli.egg-info/entry_points.txt +0 -0
  222. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli.egg-info/requires.txt +0 -0
  223. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/src/swarph_cli.egg-info/top_level.txt +0 -0
  224. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1006_session_board.py +0 -0
  225. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1010_strand_only.py +0 -0
  226. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1013_spawn_channel.py +0 -0
  227. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1017_muse_tui.py +0 -0
  228. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1050_surrogate_wake.py +0 -0
  229. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1052_opencode_deaf.py +0 -0
  230. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1059_watchdog_unread_env.py +0 -0
  231. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1061_roster_cli.py +0 -0
  232. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1064_stuck_sweep.py +0 -0
  233. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1065_release.py +0 -0
  234. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1066_quiet_wakes.py +0 -0
  235. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1068_structured_accept_cli.py +0 -0
  236. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1071_quota_sync.py +0 -0
  237. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1073_triage.py +0 -0
  238. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1073_triage_board.py +0 -0
  239. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1073_wheel_install.py +0 -0
  240. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1075_task_cli.py +0 -0
  241. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_1083_openai_decisions.py +0 -0
  242. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_124_register_merge.py +0 -0
  243. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_126_pending_from_complete.py +0 -0
  244. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_132_ensure_monitor_state_dir.py +0 -0
  245. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_138_memory_navigate.py +0 -0
  246. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_139_tool_probe.py +0 -0
  247. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_183_card_anchor.py +0 -0
  248. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_184_notify_honesty.py +0 -0
  249. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_201_win32_bash_refusal.py +0 -0
  250. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_243_onboard_per_peer_token.py +0 -0
  251. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_307_task4_ask_reply.py +0 -0
  252. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_312_codegraph_fuzzy_verb.py +0 -0
  253. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_319_refusal_exit_codes.py +0 -0
  254. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_323_mistral_backend.py +0 -0
  255. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_332_report_organize_findings.py +0 -0
  256. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_356_query_filters.py +0 -0
  257. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_397_gh_identity_router.py +0 -0
  258. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_397_router_preflight.py +0 -0
  259. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_402_one_identity_resolver.py +0 -0
  260. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_432_rowclear.py +0 -0
  261. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_467b_onboard_operator_credential.py +0 -0
  262. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_472_register_caller_binding.py +0 -0
  263. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_484_codex_queue_sink.py +0 -0
  264. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_523_guide.py +0 -0
  265. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_524_conftest_hermeticity.py +0 -0
  266. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_532_accept_flag.py +0 -0
  267. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_535_version_capability.py +0 -0
  268. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_538_signal_bench.py +0 -0
  269. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_546_default_gateway.py +0 -0
  270. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_547_verbs_from_registry.py +0 -0
  271. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_548_gateway_remainder.py +0 -0
  272. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_552_codegraph_gateway.py +0 -0
  273. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_555_relay_row_shape.py +0 -0
  274. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_556_relay_freshness.py +0 -0
  275. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_559_edges_truncated.py +0 -0
  276. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_564_bootstrap_first_peer.py +0 -0
  277. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_578_no_machine_specific_host_defaults.py +0 -0
  278. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_579_register_bootstrap_message.py +0 -0
  279. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_591_cli_step_graph.py +0 -0
  280. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_644_monitor_supervision.py +0 -0
  281. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_648_install_unit.py +0 -0
  282. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_654_reexec.py +0 -0
  283. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_656_owned_slm.py +0 -0
  284. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_684_dreaming_verb.py +0 -0
  285. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_689_pkg_version_order.py +0 -0
  286. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_715_grok_wake.py +0 -0
  287. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_716_timeline_one_path.py +0 -0
  288. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_723_grok_0251.py +0 -0
  289. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_724_ps1_ascii_or_bom.py +0 -0
  290. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_725_stdio_reconfigure.py +0 -0
  291. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_726_grok_limit_screen.py +0 -0
  292. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_729_arm_check_delivery_gap.py +0 -0
  293. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_729_dm_once.py +0 -0
  294. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_729_wake_watchdog.py +0 -0
  295. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_734_dreaming_enrich_degrade.py +0 -0
  296. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_735_dm_mcp_tools.py +0 -0
  297. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_739_wake_writer.py +0 -0
  298. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_740_edit_project.py +0 -0
  299. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_762_cards_edit_priority.py +0 -0
  300. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_764_enrich_collapse.py +0 -0
  301. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_801_confirm_flow_cli.py +0 -0
  302. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_802_stage_history.py +0 -0
  303. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_825_codegraph_hook_noise.py +0 -0
  304. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_825_install_posttooluse_only.py +0 -0
  305. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_825_remaining_cap_shred_bind.py +0 -0
  306. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_829_counterfactual_column.py +0 -0
  307. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_830_hook_binding_version.py +0 -0
  308. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_84_cli_labels.py +0 -0
  309. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_866_doctrine_guide.py +0 -0
  310. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_872_identity_refuses_not_warns.py +0 -0
  311. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_874_source_text.py +0 -0
  312. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_888_opencode_data_dir_can_fail.py +0 -0
  313. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_937_dreaming_notify.py +0 -0
  314. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_938_organize_line_limit.py +0 -0
  315. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_941_bench_backends.py +0 -0
  316. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_941_harness_342.py +0 -0
  317. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_945_same_line_pairing.py +0 -0
  318. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_955_prompt_audit.py +0 -0
  319. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_957_auth_http.py +0 -0
  320. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_959_venv_interpreter.py +0 -0
  321. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_960_channel.py +0 -0
  322. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_960_ensure_monitor_heartbeat.py +0 -0
  323. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_961_cursor_grok_footer.py +0 -0
  324. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_961_loud_stop.py +0 -0
  325. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_963_plugin_manifest.py +0 -0
  326. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_964_channel_cell.py +0 -0
  327. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_965_mesh_wait.py +0 -0
  328. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_975_channel_hop.py +0 -0
  329. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_add_security_gate.py +0 -0
  330. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_artifact_add.py +0 -0
  331. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_artifact_hash.py +0 -0
  332. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_artifact_lib.py +0 -0
  333. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_artifact_mcp.py +0 -0
  334. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_artifact_skill.py +0 -0
  335. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_artifact_tool.py +0 -0
  336. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_artifact_uri.py +0 -0
  337. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_bench_backends.py +0 -0
  338. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_bench_claude_cli.py +0 -0
  339. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_bench_codex_cli.py +0 -0
  340. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_bench_command.py +0 -0
  341. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_bench_pack.py +0 -0
  342. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_bench_prices.py +0 -0
  343. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_bench_quality.py +0 -0
  344. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_bench_runner.py +0 -0
  345. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_bench_validate.py +0 -0
  346. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_board_card_thread.py +0 -0
  347. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_board_command.py +0 -0
  348. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_board_merge_check.py +0 -0
  349. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_board_obligation_close.py +0 -0
  350. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_brain_ask_command.py +0 -0
  351. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_brain_ask_env_diagnosis.py +0 -0
  352. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_brain_ask_identity_explicitness.py +0 -0
  353. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_brain_command.py +0 -0
  354. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_caller_meta_guard.py +0 -0
  355. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_capture_lineage.py +0 -0
  356. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_capture_liveness.py +0 -0
  357. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_capture_manifest.py +0 -0
  358. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_capture_paths.py +0 -0
  359. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_capture_security.py +0 -0
  360. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_cell_command_dispatch.py +0 -0
  361. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_cell_harden.py +0 -0
  362. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_cell_loader.py +0 -0
  363. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_cell_selfcheck.py +0 -0
  364. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_cell_verify.py +0 -0
  365. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_chain_token.py +0 -0
  366. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_channel_command.py +0 -0
  367. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_channel_poll_never_breaks_dms.py +0 -0
  368. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_channel_post.py +0 -0
  369. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_channel_wake_policy_filter.py +0 -0
  370. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_chat_command.py +0 -0
  371. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_claude_parser.py +0 -0
  372. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_claude_tmux_template.py +0 -0
  373. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_codegraph_caller_scope.py +0 -0
  374. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_codegraph_command.py +0 -0
  375. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_codegraph_hook.py +0 -0
  376. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_codegraph_mcp.py +0 -0
  377. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_codex_waker.py +0 -0
  378. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_compress_caller_convention.py +0 -0
  379. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_compress_command.py +0 -0
  380. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_compress_levers.py +0 -0
  381. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_compress_marker.py +0 -0
  382. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_compress_verify.py +0 -0
  383. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_console_encoding_e2e.py +0 -0
  384. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_content_composition.py +0 -0
  385. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_copilot_membrane.py +0 -0
  386. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_copilot_pane_reader.py +0 -0
  387. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_cursor_membrane.py +0 -0
  388. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_daemon_command.py +0 -0
  389. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_daemon_console_encoding.py +0 -0
  390. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_daemon_delivery.py +0 -0
  391. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_delivery_queue.py +0 -0
  392. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_display_sanitize.py +0 -0
  393. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_ensure_monitor_no_peer_default.py +0 -0
  394. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_event_emit.py +0 -0
  395. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_feature_to_uri.py +0 -0
  396. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_gateway_brain.py +0 -0
  397. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_gateway_client.py +0 -0
  398. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_gateway_command.py +0 -0
  399. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_gateway_message_idempotency.py +0 -0
  400. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_gh_route_doctor_mesh_name.py +0 -0
  401. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_group_command.py +0 -0
  402. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_guide_commands_parse.py +0 -0
  403. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_guide_selfcheck.py +0 -0
  404. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_heartbeat_check.py +0 -0
  405. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_highlight_command.py +0 -0
  406. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_hook_output.py +0 -0
  407. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_hooks_activity_marker.py +0 -0
  408. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_hooks_add.py +0 -0
  409. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_hooks_bundle.py +0 -0
  410. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_hooks_init.py +0 -0
  411. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_hooks_legacy_generation_removal.py +0 -0
  412. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_hooks_lifecycle.py +0 -0
  413. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_hooks_merge.py +0 -0
  414. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_hooks_verify.py +0 -0
  415. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_hooks_win32_bash_wrapper.py +0 -0
  416. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_hooks_win32_command_path.py +0 -0
  417. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_import_command.py +0 -0
  418. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_inbox_identity_provenance.py +0 -0
  419. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_init_command.py +0 -0
  420. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_init_provider_menu.py +0 -0
  421. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_install_codex_hooks.py +0 -0
  422. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_install_hook.py +0 -0
  423. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_install_multiplexer_command.py +0 -0
  424. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_install_postcompact_hook.py +0 -0
  425. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_install_wake_hook.py +0 -0
  426. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_lane_command.py +0 -0
  427. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_main.py +0 -0
  428. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_main_unknown_verb_guard.py +0 -0
  429. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_mcp_missing_hint.py +0 -0
  430. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_mcp_server.py +0 -0
  431. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_memory_command.py +0 -0
  432. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_memory_emit_snippet.py +0 -0
  433. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_memory_gateway.py +0 -0
  434. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_memory_sync.py +0 -0
  435. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_memory_sync_membrane.py +0 -0
  436. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_mesh_command.py +0 -0
  437. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_mesh_inbox_mark_read.py +0 -0
  438. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_mesh_inbox_sanitize.py +0 -0
  439. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_mesh_originate_thread_623.py +0 -0
  440. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_mesh_send_unknown_peer.py +0 -0
  441. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_mesh_sidecar.py +0 -0
  442. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_mesh_sidecar_cursor_decoupled.py +0 -0
  443. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_mesh_sidecar_muse_sink.py +0 -0
  444. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_mesh_sidecar_wake_survives_read.py +0 -0
  445. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_meta_edge_identity.py +0 -0
  446. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_monitor_channel_poll.py +0 -0
  447. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_monitor_cli.py +0 -0
  448. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_monitor_daemon_collision.py +0 -0
  449. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_monitor_self_name_verification.py +0 -0
  450. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_monitor_state_split.py +0 -0
  451. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_multiplexer.py +0 -0
  452. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_muse_membrane.py +0 -0
  453. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_muse_own_cli.py +0 -0
  454. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_obligation_close_is_surfaced.py +0 -0
  455. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_okf_links.py +0 -0
  456. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_onboard_command.py +0 -0
  457. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_opencode_plugin.py +0 -0
  458. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_operator_me.py +0 -0
  459. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_orphan_daemons.py +0 -0
  460. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_packaged_artifacts_exist.py +0 -0
  461. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_packaged_skills.py +0 -0
  462. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_peer_executor.py +0 -0
  463. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_peer_executor_windows.py +0 -0
  464. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_peer_reply_drain_command.py +0 -0
  465. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_peer_reply_drain_supervisor.py +0 -0
  466. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_peer_reply_outbox.py +0 -0
  467. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_peer_reply_transport.py +0 -0
  468. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_peer_service_e2e.py +0 -0
  469. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_peer_service_host.py +0 -0
  470. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_peer_service_payload.py +0 -0
  471. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_peer_service_reply.py +0 -0
  472. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_postcompact_recall.py +0 -0
  473. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_process_liveness.py +0 -0
  474. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_protocol_handler.py +0 -0
  475. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_providers_isolation.py +0 -0
  476. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_ratify_command.py +0 -0
  477. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_readme_claims_no_gateway_default.py +0 -0
  478. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_repl_caller_convention.py +0 -0
  479. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_schedule_command.py +0 -0
  480. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_schedule_create_contract.py +0 -0
  481. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_scrub.py +0 -0
  482. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_security.py +0 -0
  483. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_service_app.py +0 -0
  484. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_service_command.py +0 -0
  485. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_service_providers.py +0 -0
  486. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_session_bridge_inject.py +0 -0
  487. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_session_bridge_probe.py +0 -0
  488. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_session_bridge_resolve.py +0 -0
  489. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_session_path_role_gate.py +0 -0
  490. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_shipped_units_match_the_cli.py +0 -0
  491. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_smoke_chat.py +0 -0
  492. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_smoke_one_shot.py +0 -0
  493. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_smoke_phase_5_5.py +0 -0
  494. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_spawn_base_hoist.py +0 -0
  495. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_spawn_command.py +0 -0
  496. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_spawn_identity_stamp.py +0 -0
  497. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_spawn_live_pin.py +0 -0
  498. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_spawn_mitosis_lineage.py +0 -0
  499. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_spawn_tmux_session.py +0 -0
  500. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_spawn_windows_relaunch.py +0 -0
  501. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_subprocess_decode_encoding.py +0 -0
  502. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_timeline_command.py +0 -0
  503. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_tmux_wake_runstate_defer.py +0 -0
  504. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_tmux_wake_session_reanchor.py +0 -0
  505. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_tmux_wake_stale.py +0 -0
  506. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_tmux_wake_submit_verify.py +0 -0
  507. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_token_file_one_parser.py +0 -0
  508. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_token_precedence_explicit_first.py +0 -0
  509. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_unified_token_resolver.py +0 -0
  510. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_version_command.py +0 -0
  511. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_version_consistency.py +0 -0
  512. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_vibe_membrane.py +0 -0
  513. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_watchdog.py +0 -0
  514. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_watchdog_dm_wake.py +0 -0
  515. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_watchdog_dm_wake_cooldown.py +0 -0
  516. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_watchdog_dm_wake_wiring.py +0 -0
  517. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_watchdog_emit_health.py +0 -0
  518. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_watchdog_install_flags.py +0 -0
  519. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_watchdog_model_rung.py +0 -0
  520. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/tests/test_watchdog_stale_peers.py +0 -0
  521. {swarph_cli-0.72.20 → swarph_cli-0.72.22}/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.20
3
+ Version: 0.72.22
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.20"
7
+ version = "0.72.22"
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" }
@@ -153,7 +153,7 @@ where = ["src"]
153
153
  # installed 0.72.13 failed 'owner map unreadable' while the tree passed.
154
154
  # test_1073_wheel_install builds the wheel and runs the installed copy.
155
155
  swarph_cli = ["systemd/*.service", "systemd/*.timer", "systemd/*.default",
156
- "systemd/*.path",
156
+ "systemd/*.path", "launchd/*.plist",
157
157
  "scripts/*.sh", "scripts/*.ps1", "guide/*.md",
158
158
  "payloads/postcompact/*.sh", "payloads/postcompact/*.cmd",
159
159
  "payloads/opencode/*.js",
@@ -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.20"
19
+ __version__ = "0.72.22"
20
20
 
21
21
  __all__ = ["__version__"]
@@ -1013,6 +1013,7 @@ def _build_parser() -> argparse.ArgumentParser:
1013
1013
  ct = cards.add_parser("thread", help="show the card's conversation (#181: a card IS a thread)")
1014
1014
  ct.add_argument("id", type=int)
1015
1015
  ct.add_argument("--limit", type=int, default=None, help="max messages (gateway caps at 1000)")
1016
+ ct.add_argument("--json", action="store_true")
1016
1017
  _add_common(ct)
1017
1018
  cy = cards.add_parser("say", help="post a message onto the card's thread")
1018
1019
  cy.add_argument("id", type=int)
@@ -75,6 +75,12 @@ def run_hook(stdin_text: Optional[str] = None) -> int:
75
75
  res = ghid.resolve(peer or None)
76
76
  except ghid.RouterRefusal as exc:
77
77
  return _deny(str(exc))
78
+ except Exception as exc:
79
+ # >>> A CRASHED RESOLVER MUST DENY, NOT EXIT NON-ZERO. <<< Claude Code blocks a
80
+ # PreToolUse call only on exit 2 or a deny; any other failure lets `gh` run as
81
+ # the active account (#360). drop-on-meta-edge measured it on #1818.
82
+ return _deny(f"the identity resolver crashed, so no identity was resolved: "
83
+ f"{type(exc).__name__}: {exc}")
78
84
 
79
85
  rewritten = ghid.inject(command, res.login)
80
86
  updated = dict(payload.get("tool_input") or {})
@@ -97,7 +103,7 @@ def run_show() -> int:
97
103
  peer = identity.declared(env=identity.SELF_ONLY)[0] or ""
98
104
  try:
99
105
  res = ghid.resolve(peer or None)
100
- except ghid.RouterRefusal as exc:
106
+ except Exception as exc: # RouterRefusal, or a resolver crash: both are "no identity"
101
107
  print_safe(f"swarph gh-route: REFUSED\n {exc}", file=sys.stderr)
102
108
  return 1
103
109
  print_safe(f"cell {res.peer}")
@@ -145,7 +151,7 @@ def _cells_on_this_box() -> list:
145
151
  try:
146
152
  doc = yaml.safe_load(f.read_text(encoding="utf-8")) or {}
147
153
  name = doc.get("name") if isinstance(doc, dict) else None
148
- except OSError as exc:
154
+ except (OSError, UnicodeDecodeError, RecursionError) as exc:
149
155
  # >>> AN UNREADABLE CONFIG IS NOT A CELL NAMED AFTER ITS FILE. <<< The first
150
156
  # version's docstring promised this distinction and the CODE DID NOT MAKE IT:
151
157
  # OSError and no-name-found both set name=None and both fell through to
@@ -169,6 +175,25 @@ def _cells_on_this_box() -> list:
169
175
  return sorted(out)
170
176
 
171
177
 
178
+ def _any_yaml_login() -> bool:
179
+ """True when at least one cell yaml on this box carries a ``github:`` value. With no
180
+ json AND no yaml login the router is unconfigured, not merely incomplete."""
181
+ import yaml # local import — keeps `swarph --version` PyYAML-free (cell.py:254)
182
+
183
+ try:
184
+ files = sorted(cells_dir().glob("*.yaml"))
185
+ except OSError:
186
+ return False
187
+ for f in files:
188
+ try:
189
+ doc = yaml.safe_load(f.read_text(encoding="utf-8")) or {}
190
+ except Exception:
191
+ continue
192
+ if isinstance(doc, dict) and doc.get(ghid.YAML_KEY):
193
+ return True
194
+ return False
195
+
196
+
172
197
  def run_doctor() -> int:
173
198
  """Would installing the router REFUSE anyone on this box? Answer BEFORE installing.
174
199
 
@@ -185,9 +210,20 @@ def run_doctor() -> int:
185
210
  every command that mentions one inside a string.
186
211
 
187
212
  Exit 0 only when every cell on this box resolves. Non-zero is "do not install yet".
213
+
214
+ #1144: each cell is checked through ``ghid.resolve`` — THE SAME CALL THE HOOK MAKES —
215
+ so a yaml-mapped cell reads ok and a yaml/json disagreement reads REFUSED here
216
+ exactly as it would at the first `gh` call. A preflight that loads the json itself
217
+ asks a different question than the hook, the defect _cells_on_this_box records.
188
218
  """
219
+ mp = ghid.mapping_path()
189
220
  try:
190
- table = ghid.load_mapping()
221
+ if mp.exists():
222
+ ghid.load_mapping(mp) # an UNREADABLE json refuses every cell: say so once
223
+ elif not _any_yaml_login():
224
+ raise ghid.RouterRefusal(
225
+ f"no GitHub identity mapping at {mp}, and no cell yaml under "
226
+ f"{cells_dir()} carries '{ghid.YAML_KEY}:'.")
191
227
  except ghid.RouterRefusal as exc:
192
228
  print_safe(
193
229
  f"swarph gh-route doctor: REFUSED\n {exc}\n"
@@ -209,12 +245,19 @@ def run_doctor() -> int:
209
245
  file=sys.stderr)
210
246
  return 1
211
247
 
212
- unmapped = [c for c in cells if not isinstance(table.get(c), str) or not table.get(c)]
248
+ unmapped = []
213
249
  for c in cells:
214
- login = table.get(c)
215
- ok = isinstance(login, str) and login
216
- print(f" {'ok ' if ok else 'REFUSED'} {c} -> {login if ok else '(unmapped)'}")
217
- print(f"\nmapping: {ghid.mapping_path()}")
250
+ try:
251
+ res = ghid.resolve(c, cells=cells_dir())
252
+ except ghid.RouterRefusal as exc:
253
+ unmapped.append(c)
254
+ why = str(exc).splitlines()[0]
255
+ print_safe(f" REFUSED {c} -> (unmapped) [{why}]")
256
+ continue
257
+ where = "yaml" if res.source.endswith(".yaml") else "json"
258
+ print_safe(f" ok {c} -> {res.login} [{where}: {res.source}]")
259
+ print(f"\ncell yamls: {cells_dir()} (read first, key '{ghid.YAML_KEY}:')")
260
+ print(f"mapping: {mp} (fallback, retiring)")
218
261
  if unmapped:
219
262
  print(f">>> {len(unmapped)} of {len(cells)} cells on this box would be REFUSED: "
220
263
  f"{', '.join(unmapped)}")
@@ -23,6 +23,7 @@ import yaml
23
23
  from swarph_shared.cell import PEER_NAME_RE, parse_cell_dict
24
24
  from swarph_cli.cell import CLI_ENABLED_PROVIDERS, CellError, cells_dir
25
25
  from swarph_cli.gateway_default import env_gateway
26
+ from swarph_cli.gh_identity import LOGIN_RE
26
27
 
27
28
  _CODEX_SANDBOX_DEFAULT = "workspace-write"
28
29
  _CODEX_SANDBOX_VALUES = ("workspace-write", "read-only")
@@ -68,6 +69,7 @@ def _llm_choices() -> list:
68
69
  # Prompt helpers (interactive). All no-op when a flag already supplied the value.
69
70
  # ---------------------------------------------------------------------------
70
71
 
72
+
71
73
  def _ask(prompt: str, default: Optional[str] = None) -> str:
72
74
  suffix = f" [{default}]" if default else ""
73
75
  try:
@@ -134,6 +136,9 @@ def _build_parser() -> argparse.ArgumentParser:
134
136
  p.add_argument("--assisted-memory", dest="assisted_memory", default=None, metavar="REPO",
135
137
  help="enable git-backed memory at REPO (SSH→HTTPS normalized)")
136
138
  p.add_argument("--starter", default=None)
139
+ p.add_argument("--github", default=None, metavar="LOGIN",
140
+ help="GitHub login gh-route injects for this cell (#1144). No default: "
141
+ "without it the cell is refused by gh-route where the hook is installed")
137
142
  p.add_argument("--symlink-cwd", dest="symlink_cwd", action="store_true")
138
143
  p.add_argument("--force", action="store_true")
139
144
  p.add_argument("--non-interactive", "-y", dest="non_interactive", action="store_true",
@@ -209,6 +214,21 @@ def run_init(argv: list[str]) -> int:
209
214
  if args.starter:
210
215
  cell["starter_prompt_path"] = args.starter
211
216
 
217
+ # ── GitHub login (#1144) ──
218
+ # >>> NO DEFAULT, AND NEVER THE ACTIVE `gh` ACCOUNT. <<< A login filled from
219
+ # `gh auth status` makes the cell act as whoever happens to be logged in, which is
220
+ # the #360 substitution gh-route refuses. Blank stays blank; gh-route then refuses
221
+ # the cell, and the line below says so at creation instead of at its first push.
222
+ github = (args.github or "").strip()
223
+ if not github and interactive:
224
+ github = _ask("GitHub login this cell acts as (blank = none yet)").strip()
225
+ if github:
226
+ if not LOGIN_RE.fullmatch(github):
227
+ print(f"swarph init: --github {github!r} is not a valid GitHub login",
228
+ file=sys.stderr)
229
+ return 2
230
+ cell["github"] = github
231
+
212
232
  # ── assisted memory (y/n) ──
213
233
  am_repo = args.assisted_memory
214
234
  if am_repo is None and interactive and _ask_yn("Use assisted memory (git-backed durable memory)?", False):
@@ -254,6 +274,12 @@ def run_init(argv: list[str]) -> int:
254
274
  print(f" tmux_session={cell['tmux_session']} cursor_path={cell['cursor_path']}")
255
275
  if "assisted_memory" in cell:
256
276
  print(f" assisted_memory.repo={cell['assisted_memory']['repo']} (enabled)")
277
+ if "github" in cell:
278
+ print(f" github={cell['github']}")
279
+ else:
280
+ print(f" github=(none) — >>> gh-route will REFUSE every `gh` call from {name} "
281
+ f"once its hook is installed on this box. <<< Set it by adding "
282
+ f"`github: <login>` to {dest}.")
257
283
 
258
284
  # Registration is NOT done here (R1 token mint-once is a once-only secret —
259
285
  # init scaffolding from the operator's context shouldn't capture another
@@ -3535,7 +3535,8 @@ def _monitor_deliver(state: MonitorState) -> None:
3535
3535
  from swarph_cli import stall_alert
3536
3536
  if stall_alert.is_alert_tick(ticks):
3537
3537
  stall_alert.send_stall_alert(
3538
- state.gateway, state.token, state.self_name, ticks, len(dms)
3538
+ state.gateway, state.token, state.self_name, ticks,
3539
+ stall_alert.pending_count(dms, state.self_name)
3539
3540
  )
3540
3541
  changed = True
3541
3542
  # #1010: name the deferral's real cause — a hardcoded
@@ -3065,6 +3065,10 @@ def _opencode_env(cell: Cell) -> dict[str, str]:
3065
3065
  # an operator's own disable would otherwise be lost, not preserved).
3066
3066
  env["OPENCODE_DISABLE_CLAUDE_CODE"] = "1"
3067
3067
  env["OPENCODE_DISABLE_EXTERNAL_SKILLS"] = "1"
3068
+ # $HOME is shared, but gh does not use it unless GH_CONFIG_DIR is set.
3069
+ # Keep a parent value; otherwise point the cell at $HOME/.config/gh.
3070
+ if "GH_CONFIG_DIR" not in env:
3071
+ env["GH_CONFIG_DIR"] = str(Path.home() / ".config" / "gh")
3068
3072
  # NOTE (2026-09-16, probe): the plugin's `experimental.chat.system.transform`
3069
3073
  # fires WITHOUT the OPENCODE_EXPERIMENTAL umbrella (measured on 1.18.30), so
3070
3074
  # we do NOT set it — widening the experimental surface for a flag the hook
@@ -24,12 +24,29 @@ consistent, so no server-side control can fire.
24
24
  THE MAPPING IS OPERATOR DATA, NOT SHIPPED DATA. A wrong mapping is a silent identity
25
25
  substitution, so this module ships NO defaults and NO built-in table: an absent or
26
26
  incomplete mapping is a REFUSAL, never a guess.
27
+
28
+ #1144 — THE CELL CARRIES ITS OWN LOGIN. A cell's yaml (``github: <login>``) is read
29
+ FIRST; ``gh-identities.json`` is the fallback for one release and is then retired. The
30
+ commander, 2026-10-14: "you are all suppose to have that identity in your cell yaml".
31
+ The json held 2 cells for two months while the rest were refused at their first push
32
+ (#1096), days after they were created. A field set at ``swarph init`` puts the gap at
33
+ creation instead.
34
+
35
+ >>> A CELL IS FOUND BY ITS ``name:``, NEVER BY ITS FILENAME. <<< ``lab.yaml`` carries
36
+ ``name: lab-ovh``, and SWARPH_SELF is the mesh name — the same split ``gh-route doctor``
37
+ was fixed for (_cells_on_this_box).
38
+
39
+ >>> YAML AND JSON DISAGREEING IS A REFUSAL, NOT "YAML WINS". <<< During the fallback
40
+ release both can name a login for one cell. Picking either silently is the identity
41
+ substitution this module exists to end, one layer up; the operator decides which is
42
+ right and deletes the other.
27
43
  """
28
44
  from __future__ import annotations
29
45
 
30
46
  import json
31
47
  import os
32
48
  import re
49
+ import shlex
33
50
  from dataclasses import dataclass
34
51
  from pathlib import Path
35
52
  from typing import Optional
@@ -119,14 +136,87 @@ def load_mapping(path: Optional[Path] = None) -> dict:
119
136
  try:
120
137
  data = json.loads(p.read_text(encoding="utf-8"))
121
138
  except Exception as exc:
122
- raise RouterRefusal(f"GitHub identity mapping at {p} is unreadable: {exc}")
139
+ raise RouterRefusal(f"GitHub identity mapping at {p} is unreadable: {exc}. "
140
+ f"Fix it, or delete it if every cell's yaml carries '{YAML_KEY}:'.")
123
141
  if not isinstance(data, dict):
124
142
  raise RouterRefusal(f"GitHub identity mapping at {p} must be a JSON object")
125
143
  return data
126
144
 
127
145
 
128
- def resolve(peer: Optional[str], path: Optional[Path] = None) -> Resolution:
129
- """peer -> Resolution, or RouterRefusal. Never returns a fallback."""
146
+ #: The cell-yaml key that names the cell's GitHub login (#1144).
147
+ YAML_KEY = "github"
148
+
149
+ #: GitHub's login grammar. The login is spliced into the hook's shell command, so a
150
+ #: value outside it is refused, never quoted-and-hoped (#1144 security review).
151
+ LOGIN_RE = re.compile(r"[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}")
152
+
153
+
154
+ def _checked(peer: str, login: str, source) -> "Resolution":
155
+ if not LOGIN_RE.fullmatch(login):
156
+ raise RouterRefusal(
157
+ f"{source}: GitHub login for {peer!r} is not a valid GitHub login: {login!r}")
158
+ return Resolution(peer=peer, login=login, source=str(source))
159
+
160
+
161
+ def _cells_dir() -> Path:
162
+ from swarph_cli.cell import cells_dir # local: cell.py is the one owner of the path
163
+ return cells_dir()
164
+
165
+
166
+ def yaml_claims(peer: str, directory: Optional[Path] = None, key: str = YAML_KEY):
167
+ """Every cell yaml that declares mesh name ``peer`` -> ``([(value, path)], unreadable)``.
168
+
169
+ ``key`` names the yaml key to read (default ``github``; stall_alert reads
170
+ ``responsible``, card #1135) so there is ONE yaml reader, not two.
171
+ ``value`` is the raw value (None when the file has no such key), so the
172
+ caller can tell "no yaml for this cell" from "a yaml that maps nothing". A file with
173
+ no ``name:`` is the cell named by its stem — the same rule as _cells_on_this_box.
174
+ ``unreadable`` lists files that could not be parsed: they may be this cell, so a
175
+ refusal names them rather than reading as "not mapped".
176
+ """
177
+ import yaml # local import — keeps `swarph --version` PyYAML-free (cell.py:254)
178
+
179
+ d = directory or _cells_dir()
180
+ claims, unreadable = [], []
181
+ try:
182
+ files = sorted(d.glob("*.yaml"))
183
+ except OSError:
184
+ return claims, unreadable
185
+ for f in files:
186
+ try:
187
+ doc = yaml.safe_load(f.read_text(encoding="utf-8")) or {}
188
+ except Exception:
189
+ # Not just OSError/YAMLError: a UTF-16 file (a PowerShell 5.1 redirect) raises
190
+ # UnicodeDecodeError and deep nesting raises RecursionError. Either escaping
191
+ # here crashed the hook, and a crashed hook lets `gh` run as the active
192
+ # account (#360) for every cell on the box (drop-on-meta-edge, #1818).
193
+ unreadable.append(f)
194
+ continue
195
+ if not isinstance(doc, dict):
196
+ unreadable.append(f)
197
+ continue
198
+ name = doc.get("name")
199
+ if (name if isinstance(name, str) and name else f.stem) == peer:
200
+ claims.append((doc.get(key), f))
201
+ return claims, unreadable
202
+
203
+
204
+ def _optional_mapping(path: Optional[Path]) -> Optional[dict]:
205
+ """The json table, or None when the file is ABSENT. Absent is now a normal state
206
+ (the yaml carries the login); an UNREADABLE file still refuses via load_mapping."""
207
+ p = path or mapping_path()
208
+ if not p.exists():
209
+ return None
210
+ return load_mapping(p)
211
+
212
+
213
+ def resolve(peer: Optional[str], path: Optional[Path] = None,
214
+ cells: Optional[Path] = None) -> Resolution:
215
+ """peer -> Resolution, or RouterRefusal. Never returns a fallback.
216
+
217
+ Order (#1144): the cell's yaml ``github:``, then gh-identities.json. Both present
218
+ and different is a refusal.
219
+ """
130
220
  if not peer:
131
221
  raise RouterRefusal(
132
222
  "SWARPH_SELF is unset, so this cell has no mesh identity to route from.\n"
@@ -135,21 +225,69 @@ def resolve(peer: Optional[str], path: Optional[Path] = None) -> Resolution:
135
225
  " 6 of 6 cells (#243) and the direct cause of #360.\n"
136
226
  " Set SWARPH_SELF, or pass GH_TOKEN=... explicitly for a one-off."
137
227
  )
138
- table = load_mapping(path)
228
+ claims, unreadable = yaml_claims(peer, cells)
229
+ mapped = [(v, f) for v, f in claims if v is not None]
230
+ for v, f in mapped:
231
+ if not isinstance(v, str) or not v.strip():
232
+ raise RouterRefusal(
233
+ f"{f}: '{YAML_KEY}:' for {peer!r} must be a non-empty string, "
234
+ f"got {v!r}")
235
+ yaml_logins = sorted({v.strip() for v, _ in mapped})
236
+ if len(yaml_logins) > 1:
237
+ # Two configs claiming one mesh name with different logins: either could be
238
+ # the live one, and picking is a guess.
239
+ raise RouterRefusal(
240
+ f"cell {peer!r} is claimed by {len(mapped)} cell yamls with different "
241
+ f"GitHub logins:\n"
242
+ + "".join(f" {f}: {YAML_KEY}: {v}\n" for v, f in mapped)
243
+ + " >>> REFUSING RATHER THAN PICKING ONE. <<< Keep one config per cell.")
244
+
245
+ p = path or mapping_path()
246
+ if yaml_logins:
247
+ table = _optional_mapping(path) or {}
248
+ jl = table.get(peer)
249
+ if jl is not None and jl != yaml_logins[0]:
250
+ raise RouterRefusal(
251
+ f"cell {peer!r} has two GitHub identities that disagree:\n"
252
+ f" {mapped[0][1]}: {YAML_KEY}: {yaml_logins[0]}\n"
253
+ f" {p}: {jl!r}\n"
254
+ f" >>> REFUSING RATHER THAN LETTING EITHER WIN. <<< The yaml is the\n"
255
+ f" source of truth from #1144 on: fix whichever is wrong, then delete\n"
256
+ f" {peer!r} from {p.name}.")
257
+ return _checked(peer, yaml_logins[0], mapped[0][1])
258
+
259
+ table = _optional_mapping(path)
260
+ if table is None:
261
+ raise RouterRefusal(
262
+ f"cell {peer!r} has no '{YAML_KEY}:' in its cell yaml under {cells or _cells_dir()},\n"
263
+ f" and there is no GitHub identity mapping at {p} either.\n"
264
+ f" The router refuses rather than using whichever `gh` account happens\n"
265
+ f" to be active — an ambient identity is how a cell runs for days as\n"
266
+ f" another cell (#360) with every request internally consistent.\n"
267
+ f" Add `{YAML_KEY}: <github-login>` to the cell's yaml"
268
+ f" (`swarph init --github` writes it).\n"
269
+ + _unreadable_note(unreadable))
139
270
  login = table.get(peer)
140
271
  if not login:
141
- p = path or mapping_path()
142
272
  raise RouterRefusal(
143
- f"cell {peer!r} has no GitHub identity in {p}.\n"
144
- f" Known cells: {', '.join(sorted(table)) or '(none)'}\n"
273
+ f"cell {peer!r} has no GitHub identity: no '{YAML_KEY}:' in its cell yaml"
274
+ f" under {cells or _cells_dir()}, and none in {p}.\n"
275
+ f" Known cells in {p.name}: {', '.join(sorted(table)) or '(none)'}\n"
145
276
  f" >>> REFUSING RATHER THAN USING THE ACTIVE ACCOUNT. <<< Falling back\n"
146
277
  f" would attribute {peer}'s action to whoever is logged in, and GitHub's\n"
147
278
  f" own gates key on the CREDENTIAL, not on who did the work.\n"
148
- f" Add \"{peer}\": \"<github-login>\" to that file, or pass GH_TOKEN=... explicitly."
149
- )
279
+ f" Add `{YAML_KEY}: <github-login>` to the cell's yaml, or pass GH_TOKEN=... explicitly.\n"
280
+ + _unreadable_note(unreadable))
150
281
  if not isinstance(login, str):
151
282
  raise RouterRefusal(f"mapping for {peer!r} must be a string, got {type(login).__name__}")
152
- return Resolution(peer=peer, login=login, source=str(path or mapping_path()))
283
+ return _checked(peer, login, p)
284
+
285
+
286
+ def _unreadable_note(unreadable) -> str:
287
+ if not unreadable:
288
+ return ""
289
+ return (" NOT READ (may be this cell's config): "
290
+ + ", ".join(str(f) for f in unreadable) + "\n")
153
291
 
154
292
 
155
293
  def targets_gh(command: str) -> bool:
@@ -195,4 +333,4 @@ def inject(command: str, login: str) -> str:
195
333
  per-invocation property wanted — it is not `gh auth switch`, and it touches no
196
334
  global state and no other session.
197
335
  """
198
- return f'export GH_TOKEN=$(gh auth token --user {login}); {command}'
336
+ return f'export GH_TOKEN=$(gh auth token --user {shlex.quote(login)}); {command}'
@@ -0,0 +1,33 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <!-- card #1195. Rendered from systemd/swarph-codex-outbox@.service by launchd_render.py. Do not edit by hand. -->
4
+ <plist version="1.0">
5
+ <dict>
6
+ <key>Label</key>
7
+ <string>tech.brainsurfing.swarph.codex-outbox.__PEER__</string>
8
+ <key>ProgramArguments</key>
9
+ <array>
10
+ <string>__SWARPH_BIN__</string>
11
+ <string>codex-waker</string>
12
+ <string>--drain-outbox</string>
13
+ <string>--self</string>
14
+ <string>__PEER__</string>
15
+ <string>--state-dir</string>
16
+ <string>__SWARPH_WAKER_STATE_DIR__</string>
17
+ <string>--cwd</string>
18
+ <string>__SWARPH_WAKER_CWD__</string>
19
+ <string>--outbox-dir</string>
20
+ <string>__SWARPH_OUTBOX_DIR__</string>
21
+ <string>--gateway</string>
22
+ <string>__SWARPH_GATEWAY__</string>
23
+ <string>--token-file</string>
24
+ <string>__SWARPH_TOKEN_FILE__</string>
25
+ </array>
26
+ <key>RunAtLoad</key>
27
+ <false/>
28
+ <key>StandardOutPath</key>
29
+ <string>__LOG_DIR__/launchd.out.log</string>
30
+ <key>StandardErrorPath</key>
31
+ <string>__LOG_DIR__/launchd.err.log</string>
32
+ </dict>
33
+ </plist>
@@ -0,0 +1,35 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <!-- card #1195. Rendered from systemd/swarph-codex-outbox@.service + systemd/swarph-codex-outbox@.timer by launchd_render.py. Do not edit by hand. -->
4
+ <plist version="1.0">
5
+ <dict>
6
+ <key>Label</key>
7
+ <string>tech.brainsurfing.swarph.codex-outbox.timer.__PEER__</string>
8
+ <key>ProgramArguments</key>
9
+ <array>
10
+ <string>__SWARPH_BIN__</string>
11
+ <string>codex-waker</string>
12
+ <string>--drain-outbox</string>
13
+ <string>--self</string>
14
+ <string>__PEER__</string>
15
+ <string>--state-dir</string>
16
+ <string>__SWARPH_WAKER_STATE_DIR__</string>
17
+ <string>--cwd</string>
18
+ <string>__SWARPH_WAKER_CWD__</string>
19
+ <string>--outbox-dir</string>
20
+ <string>__SWARPH_OUTBOX_DIR__</string>
21
+ <string>--gateway</string>
22
+ <string>__SWARPH_GATEWAY__</string>
23
+ <string>--token-file</string>
24
+ <string>__SWARPH_TOKEN_FILE__</string>
25
+ </array>
26
+ <key>RunAtLoad</key>
27
+ <true/>
28
+ <key>StartInterval</key>
29
+ <integer>15</integer>
30
+ <key>StandardOutPath</key>
31
+ <string>__LOG_DIR__/launchd.out.log</string>
32
+ <key>StandardErrorPath</key>
33
+ <string>__LOG_DIR__/launchd.err.log</string>
34
+ </dict>
35
+ </plist>
@@ -0,0 +1,39 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <!-- card #1195. Rendered from systemd/swarph-monitor@.service by launchd_render.py. Do not edit by hand. -->
4
+ <plist version="1.0">
5
+ <dict>
6
+ <key>Label</key>
7
+ <string>tech.brainsurfing.swarph.monitor.__PEER__</string>
8
+ <key>ProgramArguments</key>
9
+ <array>
10
+ <string>__SWARPH_BIN__</string>
11
+ <string>monitor</string>
12
+ <string>start</string>
13
+ <string>--as</string>
14
+ <string>__PEER__</string>
15
+ <string>--deliver</string>
16
+ <string>pull</string>
17
+ <string>--foreground</string>
18
+ </array>
19
+ <key>RunAtLoad</key>
20
+ <true/>
21
+ <key>KeepAlive</key>
22
+ <true/>
23
+ <key>ThrottleInterval</key>
24
+ <integer>10</integer>
25
+ <key>EnvironmentVariables</key>
26
+ <dict>
27
+ <key>SWARPH_SELF</key>
28
+ <string>__PEER__</string>
29
+ <key>HOME</key>
30
+ <string>__HOME__</string>
31
+ <key>MESH_GATEWAY_URL</key>
32
+ <string>__GATEWAY__</string>
33
+ </dict>
34
+ <key>StandardOutPath</key>
35
+ <string>__LOG_DIR__/launchd.out.log</string>
36
+ <key>StandardErrorPath</key>
37
+ <string>__LOG_DIR__/launchd.err.log</string>
38
+ </dict>
39
+ </plist>
@@ -0,0 +1,21 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <!-- card #1195. Rendered from systemd/swarph-watchdog.service by launchd_render.py. Do not edit by hand. -->
4
+ <plist version="1.0">
5
+ <dict>
6
+ <key>Label</key>
7
+ <string>tech.brainsurfing.swarph.watchdog</string>
8
+ <key>ProgramArguments</key>
9
+ <array>
10
+ <string>__SWARPH_BIN__</string>
11
+ <string>watchdog</string>
12
+ <string>--check</string>
13
+ </array>
14
+ <key>RunAtLoad</key>
15
+ <false/>
16
+ <key>StandardOutPath</key>
17
+ <string>__LOG_DIR__/launchd.out.log</string>
18
+ <key>StandardErrorPath</key>
19
+ <string>__LOG_DIR__/launchd.err.log</string>
20
+ </dict>
21
+ </plist>
@@ -0,0 +1,23 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <!-- card #1195. Rendered from systemd/swarph-watchdog.service + systemd/swarph-watchdog.timer by launchd_render.py. Do not edit by hand. -->
4
+ <plist version="1.0">
5
+ <dict>
6
+ <key>Label</key>
7
+ <string>tech.brainsurfing.swarph.watchdog.timer</string>
8
+ <key>ProgramArguments</key>
9
+ <array>
10
+ <string>__SWARPH_BIN__</string>
11
+ <string>watchdog</string>
12
+ <string>--check</string>
13
+ </array>
14
+ <key>RunAtLoad</key>
15
+ <true/>
16
+ <key>StartInterval</key>
17
+ <integer>300</integer>
18
+ <key>StandardOutPath</key>
19
+ <string>__LOG_DIR__/launchd.out.log</string>
20
+ <key>StandardErrorPath</key>
21
+ <string>__LOG_DIR__/launchd.err.log</string>
22
+ </dict>
23
+ </plist>