xdog-coding 2.4.3__tar.gz → 2.4.5__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 (290) hide show
  1. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/.gitignore +3 -0
  2. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/PKG-INFO +139 -15
  3. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/README.md +133 -10
  4. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/pyproject.toml +6 -5
  5. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/__init__.py +1 -1
  6. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/acp/backend.py +52 -30
  7. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/acp/server.py +33 -18
  8. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/cli/session_picker.py +8 -4
  9. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/config.py +33 -10
  10. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/agent_session.py +440 -221
  11. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/canonical_source.py +1 -1
  12. xdog_coding-2.4.5/src/xdog/coding/core/capability_ports.py +261 -0
  13. xdog_coding-2.4.5/src/xdog/coding/core/child_agents.py +674 -0
  14. xdog_coding-2.4.5/src/xdog/coding/core/child_extensions.py +236 -0
  15. xdog_coding-2.4.5/src/xdog/coding/core/child_runtime.py +1769 -0
  16. xdog_coding-2.4.5/src/xdog/coding/core/child_store.py +452 -0
  17. xdog_coding-2.4.5/src/xdog/coding/core/command_names.py +19 -0
  18. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/permissions.py +97 -6
  19. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/prompt_templates.py +5 -8
  20. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/resource_loader.py +46 -26
  21. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sdk.py +35 -57
  22. xdog_coding-2.4.5/src/xdog/coding/core/session_history.py +23 -0
  23. xdog_coding-2.4.5/src/xdog/coding/core/session_info.py +55 -0
  24. xdog_coding-2.4.5/src/xdog/coding/core/session_lifecycle.py +159 -0
  25. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/session_manager.py +93 -30
  26. xdog_coding-2.4.5/src/xdog/coding/core/session_preparation.py +20 -0
  27. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/session_staging.py +4 -0
  28. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/controller.py +303 -46
  29. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/intake.py +1 -0
  30. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/models.py +4 -0
  31. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/ownership.py +8 -2
  32. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/runtime.py +58 -64
  33. xdog_coding-2.4.5/src/xdog/coding/core/sessions/store.py +251 -0
  34. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/slash_commands.py +81 -22
  35. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/system_prompt.py +14 -10
  36. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/main.py +22 -39
  37. xdog_coding-2.4.5/src/xdog/coding/modes/interactive/child_messages.py +140 -0
  38. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/components/chat_log.py +52 -7
  39. xdog_coding-2.4.5/src/xdog/coding/modes/interactive/components/custom_editor.py +21 -0
  40. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/components/tool_execution.py +28 -47
  41. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/interactive_mode.py +126 -70
  42. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/provider_auth.py +1 -1
  43. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/session_events.py +40 -9
  44. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/session_presenter.py +89 -31
  45. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/theme.py +6 -0
  46. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/extension_session_helpers.py +1 -1
  47. xdog_coding-2.4.5/tests/goal_installed_consumer.py +156 -0
  48. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_access_scope.py +6 -2
  49. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_acp_artifact_contract.py +5 -7
  50. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_acp_offline_inbox.py +2 -2
  51. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_acp_review_regressions.py +4 -6
  52. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_active_tool_persistence.py +1 -1
  53. xdog_coding-2.4.5/tests/test_admission_navigation_owner.py +201 -0
  54. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_batch_mode_errors.py +6 -3
  55. xdog_coding-2.4.5/tests/test_capability_availability.py +155 -0
  56. xdog_coding-2.4.5/tests/test_capability_execution.py +212 -0
  57. xdog_coding-2.4.5/tests/test_capability_execution_recovery.py +402 -0
  58. xdog_coding-2.4.5/tests/test_capability_ports.py +91 -0
  59. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_child_active_tools.py +11 -7
  60. xdog_coding-2.4.5/tests/test_child_agent_lifetime.py +81 -0
  61. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_child_agents.py +65 -58
  62. xdog_coding-2.4.5/tests/test_child_call_admission.py +320 -0
  63. xdog_coding-2.4.5/tests/test_child_continuation.py +473 -0
  64. xdog_coding-2.4.5/tests/test_child_control_permissions.py +225 -0
  65. xdog_coding-2.4.5/tests/test_child_host_boundary.py +464 -0
  66. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_child_image_admission.py +8 -8
  67. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_child_image_submission.py +6 -6
  68. xdog_coding-2.4.5/tests/test_child_messages.py +492 -0
  69. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_child_queue_ui.py +8 -8
  70. xdog_coding-2.4.5/tests/test_child_runtime_contract.py +78 -0
  71. xdog_coding-2.4.5/tests/test_child_tool_scopes.py +366 -0
  72. xdog_coding-2.4.5/tests/test_cli_extension_trust.py +69 -0
  73. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_compaction_recovery.py +2 -2
  74. xdog_coding-2.4.5/tests/test_effective_configuration.py +88 -0
  75. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_extension_core_readonly.py +7 -7
  76. xdog_coding-2.4.5/tests/test_external_input_preview.py +208 -0
  77. xdog_coding-2.4.5/tests/test_goal_adapter.py +187 -0
  78. xdog_coding-2.4.5/tests/test_goal_child_wakeup.py +235 -0
  79. xdog_coding-2.4.5/tests/test_goal_effect_approvals.py +72 -0
  80. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_goal_extension_views.py +31 -79
  81. xdog_coding-2.4.5/tests/test_goal_lifecycle.py +224 -0
  82. xdog_coding-2.4.5/tests/test_goal_progress.py +55 -0
  83. xdog_coding-2.4.5/tests/test_goal_scoped_children.py +239 -0
  84. xdog_coding-2.4.5/tests/test_history_commit_owner.py +114 -0
  85. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_image_lifecycle_admission.py +1 -1
  86. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_inbox_auto_consume.py +3 -2
  87. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_inbox_controller.py +2 -2
  88. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_inbox_store.py +20 -3
  89. xdog_coding-2.4.5/tests/test_input_store_capacity.py +106 -0
  90. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_interactive_commands.py +1 -1
  91. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_interactive_mode.py +2 -3
  92. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_live_extensions.py +5 -1
  93. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_mcp_modern_browser_ui.py +1 -1
  94. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_native_session_queue.py +1 -1
  95. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_no_coding_rpc.py +2 -3
  96. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_owned_native_model.py +1 -1
  97. xdog_coding-2.4.5/tests/test_owner_review_regressions.py +202 -0
  98. xdog_coding-2.4.5/tests/test_panel_theme.py +55 -0
  99. xdog_coding-2.4.5/tests/test_permission_effects.py +305 -0
  100. xdog_coding-2.4.5/tests/test_prompt_preparation.py +103 -0
  101. xdog_coding-2.4.5/tests/test_public_extension_commands.py +90 -0
  102. xdog_coding-2.4.5/tests/test_queued_steering.py +246 -0
  103. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_readonly_ui.py +21 -2
  104. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_rendered_image_context.py +1 -1
  105. xdog_coding-2.4.5/tests/test_resource_loader.py +76 -0
  106. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_runtime_prompt.py +21 -19
  107. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_saved_child_drafts.py +1 -1
  108. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_sdk_runtime_compatibility.py +21 -6
  109. xdog_coding-2.4.5/tests/test_session_close_owner.py +345 -0
  110. xdog_coding-2.4.5/tests/test_session_identity_boundaries.py +153 -0
  111. xdog_coding-2.4.5/tests/test_session_info_tool.py +150 -0
  112. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_message_display.py +35 -3
  113. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_mode_routing.py +2 -1
  114. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_name_ui.py +2 -2
  115. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_ownership.py +7 -6
  116. xdog_coding-2.4.5/tests/test_session_permission_commands.py +310 -0
  117. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_smoke.py +2 -2
  118. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_staging.py +1 -1
  119. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_slash_commands.py +19 -0
  120. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_slash_skills.py +4 -3
  121. xdog_coding-2.4.5/tests/test_system_message_alignment.py +37 -0
  122. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_terminal_acceptance.py +71 -1
  123. xdog_coding-2.4.5/tests/test_tool_message_layout.py +151 -0
  124. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_tools_browser.py +3 -3
  125. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_tui_usability.py +40 -11
  126. xdog_coding-2.4.3/src/xdog/coding/core/child_agents.py +0 -251
  127. xdog_coding-2.4.3/src/xdog/coding/core/extensions/__init__.py +0 -1
  128. xdog_coding-2.4.3/src/xdog/coding/core/extensions/loader.py +0 -116
  129. xdog_coding-2.4.3/src/xdog/coding/core/extensions/runner.py +0 -79
  130. xdog_coding-2.4.3/src/xdog/coding/core/extensions/types.py +0 -11
  131. xdog_coding-2.4.3/src/xdog/coding/core/goal_adapter.py +0 -366
  132. xdog_coding-2.4.3/src/xdog/coding/core/sessions/store.py +0 -151
  133. xdog_coding-2.4.3/src/xdog/coding/modes/interactive/components/custom_editor.py +0 -30
  134. xdog_coding-2.4.3/tests/goal_installed_consumer.py +0 -233
  135. xdog_coding-2.4.3/tests/test_goal_adapter.py +0 -302
  136. xdog_coding-2.4.3/tests/test_goal_lifecycle.py +0 -268
  137. xdog_coding-2.4.3/tests/test_resource_loader.py +0 -50
  138. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/LICENSE +0 -0
  139. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/LICENSE-EXCEPTION.md +0 -0
  140. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/acp/__init__.py +0 -0
  141. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/acp/bridge.py +0 -0
  142. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/acp/cli.py +0 -0
  143. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/acp/client.py +0 -0
  144. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/acp/extensions.py +0 -0
  145. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/acp/ingress.py +0 -0
  146. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/acp/ingress_backend.py +0 -0
  147. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/acp/ingress_main.py +0 -0
  148. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/cli/__init__.py +0 -0
  149. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/cli/args.py +0 -0
  150. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/cli/config_selector.py +0 -0
  151. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/cli/enqueue.py +0 -0
  152. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/cli/file_processor.py +0 -0
  153. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/cli/initial_message.py +0 -0
  154. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/cli/list_models.py +0 -0
  155. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/__init__.py +0 -0
  156. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/bash_executor.py +0 -0
  157. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/compaction/__init__.py +0 -0
  158. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/compaction/compaction.py +0 -0
  159. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/compaction/utils.py +0 -0
  160. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/context_messages.py +0 -0
  161. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/defaults.py +0 -0
  162. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/event_bus.py +0 -0
  163. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/exec_utils.py +0 -0
  164. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/inbox_commands.py +0 -0
  165. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/keybindings.py +0 -0
  166. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/messages.py +0 -0
  167. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/model_catalog.py +0 -0
  168. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/navigation.py +0 -0
  169. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/remote_session.py +0 -0
  170. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/__init__.py +0 -0
  171. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/availability.py +0 -0
  172. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/batches.py +0 -0
  173. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/inbox_models.py +0 -0
  174. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/inbox_runtime.py +0 -0
  175. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/inbox_store.py +0 -0
  176. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/inbox_views.py +0 -0
  177. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/operations.py +0 -0
  178. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/router.py +0 -0
  179. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/sessions/turns.py +0 -0
  180. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/settings_manager.py +0 -0
  181. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/timings.py +0 -0
  182. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/tools/__init__.py +0 -0
  183. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/core/transcript_source.py +0 -0
  184. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/__init__.py +0 -0
  185. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/__init__.py +0 -0
  186. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/components/__init__.py +0 -0
  187. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/components/assistant_message.py +0 -0
  188. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/components/editor_layout.py +0 -0
  189. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/components/footer.py +0 -0
  190. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/components/permission_prompt.py +0 -0
  191. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/components/user_message.py +0 -0
  192. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/run_status.py +0 -0
  193. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/interactive/tool_renderers.py +0 -0
  194. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/modes/print_mode.py +0 -0
  195. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/py.typed +0 -0
  196. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/utils/__init__.py +0 -0
  197. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/utils/frontmatter.py +0 -0
  198. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/utils/git.py +0 -0
  199. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/utils/mime.py +0 -0
  200. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/utils/shell.py +0 -0
  201. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/src/xdog/coding/utils/sleep.py +0 -0
  202. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/acp_owner_agent.py +0 -0
  203. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/batch_helpers.py +0 -0
  204. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/conftest.py +0 -0
  205. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/fixtures/benchmark_tui.py +0 -0
  206. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/fixtures/terminal_client.py +0 -0
  207. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/fixtures/terminal_review.py +0 -0
  208. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/session_owner_process.py +0 -0
  209. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_acp_backend.py +0 -0
  210. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_acp_batch_intake.py +0 -0
  211. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_acp_bridge.py +0 -0
  212. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_acp_cli.py +0 -0
  213. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_acp_enqueue_cli.py +0 -0
  214. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_acp_ingress.py +0 -0
  215. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_acp_ingress_lifecycle.py +0 -0
  216. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_acp_optional_imports.py +0 -0
  217. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_active_tool_retirement.py +0 -0
  218. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_after_run_compaction.py +0 -0
  219. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_after_run_name.py +0 -0
  220. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_agent_session.py +0 -0
  221. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_batch_config.py +0 -0
  222. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_batch_display.py +0 -0
  223. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_batch_turns.py +0 -0
  224. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_cli_args.py +0 -0
  225. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_cli_config_selector.py +0 -0
  226. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_cli_file_processor.py +0 -0
  227. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_coding_config.py +0 -0
  228. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_command_artifact_export_ui.py +0 -0
  229. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_compact_layout.py +0 -0
  230. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_compaction_controls_ui.py +0 -0
  231. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_context_message_compaction.py +0 -0
  232. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_event_bus.py +0 -0
  233. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_extension_command_results_ui.py +0 -0
  234. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_extension_editor_ui.py +0 -0
  235. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_extension_input_draft_isolation.py +0 -0
  236. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_extension_input_ui.py +0 -0
  237. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_extension_navigation_ui.py +0 -0
  238. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_extension_provider_startup.py +0 -0
  239. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_extension_readonly_ui.py +0 -0
  240. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_extension_session_context_ui.py +0 -0
  241. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_footer_context.py +0 -0
  242. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_image_composer.py +0 -0
  243. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_inbox_activation_navigation.py +0 -0
  244. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_inbox_commands.py +0 -0
  245. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_inbox_crash.py +0 -0
  246. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_inbox_display.py +0 -0
  247. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_inbox_v2.py +0 -0
  248. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_interactive_keymap.py +0 -0
  249. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_mcp_auth_projection.py +0 -0
  250. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_mcp_browser.py +0 -0
  251. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_mcp_catalog_watch_ui.py +0 -0
  252. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_mcp_combined_watch_ui.py +0 -0
  253. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_mcp_manual_picker_ui.py +0 -0
  254. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_mcp_modern_browser_cancel.py +0 -0
  255. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_mcp_retired_gateway.py +0 -0
  256. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_mcp_roots_review_ui.py +0 -0
  257. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_mcp_sampling_ui.py +0 -0
  258. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_mcp_task_terminal.py +0 -0
  259. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_messages.py +0 -0
  260. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_no_legacy_event_host.py +0 -0
  261. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_oauth_ui.py +0 -0
  262. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_permissions.py +0 -0
  263. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_prompt_templates.py +0 -0
  264. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_provider_oauth_ui.py +0 -0
  265. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_queue_controls.py +0 -0
  266. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_removed_child_return_ui.py +0 -0
  267. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_renderer_contracts_ui.py +0 -0
  268. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_repository_review.py +0 -0
  269. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_retained_history.py +0 -0
  270. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_run_status.py +0 -0
  271. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_saved_source_ui.py +0 -0
  272. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_sdk_compaction_compat.py +0 -0
  273. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_sdk_session_state.py +0 -0
  274. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_batches.py +0 -0
  275. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_control_fences.py +0 -0
  276. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_controller.py +0 -0
  277. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_history_display.py +0 -0
  278. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_input_store.py +0 -0
  279. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_manager.py +0 -0
  280. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_navigation.py +0 -0
  281. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_picker.py +0 -0
  282. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_router.py +0 -0
  283. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_session_turns.py +0 -0
  284. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_settings_manager.py +0 -0
  285. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_skill_controls_ui.py +0 -0
  286. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_system_prompt.py +0 -0
  287. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_timings.py +0 -0
  288. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_transcript_interaction.py +0 -0
  289. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_transcript_output.py +0 -0
  290. {xdog_coding-2.4.3 → xdog_coding-2.4.5}/tests/test_unified_inbox_review_fixes.py +0 -0
@@ -57,3 +57,6 @@ plan.txt
57
57
  /cli_agent_workflow.json
58
58
  /cli_agent_workflow.py
59
59
  /essay_writer.py
60
+
61
+ # Goal workspaces contain local plans, task evidence and routing; never publish.
62
+ .xdog/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: xdog-coding
3
- Version: 2.4.3
3
+ Version: 2.4.5
4
4
  Summary: Interactive coding agent CLI
5
5
  Project-URL: Homepage, https://xdog.942295.xyz
6
6
  Project-URL: Repository, https://github.com/litterzhang/xdog
@@ -23,11 +23,12 @@ Requires-Dist: agent-client-protocol<0.13,>=0.12.1; python_version < '3.15'
23
23
  Requires-Dist: click>=8.1.0
24
24
  Requires-Dist: pydantic>=2.0
25
25
  Requires-Dist: pyyaml>=6.0
26
- Requires-Dist: xdog-agent>=2.4.3
27
- Requires-Dist: xdog-ai[openai]>=2.4.3
28
- Requires-Dist: xdog-tui>=2.4.3
26
+ Requires-Dist: xdog-agent>=2.4.5
27
+ Requires-Dist: xdog-ai[openai]>=2.4.5
28
+ Requires-Dist: xdog-skills>=2.4.5
29
+ Requires-Dist: xdog-tui>=2.4.5
29
30
  Provides-Extra: skills
30
- Requires-Dist: xdog-skills>=2.4.3; extra == 'skills'
31
+ Requires-Dist: xdog-skills>=2.4.5; extra == 'skills'
31
32
  Description-Content-Type: text/markdown
32
33
 
33
34
  # xdog-coding
@@ -59,6 +60,15 @@ saved model, messages and usage are preserved.
59
60
 
60
61
  ## Interactive terminal
61
62
 
63
+ Auxiliary browsers use the main UI's existing semantic colors: warm accent
64
+ headings and current selection, muted metadata/hints, and green/red status cues.
65
+ This covers session/history, transcript/tool inventory, details, child/draft,
66
+ MCP/OAuth, export review and attachment chrome, including existing nested/fullscreen
67
+ viewers. Coding's pre-start resume picker follows the same theme. Plain mode and
68
+ `NO_COLOR` keep these panels unstyled. Colors do not change row budgets,
69
+ keybindings, visible-confirmation requirements, original source or exported data.
70
+ See [panel theming](../../docs/panel-theming.md).
71
+
62
72
  The interface uses native scrollback, one status row, and a shared multiline
63
73
  editor. Enter submits or queues; Ctrl+Enter inserts a newline. Ctrl+O opens
64
74
  recent tool/reasoning details: Left/Right chooses an entry and Page Up/Page Down
@@ -145,6 +155,7 @@ the timer. Worker locks and cancellation signals remain separate from UI state.
145
155
 
146
156
  Potentially mutating tool calls are gated immediately before execution. By
147
157
  default, read-only filesystem operations and `current_time` run automatically;
158
+ the exact host-bound `ext_coding_session` inspection also needs no approval;
148
159
  `bash`, filesystem writes/edits/deletes, and unknown extension tools ask first.
149
160
 
150
161
  ```bash
@@ -464,6 +475,30 @@ fallback files persist until you delete them. Kernel-blocked filesystem operatio
464
475
  cannot be forcibly interrupted; helper success may transfer clipboard ownership
465
476
  to the platform's normal persistent clipboard process.
466
477
 
478
+ ### Read-only session inspection
479
+
480
+ `/session` and the built-in host extension tool `ext_coding_session` share the
481
+ same current-session query. The tool takes `{}` and returns structured JSON:
482
+ current session/branch/name/workspace, selected model and known capabilities,
483
+ thinking, effective permission/read-only state, and measured context usage.
484
+ Unknown capabilities/usage remain explicitly unavailable; selected provider/model
485
+ configuration is not proof of a server's underlying model identity. No credentials,
486
+ conversation bodies, file reads or settings dump are included.
487
+
488
+ The instruction prefix points to this query instead of embedding mutable model,
489
+ thinking, permission or session-ID values. Explicit tool selection still applies:
490
+ an empty/narrowed selection does not silently re-enable inspection, and prompts
491
+ state when the tool is unavailable. This is a Coding-owned tool, not a new Python
492
+ plugin worker or a generic slash-command execution bridge. Its actual bound tool
493
+ may read without frontend approval even in ask-all/deny/read-only mode; arbitrary
494
+ extension tools and same-name replacements gain no exemption. Existing extension
495
+ validation/vetoes remain active. Navigation/close retire old handles, and children
496
+ do not inherit their parent's inspection callback. Neither ACP nor a TUI is needed.
497
+
498
+ Session navigation normalizes title/summary/detail/error whitespace for display
499
+ only, so embedded newlines/tabs cannot desynchronize terminal row tracking. The
500
+ stored original text is not modified.
501
+
467
502
  ### MCP stdio tools (first transport slice)
468
503
 
469
504
  Global `settings.json` and project `.coding/settings.json` accept `mcp_servers`;
@@ -580,12 +615,12 @@ continuation silently reconnects, replays POSTs or expands configured disclosure
580
615
 
581
616
  ### Task planning and host read-only scope
582
617
 
583
- The builtin **`xdog-planning`** skill, supplied by `xdog-skills` (install the
618
+ The builtin **`plan`** skill, supplied by `xdog-skills` (install the
584
619
  `skills` extra), uses ordinary conversation or task documents
585
620
  for objectives, dependencies, acceptance criteria and evidence-backed progress.
586
621
  It does not create a separate plan database, inspector, execution mode or model
587
622
  loop. The former `/plan`, `PlanPanel` and `update_plan` UI/tool APIs are removed.
588
- List it with `/skills` and activate it with `/xdog-planning [request]`.
623
+ List it with `/skills` and activate it with `/plan [request]`.
589
624
 
590
625
  Use the native host control separately:
591
626
 
@@ -595,10 +630,11 @@ Use the native host control separately:
595
630
  /readonly off
596
631
  ```
597
632
 
598
- With host read-only scope on, only local `filesystem` read/ls/grep/find and
599
- `current_time` tool calls are eligible; shell, workspace writes, MCP/extension
600
- tools and child-control tools are blocked. Normal permission policy still applies
601
- to eligible calls. Cached approvals, `allow-all`, skill text, model arguments and
633
+ With host read-only scope on, only local `filesystem` read/ls/grep/find,
634
+ `current_time` calls and the host-bound `ext_coding_session` query are eligible.
635
+ Shell, workspace writes, arbitrary MCP/extension tools and child-control tools
636
+ are blocked. Ordinary eligible calls retain their normal permission policy;
637
+ the exact bound session query needs no approval. Cached approvals, `allow-all`, skill text, model arguments and
602
638
  delayed approvals cannot release or bypass this restriction. Keep planning notes
603
639
  in the conversation while read-only; writing a task document still needs the
604
640
  normal write permission outside that scope.
@@ -782,7 +818,7 @@ none of these interfaces grants tool permission or full Pi API compatibility.
782
818
  TASK` inherits the current host policy; it does not copy approval grants or bypass
783
819
  read-only. Inspect with `/agents list` or `/agents inspect ID`; use `steer ID TEXT`,
784
820
  `follow-up ID TEXT`, `cancel ID`, `wait ID` and `close ID` under `/agents`.
785
- Parents also receive reserved `agent_spawn`/`agent_control` tools; children cannot
821
+ Parents also receive the reserved unified `agent` tool; children cannot
786
822
  recursively delegate through their parent's supervision tools.
787
823
 
788
824
  Children share the workspace, so coordinate conflicting writes. Context is copied
@@ -2080,7 +2116,7 @@ count and `initial-task`/`crash-snapshot`/`durable-return` uncertainty are visib
2080
2116
  This native view has no editor, reorder/remove/return control, recovery-copy button
2081
2117
  or permission-confirmation action. Paste cannot submit or adopt a draft.
2082
2118
 
2083
- The ordinary main-Agent `agent_control` tool retains `action="queue"` with a typed
2119
+ The ordinary main-Agent `agent` tool retains `action="queue"` with a typed
2084
2120
  JSON `text` request. SDK `ChildSupervisor.control("queue", ...)` also remains.
2085
2121
  Their edit/remove/move/text-return and explicit stopped recovery operations use the
2086
2122
  real owner loop and existing identity, revision, selected-input, image-byte and
@@ -2198,7 +2234,7 @@ existing limitations.
2198
2234
  `recover_images` remains an explicit SDK/main-Agent queue operation with exact
2199
2235
  input `id` and queue `revision`. `ChildSupervisor.control` returns the verified
2200
2236
  non-destructive `image_recovery` payload and `queue.image_receipt`; the ordinary
2201
- `agent_control` wrapper returns typed images plus receipt/count metadata. The
2237
+ `agent` wrapper returns typed images plus receipt/count metadata. The
2202
2238
  text-only `recover` action refuses image-bearing inputs rather than dropping bytes.
2203
2239
  Running children use the separate owned live-return protocol, not stopped recovery.
2204
2240
 
@@ -2272,7 +2308,7 @@ SDK journaling and same-session transient editor recovery are not removed.
2272
2308
  The native user interface offers neither manual live queue edit/reorder/remove/
2273
2309
  return nor stopped task/input copy controls. Those queue operations remain in the
2274
2310
  permissioned main-Agent/SDK backend; native queue inspection is read-only.
2275
- The main Agent can use its ordinary permissioned `agent_control` tool with
2311
+ The main Agent can use its ordinary permissioned `agent` tool with
2276
2312
  `action="queue"` and a JSON `text` request containing `return_prepare`,
2277
2313
  `return_commit` or `return_cancel` plus the required input/revision/receipt fields.
2278
2314
  Preparation returns typed image content and bounded token/receipt metadata; it
@@ -2655,3 +2691,91 @@ and widget layouts are removed. Native approval and recovery reviews remain host
2655
2691
  owned; they expose no plugin layout or editor/session-mutation authority. Core TUI
2656
2692
  overlays, transcript fullscreen, Unicode, clipping, cursor and tool-approval behavior
2657
2693
  remain.
2694
+
2695
+ ## Session ownership and reliable shutdown
2696
+
2697
+ Coding's TUI, print, SDK and ACP ingress share one session controller and Agent.
2698
+ Persistent writer locks live under `<sessions>/.owners`; they do not depend on
2699
+ `TMPDIR`. Short private Linux Unix socket/discovery files are separate, under
2700
+ `/tmp/xdog-coding-<uid>/<store-hash>`. Stop older Coding processes before upgrading:
2701
+ old binaries do not participate in this store-anchored writer-lock protocol. Do
2702
+ not run mixed old/new writers against the same session store.
2703
+
2704
+ SDK applications should `await session.aclose()` in `finally`. Closure is
2705
+ idempotent, waits for actual child/Goal/extension/MCP cleanup, and reports cleanup
2706
+ errors only after attempting the other resources. Cancellation of a waiter does
2707
+ not abandon the underlying close. `session.dispose()` requests the same close
2708
+ and returns a concurrent Future; synchronous applications can wait on `.result()`.
2709
+ Do not block an asynchronous caller loop with `.result()`; await `aclose()` instead.
2710
+ Synchronous construction and controls can be called with `asyncio.to_thread` when
2711
+ used from an async application. A receiver accepting a queued message does not
2712
+ require message approval; existing approval applies to tool execution only.
2713
+
2714
+ Automatic project instructions come **only** from the working directory's
2715
+ `AGENTS.md`, `.coding/INSTRUCTIONS.md` and `.coding/instructions.md`. There is no
2716
+ parent walk. Other harness configuration files are not automatic instruction
2717
+ sources; they remain ordinary files that users can explicitly read or attach under
2718
+ normal file-access and permission rules. There is no filename denylist.
2719
+ Each automatic source must be a regular UTF-8 file of at most 64 KiB; symlinks,
2720
+ special files and unreadable/oversized sources cause an explicit preparation error. Missing files are optional. These
2721
+ instructions are refreshed in owned off-loop preparation before a turn, reach the
2722
+ actual model prompt, and never grant tool permissions. The Agent alone renders
2723
+ skill indexes and session/turn-scoped bodies; loading a skill starts no observer,
2724
+ model, receiver or daemon.
2725
+
2726
+ `CreateSessionOptions.thinking_level` is honored, including explicit `"off"`.
2727
+ Initial `allowed_tools` configuration is a **tool selection**, not authorization:
2728
+ absent/null falls through to a lower layer, `[]` selects no tools, and a nonempty
2729
+ list selects those configured names. Caller options/overrides take precedence
2730
+ over saved explicit choices, then project and global configuration. Choices are
2731
+ not unioned. Unavailable saved names do not create tools or gain authority later;
2732
+ normal permission checks still apply to the selected tools.
2733
+
2734
+ The separate input history ledger has a common **64 MiB** read/write bound.
2735
+ Admission reserves final-state, batch-ID and bounded diagnostic space for every
2736
+ unfinished input; if it cannot fit, it is refused before acknowledgement. Errors
2737
+ retain up to 4096 characters with an explicit truncation marker; batch IDs are
2738
+ limited to 256 UTF-8 bytes. Accepted execution facts are never silently deleted.
2739
+ At capacity, explicitly start another session rather than automatically archiving
2740
+ or replaying requests. Recovery marks unfinished execution interrupted and never
2741
+ replays potentially executed tool effects automatically.
2742
+
2743
+ Ordinary turn history uses one immutable, original-owner disk commit, off the
2744
+ model loop, before publishing saved state and completing producer receipts.
2745
+ File replacement synchronizes the file and parent directory. A failed or
2746
+ uncertain history commit retains the live executed tail and fences further turns;
2747
+ close and explicitly reload/inspect the saved state before continuing. Concurrent
2748
+ metadata revision conflicts fail closed instead of overwriting newer facts.
2749
+ These are local filesystem/process guarantees, not hardware power-loss
2750
+ exactly-once execution or an OS security sandbox. No existing user data is migrated
2751
+ or discarded automatically.
2752
+
2753
+ Enabled extensions may declare a public slash name. The packaged `goal_ui`
2754
+ display exposes `/goals [GOAL_ID | page OFFSET]`; default native `/goal` manages the current Goal.
2755
+ This is generic extension routing, not a Coding-specific Goal command. Public
2756
+ names appear in help/completion and cannot shadow builtins or other owners; native installed capabilities
2757
+ may explicitly overlap only their own skill command entry, without preventing skill loading;
2758
+ model tool names and permissions do not change. See
2759
+ `docs/extension-public-commands.md` for the shared Coding/Claw contract.
2760
+
2761
+
2762
+ ### Installed capability code boundaries
2763
+
2764
+ Trusted installed native capabilities use generic owner, lifecycle event, ACP
2765
+ routing and receipt ports. Coding/Claw default dependencies include xdog-skills:
2766
+ `/goal` commands and the model tool are available without a display-worker setting
2767
+ or Goal enable flag. The packaged skill remains discoverable/loadable. No Goal is
2768
+ created merely by installation or ordinary chat.
2769
+
2770
+ Goal owns one current binding/history, task files and ACP reminders. The current
2771
+ main Agent plans, executes itself or uses existing child tools, updates tasks and
2772
+ judges completion according to the skill. No Goal-owned worker/reviewer scheduler
2773
+ or independent acceptance protocol remains. Tasks/*.json are authoritative, not
2774
+ projections of duplicate database task state. Pauses and user/host waits cannot be
2775
+ released by an automatic message. Existing readonly/permissions/approval checks
2776
+ remain in force. Eyes watches only the generated task directory configuration;
2777
+ stopping Goal automation does not cancel unrelated observers or accepted work.
2778
+
2779
+ See `docs/goal-simple-design.md` and its requirement/verification record. Earlier
2780
+ capability-boundary and Goal reviewer lifecycle evidence describes its old frozen
2781
+ implementation, not the current Goal contract.
@@ -27,6 +27,15 @@ saved model, messages and usage are preserved.
27
27
 
28
28
  ## Interactive terminal
29
29
 
30
+ Auxiliary browsers use the main UI's existing semantic colors: warm accent
31
+ headings and current selection, muted metadata/hints, and green/red status cues.
32
+ This covers session/history, transcript/tool inventory, details, child/draft,
33
+ MCP/OAuth, export review and attachment chrome, including existing nested/fullscreen
34
+ viewers. Coding's pre-start resume picker follows the same theme. Plain mode and
35
+ `NO_COLOR` keep these panels unstyled. Colors do not change row budgets,
36
+ keybindings, visible-confirmation requirements, original source or exported data.
37
+ See [panel theming](../../docs/panel-theming.md).
38
+
30
39
  The interface uses native scrollback, one status row, and a shared multiline
31
40
  editor. Enter submits or queues; Ctrl+Enter inserts a newline. Ctrl+O opens
32
41
  recent tool/reasoning details: Left/Right chooses an entry and Page Up/Page Down
@@ -113,6 +122,7 @@ the timer. Worker locks and cancellation signals remain separate from UI state.
113
122
 
114
123
  Potentially mutating tool calls are gated immediately before execution. By
115
124
  default, read-only filesystem operations and `current_time` run automatically;
125
+ the exact host-bound `ext_coding_session` inspection also needs no approval;
116
126
  `bash`, filesystem writes/edits/deletes, and unknown extension tools ask first.
117
127
 
118
128
  ```bash
@@ -432,6 +442,30 @@ fallback files persist until you delete them. Kernel-blocked filesystem operatio
432
442
  cannot be forcibly interrupted; helper success may transfer clipboard ownership
433
443
  to the platform's normal persistent clipboard process.
434
444
 
445
+ ### Read-only session inspection
446
+
447
+ `/session` and the built-in host extension tool `ext_coding_session` share the
448
+ same current-session query. The tool takes `{}` and returns structured JSON:
449
+ current session/branch/name/workspace, selected model and known capabilities,
450
+ thinking, effective permission/read-only state, and measured context usage.
451
+ Unknown capabilities/usage remain explicitly unavailable; selected provider/model
452
+ configuration is not proof of a server's underlying model identity. No credentials,
453
+ conversation bodies, file reads or settings dump are included.
454
+
455
+ The instruction prefix points to this query instead of embedding mutable model,
456
+ thinking, permission or session-ID values. Explicit tool selection still applies:
457
+ an empty/narrowed selection does not silently re-enable inspection, and prompts
458
+ state when the tool is unavailable. This is a Coding-owned tool, not a new Python
459
+ plugin worker or a generic slash-command execution bridge. Its actual bound tool
460
+ may read without frontend approval even in ask-all/deny/read-only mode; arbitrary
461
+ extension tools and same-name replacements gain no exemption. Existing extension
462
+ validation/vetoes remain active. Navigation/close retire old handles, and children
463
+ do not inherit their parent's inspection callback. Neither ACP nor a TUI is needed.
464
+
465
+ Session navigation normalizes title/summary/detail/error whitespace for display
466
+ only, so embedded newlines/tabs cannot desynchronize terminal row tracking. The
467
+ stored original text is not modified.
468
+
435
469
  ### MCP stdio tools (first transport slice)
436
470
 
437
471
  Global `settings.json` and project `.coding/settings.json` accept `mcp_servers`;
@@ -548,12 +582,12 @@ continuation silently reconnects, replays POSTs or expands configured disclosure
548
582
 
549
583
  ### Task planning and host read-only scope
550
584
 
551
- The builtin **`xdog-planning`** skill, supplied by `xdog-skills` (install the
585
+ The builtin **`plan`** skill, supplied by `xdog-skills` (install the
552
586
  `skills` extra), uses ordinary conversation or task documents
553
587
  for objectives, dependencies, acceptance criteria and evidence-backed progress.
554
588
  It does not create a separate plan database, inspector, execution mode or model
555
589
  loop. The former `/plan`, `PlanPanel` and `update_plan` UI/tool APIs are removed.
556
- List it with `/skills` and activate it with `/xdog-planning [request]`.
590
+ List it with `/skills` and activate it with `/plan [request]`.
557
591
 
558
592
  Use the native host control separately:
559
593
 
@@ -563,10 +597,11 @@ Use the native host control separately:
563
597
  /readonly off
564
598
  ```
565
599
 
566
- With host read-only scope on, only local `filesystem` read/ls/grep/find and
567
- `current_time` tool calls are eligible; shell, workspace writes, MCP/extension
568
- tools and child-control tools are blocked. Normal permission policy still applies
569
- to eligible calls. Cached approvals, `allow-all`, skill text, model arguments and
600
+ With host read-only scope on, only local `filesystem` read/ls/grep/find,
601
+ `current_time` calls and the host-bound `ext_coding_session` query are eligible.
602
+ Shell, workspace writes, arbitrary MCP/extension tools and child-control tools
603
+ are blocked. Ordinary eligible calls retain their normal permission policy;
604
+ the exact bound session query needs no approval. Cached approvals, `allow-all`, skill text, model arguments and
570
605
  delayed approvals cannot release or bypass this restriction. Keep planning notes
571
606
  in the conversation while read-only; writing a task document still needs the
572
607
  normal write permission outside that scope.
@@ -750,7 +785,7 @@ none of these interfaces grants tool permission or full Pi API compatibility.
750
785
  TASK` inherits the current host policy; it does not copy approval grants or bypass
751
786
  read-only. Inspect with `/agents list` or `/agents inspect ID`; use `steer ID TEXT`,
752
787
  `follow-up ID TEXT`, `cancel ID`, `wait ID` and `close ID` under `/agents`.
753
- Parents also receive reserved `agent_spawn`/`agent_control` tools; children cannot
788
+ Parents also receive the reserved unified `agent` tool; children cannot
754
789
  recursively delegate through their parent's supervision tools.
755
790
 
756
791
  Children share the workspace, so coordinate conflicting writes. Context is copied
@@ -2048,7 +2083,7 @@ count and `initial-task`/`crash-snapshot`/`durable-return` uncertainty are visib
2048
2083
  This native view has no editor, reorder/remove/return control, recovery-copy button
2049
2084
  or permission-confirmation action. Paste cannot submit or adopt a draft.
2050
2085
 
2051
- The ordinary main-Agent `agent_control` tool retains `action="queue"` with a typed
2086
+ The ordinary main-Agent `agent` tool retains `action="queue"` with a typed
2052
2087
  JSON `text` request. SDK `ChildSupervisor.control("queue", ...)` also remains.
2053
2088
  Their edit/remove/move/text-return and explicit stopped recovery operations use the
2054
2089
  real owner loop and existing identity, revision, selected-input, image-byte and
@@ -2166,7 +2201,7 @@ existing limitations.
2166
2201
  `recover_images` remains an explicit SDK/main-Agent queue operation with exact
2167
2202
  input `id` and queue `revision`. `ChildSupervisor.control` returns the verified
2168
2203
  non-destructive `image_recovery` payload and `queue.image_receipt`; the ordinary
2169
- `agent_control` wrapper returns typed images plus receipt/count metadata. The
2204
+ `agent` wrapper returns typed images plus receipt/count metadata. The
2170
2205
  text-only `recover` action refuses image-bearing inputs rather than dropping bytes.
2171
2206
  Running children use the separate owned live-return protocol, not stopped recovery.
2172
2207
 
@@ -2240,7 +2275,7 @@ SDK journaling and same-session transient editor recovery are not removed.
2240
2275
  The native user interface offers neither manual live queue edit/reorder/remove/
2241
2276
  return nor stopped task/input copy controls. Those queue operations remain in the
2242
2277
  permissioned main-Agent/SDK backend; native queue inspection is read-only.
2243
- The main Agent can use its ordinary permissioned `agent_control` tool with
2278
+ The main Agent can use its ordinary permissioned `agent` tool with
2244
2279
  `action="queue"` and a JSON `text` request containing `return_prepare`,
2245
2280
  `return_commit` or `return_cancel` plus the required input/revision/receipt fields.
2246
2281
  Preparation returns typed image content and bounded token/receipt metadata; it
@@ -2623,3 +2658,91 @@ and widget layouts are removed. Native approval and recovery reviews remain host
2623
2658
  owned; they expose no plugin layout or editor/session-mutation authority. Core TUI
2624
2659
  overlays, transcript fullscreen, Unicode, clipping, cursor and tool-approval behavior
2625
2660
  remain.
2661
+
2662
+ ## Session ownership and reliable shutdown
2663
+
2664
+ Coding's TUI, print, SDK and ACP ingress share one session controller and Agent.
2665
+ Persistent writer locks live under `<sessions>/.owners`; they do not depend on
2666
+ `TMPDIR`. Short private Linux Unix socket/discovery files are separate, under
2667
+ `/tmp/xdog-coding-<uid>/<store-hash>`. Stop older Coding processes before upgrading:
2668
+ old binaries do not participate in this store-anchored writer-lock protocol. Do
2669
+ not run mixed old/new writers against the same session store.
2670
+
2671
+ SDK applications should `await session.aclose()` in `finally`. Closure is
2672
+ idempotent, waits for actual child/Goal/extension/MCP cleanup, and reports cleanup
2673
+ errors only after attempting the other resources. Cancellation of a waiter does
2674
+ not abandon the underlying close. `session.dispose()` requests the same close
2675
+ and returns a concurrent Future; synchronous applications can wait on `.result()`.
2676
+ Do not block an asynchronous caller loop with `.result()`; await `aclose()` instead.
2677
+ Synchronous construction and controls can be called with `asyncio.to_thread` when
2678
+ used from an async application. A receiver accepting a queued message does not
2679
+ require message approval; existing approval applies to tool execution only.
2680
+
2681
+ Automatic project instructions come **only** from the working directory's
2682
+ `AGENTS.md`, `.coding/INSTRUCTIONS.md` and `.coding/instructions.md`. There is no
2683
+ parent walk. Other harness configuration files are not automatic instruction
2684
+ sources; they remain ordinary files that users can explicitly read or attach under
2685
+ normal file-access and permission rules. There is no filename denylist.
2686
+ Each automatic source must be a regular UTF-8 file of at most 64 KiB; symlinks,
2687
+ special files and unreadable/oversized sources cause an explicit preparation error. Missing files are optional. These
2688
+ instructions are refreshed in owned off-loop preparation before a turn, reach the
2689
+ actual model prompt, and never grant tool permissions. The Agent alone renders
2690
+ skill indexes and session/turn-scoped bodies; loading a skill starts no observer,
2691
+ model, receiver or daemon.
2692
+
2693
+ `CreateSessionOptions.thinking_level` is honored, including explicit `"off"`.
2694
+ Initial `allowed_tools` configuration is a **tool selection**, not authorization:
2695
+ absent/null falls through to a lower layer, `[]` selects no tools, and a nonempty
2696
+ list selects those configured names. Caller options/overrides take precedence
2697
+ over saved explicit choices, then project and global configuration. Choices are
2698
+ not unioned. Unavailable saved names do not create tools or gain authority later;
2699
+ normal permission checks still apply to the selected tools.
2700
+
2701
+ The separate input history ledger has a common **64 MiB** read/write bound.
2702
+ Admission reserves final-state, batch-ID and bounded diagnostic space for every
2703
+ unfinished input; if it cannot fit, it is refused before acknowledgement. Errors
2704
+ retain up to 4096 characters with an explicit truncation marker; batch IDs are
2705
+ limited to 256 UTF-8 bytes. Accepted execution facts are never silently deleted.
2706
+ At capacity, explicitly start another session rather than automatically archiving
2707
+ or replaying requests. Recovery marks unfinished execution interrupted and never
2708
+ replays potentially executed tool effects automatically.
2709
+
2710
+ Ordinary turn history uses one immutable, original-owner disk commit, off the
2711
+ model loop, before publishing saved state and completing producer receipts.
2712
+ File replacement synchronizes the file and parent directory. A failed or
2713
+ uncertain history commit retains the live executed tail and fences further turns;
2714
+ close and explicitly reload/inspect the saved state before continuing. Concurrent
2715
+ metadata revision conflicts fail closed instead of overwriting newer facts.
2716
+ These are local filesystem/process guarantees, not hardware power-loss
2717
+ exactly-once execution or an OS security sandbox. No existing user data is migrated
2718
+ or discarded automatically.
2719
+
2720
+ Enabled extensions may declare a public slash name. The packaged `goal_ui`
2721
+ display exposes `/goals [GOAL_ID | page OFFSET]`; default native `/goal` manages the current Goal.
2722
+ This is generic extension routing, not a Coding-specific Goal command. Public
2723
+ names appear in help/completion and cannot shadow builtins or other owners; native installed capabilities
2724
+ may explicitly overlap only their own skill command entry, without preventing skill loading;
2725
+ model tool names and permissions do not change. See
2726
+ `docs/extension-public-commands.md` for the shared Coding/Claw contract.
2727
+
2728
+
2729
+ ### Installed capability code boundaries
2730
+
2731
+ Trusted installed native capabilities use generic owner, lifecycle event, ACP
2732
+ routing and receipt ports. Coding/Claw default dependencies include xdog-skills:
2733
+ `/goal` commands and the model tool are available without a display-worker setting
2734
+ or Goal enable flag. The packaged skill remains discoverable/loadable. No Goal is
2735
+ created merely by installation or ordinary chat.
2736
+
2737
+ Goal owns one current binding/history, task files and ACP reminders. The current
2738
+ main Agent plans, executes itself or uses existing child tools, updates tasks and
2739
+ judges completion according to the skill. No Goal-owned worker/reviewer scheduler
2740
+ or independent acceptance protocol remains. Tasks/*.json are authoritative, not
2741
+ projections of duplicate database task state. Pauses and user/host waits cannot be
2742
+ released by an automatic message. Existing readonly/permissions/approval checks
2743
+ remain in force. Eyes watches only the generated task directory configuration;
2744
+ stopping Goal automation does not cancel unrelated observers or accepted work.
2745
+
2746
+ See `docs/goal-simple-design.md` and its requirement/verification record. Earlier
2747
+ capability-boundary and Goal reviewer lifecycle evidence describes its old frozen
2748
+ implementation, not the current Goal contract.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "xdog-coding"
7
- version = "2.4.3"
7
+ version = "2.4.5"
8
8
  description = "Interactive coding agent CLI"
9
9
  requires-python = ">=3.12"
10
10
  classifiers = [
@@ -22,17 +22,18 @@ readme = "README.md"
22
22
  license = "AGPL-3.0-or-later"
23
23
  license-files = ["LICENSE", "LICENSE-EXCEPTION.md"]
24
24
  dependencies = [
25
- "xdog-ai[openai]>=2.4.3",
26
- "xdog-agent>=2.4.3",
25
+ "xdog-ai[openai]>=2.4.5",
26
+ "xdog-agent>=2.4.5",
27
+ "xdog-skills>=2.4.5",
27
28
  "agent-client-protocol>=0.12.1,<0.13; python_version < '3.15'",
28
- "xdog-tui>=2.4.3",
29
+ "xdog-tui>=2.4.5",
29
30
  "pyyaml>=6.0",
30
31
  "click>=8.1.0",
31
32
  "pydantic>=2.0",
32
33
  ]
33
34
 
34
35
  [project.optional-dependencies]
35
- skills = ["xdog-skills>=2.4.3"]
36
+ skills = ["xdog-skills>=2.4.5"]
36
37
 
37
38
  [project.urls]
38
39
  Homepage = "https://xdog.942295.xyz"
@@ -1,3 +1,3 @@
1
1
  """coding - Interactive coding agent CLI."""
2
2
 
3
- __version__ = "2.4.3"
3
+ __version__ = "2.4.5"
@@ -89,17 +89,19 @@ class CodingBackend:
89
89
  try:
90
90
  session = await asyncio.shield(task)
91
91
  except asyncio.CancelledError:
92
- session = await task
93
- session.dispose()
92
+ from xdog.agent.async_work import wait_owned
93
+ async def settle_construction() -> None:
94
+ late_session = await task
95
+ await late_session.aclose()
96
+ await wait_owned(asyncio.create_task(settle_construction(), name='coding-acp-canceled-construction'))
94
97
  raise
95
- runtime = SessionRuntime(session, bound=False, router=self.router)
96
- runtime.start()
97
98
  try:
99
+ runtime = SessionRuntime(session, bound=False, router=self.router)
100
+ runtime.start()
98
101
  from xdog.coding.acp.server import serve_local
99
-
100
102
  server = await serve_local(runtime)
101
103
  except BaseException:
102
- await asyncio.wrap_future(runtime.close())
104
+ await session.aclose()
103
105
  raise
104
106
  self._owned[session.session_id] = peer.id, runtime, server
105
107
  ref = SessionRef(session.session_id, session.working_dir, runtime.controller.generation)
@@ -300,31 +302,51 @@ class CodingBackend:
300
302
  await asyncio.wrap_future(running.controller.cancel(running.ticket.id, peer_id=peer.id))
301
303
 
302
304
  async def disconnect(self, peer: Peer) -> None:
303
- await self._inbox.disconnect(peer)
305
+ from functools import partial
306
+
307
+ from xdog.agent.async_work import settle_cleanup
304
308
  pending = tuple(row for key, row in self._running.items() if key[0] == peer.id)
305
- for row in pending:
306
- if row.ticket is None and not row.task.cancelling():
307
- row.task.cancel()
308
- for controller in {row.controller for row in pending}:
309
- await asyncio.wrap_future(controller.disconnect(peer.id))
310
- tasks = [row.task for row in pending if row.task is not asyncio.current_task()]
311
- if tasks:
312
- for task in tasks:
313
- if not task.done() and not task.cancelling():
314
- task.cancel()
315
- await asyncio.gather(*tasks, return_exceptions=True)
316
- for key, remote in tuple(self._remote.items()):
317
- if key[0] == peer.id:
318
- await remote.close()
319
- del self._remote[key]
320
- for identifier, (owner, runtime, server) in tuple(self._owned.items()):
321
- if owner == peer.id:
322
- await server.close()
323
- await asyncio.wrap_future(runtime.close())
324
- del self._owned[identifier]
325
- for key in tuple(self._refs):
326
- if key[0] == peer.id:
327
- del self._refs[key]
309
+ async def ingress() -> None:
310
+ await self._inbox.disconnect(peer)
311
+ async def requests() -> None:
312
+ for row in pending:
313
+ if row.ticket is None and not row.task.cancelling():
314
+ row.task.cancel()
315
+ async def disconnect(controller: SessionController) -> None:
316
+ await asyncio.wrap_future(controller.disconnect(peer.id))
317
+ async def join() -> None:
318
+ tasks = [row.task for row in pending if row.task is not asyncio.current_task()]
319
+ for task in tasks:
320
+ if not task.done() and not task.cancelling():
321
+ task.cancel()
322
+ if tasks:
323
+ await asyncio.gather(*tasks, return_exceptions=True)
324
+ controllers = {row.controller for row in pending}
325
+ await settle_cleanup(*(partial(disconnect, controller) for controller in controllers),
326
+ join, message='ACP request retirement failed')
327
+ async def remote(key: tuple[str, str], attachment: AcpAttachment) -> None:
328
+ try:
329
+ await attachment.close()
330
+ finally:
331
+ self._remote.pop(key, None)
332
+ async def owned(identifier: str, runtime: SessionRuntime) -> None:
333
+ try:
334
+ # The session owns its CURRENT endpoint too. Closing the saved
335
+ # old endpoint first would bypass all remaining resource cleanup.
336
+ await runtime.session.aclose()
337
+ finally:
338
+ if runtime.session._lease is None:
339
+ self._owned.pop(identifier, None)
340
+ async def references() -> None:
341
+ for key in tuple(self._refs):
342
+ if key[0] == peer.id:
343
+ self._refs.pop(key, None)
344
+ owned_sessions = tuple(self._owned.items())
345
+ await settle_cleanup(ingress, requests,
346
+ *(partial(remote, key, attachment) for key, attachment in tuple(self._remote.items()) if key[0] == peer.id),
347
+ *(partial(owned, identifier, runtime) for identifier, (owner, runtime, _server) in owned_sessions
348
+ if owner == peer.id), references, message='ACP peer cleanup failed')
349
+
328
350
  async def extension(self, peer: Peer, method: str, params: dict[str, Any]) -> dict[str, Any]:
329
351
  if method in {'xdog/enqueue', 'xdog/inbox_status'}:
330
352
  target = params.get('session_id')