xdog-coding 2.4.2__tar.gz → 2.4.3__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 (239) hide show
  1. xdog_coding-2.4.2/README.md → xdog_coding-2.4.3/PKG-INFO +80 -17
  2. xdog_coding-2.4.2/PKG-INFO → xdog_coding-2.4.3/README.md +48 -47
  3. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/pyproject.toml +7 -4
  4. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/__init__.py +1 -1
  5. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/config.py +1 -1
  6. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/agent_session.py +86 -9
  7. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/child_agents.py +35 -9
  8. xdog_coding-2.4.3/src/xdog/coding/core/goal_adapter.py +366 -0
  9. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/controller.py +32 -8
  10. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/inbox_models.py +1 -1
  11. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/inbox_runtime.py +56 -14
  12. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/inbox_store.py +37 -4
  13. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/runtime.py +1 -0
  14. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/slash_commands.py +11 -2
  15. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/interactive_mode.py +1 -3
  16. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/session_events.py +3 -6
  17. xdog_coding-2.4.3/tests/goal_installed_consumer.py +233 -0
  18. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_access_scope.py +6 -5
  19. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_acp_artifact_contract.py +5 -1
  20. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_acp_review_regressions.py +44 -13
  21. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_active_tool_retirement.py +13 -8
  22. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_child_agents.py +50 -9
  23. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_compaction_controls_ui.py +3 -2
  24. xdog_coding-2.4.3/tests/test_goal_adapter.py +302 -0
  25. xdog_coding-2.4.3/tests/test_goal_extension_views.py +212 -0
  26. xdog_coding-2.4.3/tests/test_goal_lifecycle.py +268 -0
  27. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_inbox_auto_consume.py +5 -2
  28. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_runtime_prompt.py +3 -2
  29. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_mode_routing.py +2 -0
  30. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_slash_skills.py +2 -0
  31. xdog_coding-2.4.3/tests/test_unified_inbox_review_fixes.py +397 -0
  32. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/.gitignore +0 -0
  33. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/LICENSE +0 -0
  34. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/LICENSE-EXCEPTION.md +0 -0
  35. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/acp/__init__.py +0 -0
  36. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/acp/backend.py +0 -0
  37. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/acp/bridge.py +0 -0
  38. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/acp/cli.py +0 -0
  39. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/acp/client.py +0 -0
  40. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/acp/extensions.py +0 -0
  41. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/acp/ingress.py +0 -0
  42. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/acp/ingress_backend.py +0 -0
  43. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/acp/ingress_main.py +0 -0
  44. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/acp/server.py +0 -0
  45. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/cli/__init__.py +0 -0
  46. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/cli/args.py +0 -0
  47. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/cli/config_selector.py +0 -0
  48. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/cli/enqueue.py +0 -0
  49. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/cli/file_processor.py +0 -0
  50. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/cli/initial_message.py +0 -0
  51. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/cli/list_models.py +0 -0
  52. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/cli/session_picker.py +0 -0
  53. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/__init__.py +0 -0
  54. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/bash_executor.py +0 -0
  55. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/canonical_source.py +0 -0
  56. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/compaction/__init__.py +0 -0
  57. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/compaction/compaction.py +0 -0
  58. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/compaction/utils.py +0 -0
  59. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/context_messages.py +0 -0
  60. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/defaults.py +0 -0
  61. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/event_bus.py +0 -0
  62. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/exec_utils.py +0 -0
  63. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/extensions/__init__.py +0 -0
  64. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/extensions/loader.py +0 -0
  65. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/extensions/runner.py +0 -0
  66. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/extensions/types.py +0 -0
  67. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/inbox_commands.py +0 -0
  68. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/keybindings.py +0 -0
  69. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/messages.py +0 -0
  70. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/model_catalog.py +0 -0
  71. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/navigation.py +0 -0
  72. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/permissions.py +0 -0
  73. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/prompt_templates.py +0 -0
  74. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/remote_session.py +0 -0
  75. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/resource_loader.py +0 -0
  76. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sdk.py +0 -0
  77. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/session_manager.py +0 -0
  78. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/session_staging.py +0 -0
  79. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/__init__.py +0 -0
  80. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/availability.py +0 -0
  81. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/batches.py +0 -0
  82. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/inbox_views.py +0 -0
  83. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/intake.py +0 -0
  84. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/models.py +0 -0
  85. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/operations.py +0 -0
  86. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/ownership.py +0 -0
  87. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/router.py +0 -0
  88. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/store.py +0 -0
  89. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/sessions/turns.py +0 -0
  90. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/settings_manager.py +0 -0
  91. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/system_prompt.py +0 -0
  92. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/timings.py +0 -0
  93. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/tools/__init__.py +0 -0
  94. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/core/transcript_source.py +0 -0
  95. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/main.py +0 -0
  96. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/__init__.py +0 -0
  97. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/__init__.py +0 -0
  98. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/components/__init__.py +0 -0
  99. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/components/assistant_message.py +0 -0
  100. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/components/chat_log.py +0 -0
  101. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/components/custom_editor.py +0 -0
  102. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/components/editor_layout.py +0 -0
  103. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/components/footer.py +0 -0
  104. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/components/permission_prompt.py +0 -0
  105. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/components/tool_execution.py +0 -0
  106. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/components/user_message.py +0 -0
  107. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/provider_auth.py +0 -0
  108. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/run_status.py +0 -0
  109. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/session_presenter.py +0 -0
  110. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/theme.py +0 -0
  111. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/interactive/tool_renderers.py +0 -0
  112. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/modes/print_mode.py +0 -0
  113. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/py.typed +0 -0
  114. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/utils/__init__.py +0 -0
  115. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/utils/frontmatter.py +0 -0
  116. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/utils/git.py +0 -0
  117. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/utils/mime.py +0 -0
  118. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/utils/shell.py +0 -0
  119. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/src/xdog/coding/utils/sleep.py +0 -0
  120. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/acp_owner_agent.py +0 -0
  121. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/batch_helpers.py +0 -0
  122. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/conftest.py +0 -0
  123. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/extension_session_helpers.py +0 -0
  124. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/fixtures/benchmark_tui.py +0 -0
  125. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/fixtures/terminal_client.py +0 -0
  126. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/fixtures/terminal_review.py +0 -0
  127. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/session_owner_process.py +0 -0
  128. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_acp_backend.py +0 -0
  129. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_acp_batch_intake.py +0 -0
  130. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_acp_bridge.py +0 -0
  131. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_acp_cli.py +0 -0
  132. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_acp_enqueue_cli.py +0 -0
  133. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_acp_ingress.py +0 -0
  134. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_acp_ingress_lifecycle.py +0 -0
  135. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_acp_offline_inbox.py +0 -0
  136. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_acp_optional_imports.py +0 -0
  137. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_active_tool_persistence.py +0 -0
  138. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_after_run_compaction.py +0 -0
  139. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_after_run_name.py +0 -0
  140. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_agent_session.py +0 -0
  141. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_batch_config.py +0 -0
  142. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_batch_display.py +0 -0
  143. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_batch_mode_errors.py +0 -0
  144. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_batch_turns.py +0 -0
  145. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_child_active_tools.py +0 -0
  146. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_child_image_admission.py +0 -0
  147. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_child_image_submission.py +0 -0
  148. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_child_queue_ui.py +0 -0
  149. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_cli_args.py +0 -0
  150. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_cli_config_selector.py +0 -0
  151. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_cli_file_processor.py +0 -0
  152. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_coding_config.py +0 -0
  153. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_command_artifact_export_ui.py +0 -0
  154. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_compact_layout.py +0 -0
  155. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_compaction_recovery.py +0 -0
  156. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_context_message_compaction.py +0 -0
  157. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_event_bus.py +0 -0
  158. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_extension_command_results_ui.py +0 -0
  159. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_extension_core_readonly.py +0 -0
  160. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_extension_editor_ui.py +0 -0
  161. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_extension_input_draft_isolation.py +0 -0
  162. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_extension_input_ui.py +0 -0
  163. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_extension_navigation_ui.py +0 -0
  164. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_extension_provider_startup.py +0 -0
  165. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_extension_readonly_ui.py +0 -0
  166. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_extension_session_context_ui.py +0 -0
  167. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_footer_context.py +0 -0
  168. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_image_composer.py +0 -0
  169. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_image_lifecycle_admission.py +0 -0
  170. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_inbox_activation_navigation.py +0 -0
  171. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_inbox_commands.py +0 -0
  172. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_inbox_controller.py +0 -0
  173. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_inbox_crash.py +0 -0
  174. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_inbox_display.py +0 -0
  175. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_inbox_store.py +0 -0
  176. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_inbox_v2.py +0 -0
  177. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_interactive_commands.py +0 -0
  178. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_interactive_keymap.py +0 -0
  179. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_interactive_mode.py +0 -0
  180. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_live_extensions.py +0 -0
  181. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_mcp_auth_projection.py +0 -0
  182. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_mcp_browser.py +0 -0
  183. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_mcp_catalog_watch_ui.py +0 -0
  184. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_mcp_combined_watch_ui.py +0 -0
  185. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_mcp_manual_picker_ui.py +0 -0
  186. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_mcp_modern_browser_cancel.py +0 -0
  187. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_mcp_modern_browser_ui.py +0 -0
  188. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_mcp_retired_gateway.py +0 -0
  189. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_mcp_roots_review_ui.py +0 -0
  190. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_mcp_sampling_ui.py +0 -0
  191. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_mcp_task_terminal.py +0 -0
  192. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_messages.py +0 -0
  193. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_native_session_queue.py +0 -0
  194. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_no_coding_rpc.py +0 -0
  195. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_no_legacy_event_host.py +0 -0
  196. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_oauth_ui.py +0 -0
  197. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_owned_native_model.py +0 -0
  198. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_permissions.py +0 -0
  199. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_prompt_templates.py +0 -0
  200. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_provider_oauth_ui.py +0 -0
  201. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_queue_controls.py +0 -0
  202. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_readonly_ui.py +0 -0
  203. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_removed_child_return_ui.py +0 -0
  204. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_rendered_image_context.py +0 -0
  205. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_renderer_contracts_ui.py +0 -0
  206. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_repository_review.py +0 -0
  207. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_resource_loader.py +0 -0
  208. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_retained_history.py +0 -0
  209. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_run_status.py +0 -0
  210. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_saved_child_drafts.py +0 -0
  211. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_saved_source_ui.py +0 -0
  212. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_sdk_compaction_compat.py +0 -0
  213. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_sdk_runtime_compatibility.py +0 -0
  214. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_sdk_session_state.py +0 -0
  215. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_batches.py +0 -0
  216. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_control_fences.py +0 -0
  217. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_controller.py +0 -0
  218. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_history_display.py +0 -0
  219. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_input_store.py +0 -0
  220. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_manager.py +0 -0
  221. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_message_display.py +0 -0
  222. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_name_ui.py +0 -0
  223. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_navigation.py +0 -0
  224. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_ownership.py +0 -0
  225. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_picker.py +0 -0
  226. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_router.py +0 -0
  227. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_smoke.py +0 -0
  228. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_staging.py +0 -0
  229. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_session_turns.py +0 -0
  230. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_settings_manager.py +0 -0
  231. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_skill_controls_ui.py +0 -0
  232. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_slash_commands.py +0 -0
  233. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_system_prompt.py +0 -0
  234. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_terminal_acceptance.py +0 -0
  235. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_timings.py +0 -0
  236. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_tools_browser.py +0 -0
  237. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_transcript_interaction.py +0 -0
  238. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_transcript_output.py +0 -0
  239. {xdog_coding-2.4.2 → xdog_coding-2.4.3}/tests/test_tui_usability.py +0 -0
@@ -1,3 +1,35 @@
1
+ Metadata-Version: 2.5
2
+ Name: xdog-coding
3
+ Version: 2.4.3
4
+ Summary: Interactive coding agent CLI
5
+ Project-URL: Homepage, https://xdog.942295.xyz
6
+ Project-URL: Repository, https://github.com/litterzhang/xdog
7
+ Project-URL: Documentation, https://xdog.942295.xyz
8
+ Project-URL: Issues, https://github.com/litterzhang/xdog/issues
9
+ Author: HugeMan
10
+ License-Expression: AGPL-3.0-or-later
11
+ License-File: LICENSE
12
+ License-File: LICENSE-EXCEPTION.md
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.12
22
+ Requires-Dist: agent-client-protocol<0.13,>=0.12.1; python_version < '3.15'
23
+ Requires-Dist: click>=8.1.0
24
+ Requires-Dist: pydantic>=2.0
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
29
+ Provides-Extra: skills
30
+ Requires-Dist: xdog-skills>=2.4.3; extra == 'skills'
31
+ Description-Content-Type: text/markdown
32
+
1
33
  # xdog-coding
2
34
 
3
35
  > Platform scope: **Linux only**. Non-Linux adapters and native-platform support
@@ -548,7 +580,8 @@ continuation silently reconnects, replays POSTs or expands configured disclosure
548
580
 
549
581
  ### Task planning and host read-only scope
550
582
 
551
- The builtin **`xdog-planning`** skill uses ordinary conversation or task documents
583
+ The builtin **`xdog-planning`** skill, supplied by `xdog-skills` (install the
584
+ `skills` extra), uses ordinary conversation or task documents
552
585
  for objectives, dependencies, acceptance criteria and evidence-backed progress.
553
586
  It does not create a separate plan database, inspector, execution mode or model
554
587
  loop. The former `/plan`, `PlanPanel` and `update_plan` UI/tool APIs are removed.
@@ -745,7 +778,7 @@ none of these interfaces grants tool permission or full Pi API compatibility.
745
778
 
746
779
  ### Supervised child agents
747
780
 
748
- `/agents start TASK` starts bounded read-only child work. `/agents start --inherit
781
+ `/agents start TASK` starts host-managed read-only child work. `/agents start --inherit
749
782
  TASK` inherits the current host policy; it does not copy approval grants or bypass
750
783
  read-only. Inspect with `/agents list` or `/agents inspect ID`; use `steer ID TEXT`,
751
784
  `follow-up ID TEXT`, `cancel ID`, `wait ID` and `close ID` under `/agents`.
@@ -754,10 +787,34 @@ recursively delegate through their parent's supervision tools.
754
787
 
755
788
  Children share the workspace, so coordinate conflicting writes. Context is copied
756
789
  at admission through a complete tool/result checkpoint. Model/options/tool execution
757
- mode are inherited. Defaults are three active children, 16 retained records,
758
- 120-second execution deadline, 16 model calls and a 32,000 reported-token stop
759
- threshold—not exact billing. Output limits are clamped; input accounting can
760
- overshoot on the final request. Cleanup/persistence may outlast the execution deadline.
790
+ mode are inherited. There is no fixed concurrent-child or retained-record count
791
+ limit, elapsed-time deadline, model-call cap or cumulative reported-token stop
792
+ threshold. The main Agent/host manages lifecycle with cancel/wait/close. Usage
793
+ counters remain reported usage, not exact billable accounting; actual model
794
+ output/context limits, permissions and message/input/image/per-file capacities
795
+ still apply. Complete history uses atomic segmented persistence instead of a
796
+ cumulative 512 KiB / 2,000-message execution cutoff; tool/result pairs are not
797
+ silently truncated.
798
+
799
+ Coding and Claw child factories explicitly enable the Agent's existing built-in
800
+ compaction policy through `AgentConfig(compaction=selected.compaction(child_stream))`
801
+ and provide `archive_compaction=store.archive_compaction` to the supervisor.
802
+ This does **not** change the generic Agent default: automatic compaction is off
803
+ unless explicitly configured. The selected helper uses the executing adapter's
804
+ real context/prompt/output capacity; unknown metadata, context capacity or output
805
+ reserve returns `None` (auto-compaction remains off), not a guessed fallback.
806
+ A host requiring automatic compaction must reject that case or explicitly supply
807
+ trusted capacity/reserve through native `CompactionConfig`.
808
+
809
+ With the policy enabled, one long tool turn can compact repeatedly at safe paired
810
+ boundaries. The supervisor waits for a durable full pre-compaction snapshot before
811
+ the native summary request starts. Archive, summary or stream-cleanup failure does
812
+ not commit a history cut, and cancellation settles owned writes/cleanup. The native
813
+ summary's per-request timeout/capacity checks remain; there is no replacement child
814
+ lifetime cap. Inspect shows the current retained context, possibly with summaries;
815
+ `children.store.compaction_archives(child_id)` reads full earlier snapshots without
816
+ replay. These child archives are separate from the parent session's `/tree`
817
+ compaction checkpoints.
761
818
 
762
819
  Each child has independent Coding approvals and extension workers/state. Parent
763
820
  validation/context hooks and current read-only/permission gates remain authoritative;
@@ -800,10 +857,10 @@ still uses silent no-UI answers to avoid borrowing its separate dialog reservati
800
857
  Complex extension forms are removed; basic child dialogs retain these ownership and cancellation checks.
801
858
 
802
859
 
803
- ### Child specialization and limits
860
+ ### Child specialization and protocol limits
804
861
 
805
862
  `/agents start --label Reviewer --instructions "Inspect only" --tools filesystem,current_time
806
- --fresh --timeout 60 --calls 4 --tokens 8000 -- TASK` specializes a child without
863
+ --fresh -- TASK` specializes a child without
807
864
  changing parent permissions. Options precede the task; `--` preserves a task that
808
865
  starts with flags. Plain tasks preserve quotes/newlines. `--tools none` gives the
809
866
  child no executable tools; otherwise selected names must exist in its inherited tool
@@ -812,11 +869,15 @@ fail visibly. Instructions append to, rather than replace, parent restrictions.
812
869
 
813
870
  In `/agents` press `n`, then Ctrl+G for settings JSON. Supported keys are `label`,
814
871
  `instructions`, `tools` (array or null for inherited tools), `inherit_context`,
815
- `timeout`, `max_model_calls` and `max_tokens`. Enter applies the settings draft only;
872
+ `model`, `thinking` and `preset`. Enter applies the settings draft only;
816
873
  start review requires every page to be painted before confirmation. Resize invalidates
817
874
  that review. This confirmation does NOT approve tool use. Effective settings persist
818
- with child results and appear in complete child source. Request/token caps may be
819
- lowered, not raised above 16 / 32,000; token usage is not exact billable accounting.
875
+ with child results and appear in complete child source. Runtime budget options
876
+ `--timeout`, `--calls`, `--tokens` and config/preset keys `timeout`, `max_model_calls`,
877
+ `max_tokens` are removed and rejected for new starts. Historical child records with
878
+ these budget fields remain readable; the fields are inert and never reapply a
879
+ budget or restart work. This removal does not remove the actual model's per-request
880
+ output token ceiling.
820
881
  `--fresh` omits canonical history/child entry inheritance, not mandatory parent
821
882
  validation/context or the shared workspace. Model/reasoning inherit by default; explicit overrides now use the actual adapter.
822
883
  Named presets now use explicit user configuration. Claw specialized
@@ -840,9 +901,12 @@ host native-tool overrides. Switching to a nonreasoning model disables inherited
840
901
  reasoning; unsupported positive choices fail visibly. Model switches omit inherited/
841
902
  transformed provider continuity and old reasoning from the CHILD copy, leaving parent
842
903
  provenance/history intact. Transformed images are validated; oversized switched-model
843
- contexts fail a conservative byte-based preflight with fresh/lower-output/larger-model
844
- guidance, not automatic summarization or exact token accounting. Parent model/options/
845
- settings/grants never change. Named presets now use explicit user configuration.
904
+ contexts use the same built-in text-token estimate as native compaction, rather
905
+ than comparing text bytes to token capacity. This is not exact tokenizer accounting.
906
+ Host-enabled compaction runs before forwarding the next model request; context that
907
+ cannot be safely compacted or fit still fails explicitly with original history
908
+ retained. Image/capability and actual output limits remain enforced. Parent
909
+ model/options/settings/grants never change. Named presets use explicit user configuration.
846
910
 
847
911
 
848
912
  ### Named child presets
@@ -859,15 +923,14 @@ using this descriptor shape:
859
923
  "instructions": "Review requested code; return findings with file locations.",
860
924
  "tools": ["filesystem", "current_time"],
861
925
  "inherit_context": false,
862
- "max_model_calls": 4,
863
- "max_tokens": 8000
926
+ "label": "Reviewer"
864
927
  }
865
928
  }
866
929
  }
867
930
  }
868
931
  ```
869
932
 
870
- Browse `/agents presets`, or use `/agents start --preset reviewer --tokens 6000 --
933
+ Browse `/agents presets`, or use `/agents start --preset reviewer --label Audit --
871
934
  TASK`. Explicit flags override template fields. Ctrl+P selects a template in a new
872
935
  child form, Ctrl+G adjusts the draft, and full expanded settings/task review still
873
936
  precedes execution. Selection itself makes no model request. Templates cannot encode
@@ -1,33 +1,3 @@
1
- Metadata-Version: 2.5
2
- Name: xdog-coding
3
- Version: 2.4.2
4
- Summary: Interactive coding agent CLI
5
- Project-URL: Homepage, https://xdog.942295.xyz
6
- Project-URL: Repository, https://github.com/litterzhang/xdog
7
- Project-URL: Documentation, https://xdog.942295.xyz
8
- Project-URL: Issues, https://github.com/litterzhang/xdog/issues
9
- Author: HugeMan
10
- License-Expression: AGPL-3.0-or-later
11
- License-File: LICENSE
12
- License-File: LICENSE-EXCEPTION.md
13
- Classifier: Development Status :: 5 - Production/Stable
14
- Classifier: Intended Audience :: Developers
15
- Classifier: Operating System :: POSIX :: Linux
16
- Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.12
18
- Classifier: Programming Language :: Python :: 3.13
19
- Classifier: Topic :: Software Development :: Libraries
20
- Classifier: Typing :: Typed
21
- Requires-Python: >=3.12
22
- Requires-Dist: agent-client-protocol<0.13,>=0.12.1; python_version < '3.15'
23
- Requires-Dist: click>=8.1.0
24
- Requires-Dist: pydantic>=2.0
25
- Requires-Dist: pyyaml>=6.0
26
- Requires-Dist: xdog-agent>=2.4.2
27
- Requires-Dist: xdog-ai[openai]>=2.4.2
28
- Requires-Dist: xdog-tui>=2.4.2
29
- Description-Content-Type: text/markdown
30
-
31
1
  # xdog-coding
32
2
 
33
3
  > Platform scope: **Linux only**. Non-Linux adapters and native-platform support
@@ -578,7 +548,8 @@ continuation silently reconnects, replays POSTs or expands configured disclosure
578
548
 
579
549
  ### Task planning and host read-only scope
580
550
 
581
- The builtin **`xdog-planning`** skill uses ordinary conversation or task documents
551
+ The builtin **`xdog-planning`** skill, supplied by `xdog-skills` (install the
552
+ `skills` extra), uses ordinary conversation or task documents
582
553
  for objectives, dependencies, acceptance criteria and evidence-backed progress.
583
554
  It does not create a separate plan database, inspector, execution mode or model
584
555
  loop. The former `/plan`, `PlanPanel` and `update_plan` UI/tool APIs are removed.
@@ -775,7 +746,7 @@ none of these interfaces grants tool permission or full Pi API compatibility.
775
746
 
776
747
  ### Supervised child agents
777
748
 
778
- `/agents start TASK` starts bounded read-only child work. `/agents start --inherit
749
+ `/agents start TASK` starts host-managed read-only child work. `/agents start --inherit
779
750
  TASK` inherits the current host policy; it does not copy approval grants or bypass
780
751
  read-only. Inspect with `/agents list` or `/agents inspect ID`; use `steer ID TEXT`,
781
752
  `follow-up ID TEXT`, `cancel ID`, `wait ID` and `close ID` under `/agents`.
@@ -784,10 +755,34 @@ recursively delegate through their parent's supervision tools.
784
755
 
785
756
  Children share the workspace, so coordinate conflicting writes. Context is copied
786
757
  at admission through a complete tool/result checkpoint. Model/options/tool execution
787
- mode are inherited. Defaults are three active children, 16 retained records,
788
- 120-second execution deadline, 16 model calls and a 32,000 reported-token stop
789
- threshold—not exact billing. Output limits are clamped; input accounting can
790
- overshoot on the final request. Cleanup/persistence may outlast the execution deadline.
758
+ mode are inherited. There is no fixed concurrent-child or retained-record count
759
+ limit, elapsed-time deadline, model-call cap or cumulative reported-token stop
760
+ threshold. The main Agent/host manages lifecycle with cancel/wait/close. Usage
761
+ counters remain reported usage, not exact billable accounting; actual model
762
+ output/context limits, permissions and message/input/image/per-file capacities
763
+ still apply. Complete history uses atomic segmented persistence instead of a
764
+ cumulative 512 KiB / 2,000-message execution cutoff; tool/result pairs are not
765
+ silently truncated.
766
+
767
+ Coding and Claw child factories explicitly enable the Agent's existing built-in
768
+ compaction policy through `AgentConfig(compaction=selected.compaction(child_stream))`
769
+ and provide `archive_compaction=store.archive_compaction` to the supervisor.
770
+ This does **not** change the generic Agent default: automatic compaction is off
771
+ unless explicitly configured. The selected helper uses the executing adapter's
772
+ real context/prompt/output capacity; unknown metadata, context capacity or output
773
+ reserve returns `None` (auto-compaction remains off), not a guessed fallback.
774
+ A host requiring automatic compaction must reject that case or explicitly supply
775
+ trusted capacity/reserve through native `CompactionConfig`.
776
+
777
+ With the policy enabled, one long tool turn can compact repeatedly at safe paired
778
+ boundaries. The supervisor waits for a durable full pre-compaction snapshot before
779
+ the native summary request starts. Archive, summary or stream-cleanup failure does
780
+ not commit a history cut, and cancellation settles owned writes/cleanup. The native
781
+ summary's per-request timeout/capacity checks remain; there is no replacement child
782
+ lifetime cap. Inspect shows the current retained context, possibly with summaries;
783
+ `children.store.compaction_archives(child_id)` reads full earlier snapshots without
784
+ replay. These child archives are separate from the parent session's `/tree`
785
+ compaction checkpoints.
791
786
 
792
787
  Each child has independent Coding approvals and extension workers/state. Parent
793
788
  validation/context hooks and current read-only/permission gates remain authoritative;
@@ -830,10 +825,10 @@ still uses silent no-UI answers to avoid borrowing its separate dialog reservati
830
825
  Complex extension forms are removed; basic child dialogs retain these ownership and cancellation checks.
831
826
 
832
827
 
833
- ### Child specialization and limits
828
+ ### Child specialization and protocol limits
834
829
 
835
830
  `/agents start --label Reviewer --instructions "Inspect only" --tools filesystem,current_time
836
- --fresh --timeout 60 --calls 4 --tokens 8000 -- TASK` specializes a child without
831
+ --fresh -- TASK` specializes a child without
837
832
  changing parent permissions. Options precede the task; `--` preserves a task that
838
833
  starts with flags. Plain tasks preserve quotes/newlines. `--tools none` gives the
839
834
  child no executable tools; otherwise selected names must exist in its inherited tool
@@ -842,11 +837,15 @@ fail visibly. Instructions append to, rather than replace, parent restrictions.
842
837
 
843
838
  In `/agents` press `n`, then Ctrl+G for settings JSON. Supported keys are `label`,
844
839
  `instructions`, `tools` (array or null for inherited tools), `inherit_context`,
845
- `timeout`, `max_model_calls` and `max_tokens`. Enter applies the settings draft only;
840
+ `model`, `thinking` and `preset`. Enter applies the settings draft only;
846
841
  start review requires every page to be painted before confirmation. Resize invalidates
847
842
  that review. This confirmation does NOT approve tool use. Effective settings persist
848
- with child results and appear in complete child source. Request/token caps may be
849
- lowered, not raised above 16 / 32,000; token usage is not exact billable accounting.
843
+ with child results and appear in complete child source. Runtime budget options
844
+ `--timeout`, `--calls`, `--tokens` and config/preset keys `timeout`, `max_model_calls`,
845
+ `max_tokens` are removed and rejected for new starts. Historical child records with
846
+ these budget fields remain readable; the fields are inert and never reapply a
847
+ budget or restart work. This removal does not remove the actual model's per-request
848
+ output token ceiling.
850
849
  `--fresh` omits canonical history/child entry inheritance, not mandatory parent
851
850
  validation/context or the shared workspace. Model/reasoning inherit by default; explicit overrides now use the actual adapter.
852
851
  Named presets now use explicit user configuration. Claw specialized
@@ -870,9 +869,12 @@ host native-tool overrides. Switching to a nonreasoning model disables inherited
870
869
  reasoning; unsupported positive choices fail visibly. Model switches omit inherited/
871
870
  transformed provider continuity and old reasoning from the CHILD copy, leaving parent
872
871
  provenance/history intact. Transformed images are validated; oversized switched-model
873
- contexts fail a conservative byte-based preflight with fresh/lower-output/larger-model
874
- guidance, not automatic summarization or exact token accounting. Parent model/options/
875
- settings/grants never change. Named presets now use explicit user configuration.
872
+ contexts use the same built-in text-token estimate as native compaction, rather
873
+ than comparing text bytes to token capacity. This is not exact tokenizer accounting.
874
+ Host-enabled compaction runs before forwarding the next model request; context that
875
+ cannot be safely compacted or fit still fails explicitly with original history
876
+ retained. Image/capability and actual output limits remain enforced. Parent
877
+ model/options/settings/grants never change. Named presets use explicit user configuration.
876
878
 
877
879
 
878
880
  ### Named child presets
@@ -889,15 +891,14 @@ using this descriptor shape:
889
891
  "instructions": "Review requested code; return findings with file locations.",
890
892
  "tools": ["filesystem", "current_time"],
891
893
  "inherit_context": false,
892
- "max_model_calls": 4,
893
- "max_tokens": 8000
894
+ "label": "Reviewer"
894
895
  }
895
896
  }
896
897
  }
897
898
  }
898
899
  ```
899
900
 
900
- Browse `/agents presets`, or use `/agents start --preset reviewer --tokens 6000 --
901
+ Browse `/agents presets`, or use `/agents start --preset reviewer --label Audit --
901
902
  TASK`. Explicit flags override template fields. Ctrl+P selects a template in a new
902
903
  child form, Ctrl+G adjusts the draft, and full expanded settings/task review still
903
904
  precedes execution. Selection itself makes no model request. Templates cannot encode
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "xdog-coding"
7
- version = "2.4.2"
7
+ version = "2.4.3"
8
8
  description = "Interactive coding agent CLI"
9
9
  requires-python = ">=3.12"
10
10
  classifiers = [
@@ -22,15 +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.2",
26
- "xdog-agent>=2.4.2",
25
+ "xdog-ai[openai]>=2.4.3",
26
+ "xdog-agent>=2.4.3",
27
27
  "agent-client-protocol>=0.12.1,<0.13; python_version < '3.15'",
28
- "xdog-tui>=2.4.2",
28
+ "xdog-tui>=2.4.3",
29
29
  "pyyaml>=6.0",
30
30
  "click>=8.1.0",
31
31
  "pydantic>=2.0",
32
32
  ]
33
33
 
34
+ [project.optional-dependencies]
35
+ skills = ["xdog-skills>=2.4.3"]
36
+
34
37
  [project.urls]
35
38
  Homepage = "https://xdog.942295.xyz"
36
39
  Repository = "https://github.com/litterzhang/xdog"
@@ -1,3 +1,3 @@
1
1
  """coding - Interactive coding agent CLI."""
2
2
 
3
- __version__ = "2.4.2"
3
+ __version__ = "2.4.3"
@@ -37,7 +37,7 @@ def validate_max_messages_per_turn(value: object) -> int:
37
37
 
38
38
  MONOREPO_NAME = "xdog"
39
39
  APP_NAME = "coding"
40
- VERSION = "2.4.2"
40
+ VERSION = "2.4.3"
41
41
  PROJECT_DIR_NAME = ".coding"
42
42
  ENV_OVERRIDE = "CODING_DIR"
43
43
 
@@ -10,6 +10,7 @@ import uuid
10
10
  from collections.abc import Awaitable, Callable
11
11
  from dataclasses import dataclass, field, replace
12
12
  from functools import wraps
13
+ from importlib.util import find_spec
13
14
  from pathlib import Path
14
15
  from typing import TYPE_CHECKING, Any, Concatenate, ParamSpec, TypeVar
15
16
 
@@ -55,6 +56,7 @@ from xdog.coding.core.system_prompt import build_system_prompt
55
56
  if TYPE_CHECKING:
56
57
  from concurrent.futures import Future
57
58
 
59
+ from xdog.coding.core.goal_adapter import CodingGoalHost
58
60
  from xdog.coding.core.session_staging import StagedExtensions
59
61
  from xdog.coding.core.sessions.batches import TurnInput
60
62
  from xdog.coding.core.sessions.controller import SessionController
@@ -80,11 +82,14 @@ def _idle_change(method: Callable[Concatenate["AgentSession", P], R]) -> Callabl
80
82
  async def owned() -> R:
81
83
  return wrapped(self, *args, **kwargs)
82
84
  try:
83
- same_loop = asyncio.get_running_loop() is controller._loop
85
+ asyncio.get_running_loop()
84
86
  except RuntimeError:
85
- same_loop = False
86
- if same_loop:
87
- raise RuntimeError("Session controls must be submitted to the session owner")
87
+ pass
88
+ else:
89
+ # A synchronous wait would block this caller's loop, which may
90
+ # own the admitted producer's completion/cancellation signal.
91
+ raise RuntimeError("Session controls must be submitted to the session owner; "
92
+ "use an owner operation or asyncio.to_thread from async callers")
88
93
  borrowed = runtime is None
89
94
  if borrowed:
90
95
  with self._sdk_lock:
@@ -144,6 +149,7 @@ def _idle_change(method: Callable[Concatenate["AgentSession", P], R]) -> Callabl
144
149
  async def rebind_sdk() -> None:
145
150
  from xdog.coding.core.sessions.store import InputStore
146
151
  await asyncio.wrap_future(discarded)
152
+ await self._settle_retired_goals()
147
153
  previous = controller.inbox
148
154
  if previous is not None:
149
155
  await previous.retire()
@@ -194,6 +200,11 @@ class AgentSession:
194
200
  _sdk_closing: Future[None] | None = field(default=None, init=False, repr=False)
195
201
  _sdk_retiring_leases: set[SessionLease] = field(default_factory=set, init=False, repr=False)
196
202
  _sdk_disposing: bool = field(default=False, init=False, repr=False)
203
+ _retired_goal_hosts: list[CodingGoalHost] = field(default_factory=list, init=False, repr=False)
204
+ _goal_start: asyncio.Task[None] | None = field(default=None, init=False, repr=False)
205
+ _user_prompt_messages: dict[int, UserMessage] = field(default_factory=dict, init=False, repr=False)
206
+ _authorized_messages: dict[int, UserMessage] = field(default_factory=dict, init=False, repr=False)
207
+ _user_operation_authorized: bool = field(default=False, init=False, repr=False)
197
208
  _sdk_lock: threading.Lock = field(default_factory=threading.Lock, init=False, repr=False)
198
209
  _lease: SessionLease | None = field(default=None, init=False, repr=False)
199
210
  _pending_lease: SessionLease | None = field(default=None, init=False, repr=False)
@@ -259,13 +270,17 @@ class AgentSession:
259
270
 
260
271
  async def _transform_user_input(self, message: UserMessage, source: str,
261
272
  cancel: asyncio.Event | None = None) -> UserMessage | HandledInput:
273
+ authorized = self._user_prompt_messages.get(id(message)) is message
262
274
  try:
263
275
  if self._base_input_transform is not None:
264
276
  value = await self._base_input_transform(message, source, cancel)
265
277
  if isinstance(value, HandledInput):
266
278
  return value
267
279
  message = value
268
- return await self.extensions.input(message, source, channel="coding")
280
+ value = await self.extensions.input(message, source, channel="coding")
281
+ if authorized and isinstance(value, UserMessage):
282
+ self._authorized_messages[id(value)] = value
283
+ return value
269
284
  finally:
270
285
  await self._sync_extension_tools()
271
286
 
@@ -321,7 +336,8 @@ class AgentSession:
321
336
 
322
337
  def _load_children(self) -> None:
323
338
  self.children = CodingChildren(self)
324
- base = tuple(tool for tool in self.agent.state.tools if tool.name not in {"agent_spawn", "agent_control"})
339
+ base = tuple(tool for tool in self.agent.state.tools if tool.name not in {"agent_spawn", "agent_control"}
340
+ and not any(tool is host.tool for host in self._retired_goal_hosts))
325
341
  self.agent.set_tools((*base, *self.children.supervisor.tools()))
326
342
 
327
343
  def _children_idle(self) -> None:
@@ -374,6 +390,42 @@ class AgentSession:
374
390
  finally:
375
391
  await self._sync_extension_tools()
376
392
 
393
+ async def initialize_goals(self) -> None:
394
+ """Attach an installed capability on the existing session execution owner."""
395
+ if find_spec("xdog.skills") is None:
396
+ return
397
+ await self._settle_retired_goals()
398
+ if self.children.goal_host is not None:
399
+ return
400
+ if self._goal_start is None:
401
+ async def start() -> None:
402
+ from xdog.coding.core.goal_adapter import CodingGoalHost
403
+ from xdog.skills.goal.host import OperationContext
404
+ host = await CodingGoalHost.open(
405
+ self, context=lambda: OperationContext(self._user_operation_authorized))
406
+ await host.flush() # Durable obligations only; no model/Goal-state polling.
407
+ self._goal_start = asyncio.create_task(start())
408
+ from xdog.agent.async_work import wait_owned
409
+ try:
410
+ await wait_owned(self._goal_start)
411
+ finally:
412
+ if self._goal_start.done():
413
+ self._goal_start = None
414
+
415
+ def _retire_goal_host(self, host: CodingGoalHost) -> None:
416
+ if host not in self._retired_goal_hosts:
417
+ self._retired_goal_hosts.append(host)
418
+ # The controller's existing settling/close path joins these exact hosts;
419
+ # scheduling is not permission to release their callback loop/lease.
420
+ if not host.loop.is_closed():
421
+ host.loop.call_soon_threadsafe(lambda: asyncio.create_task(host.aclose()))
422
+
423
+ async def _settle_retired_goals(self) -> None:
424
+ from xdog.agent.supervision import settle_on
425
+ for host in tuple(self._retired_goal_hosts):
426
+ await settle_on(host.loop, host.aclose())
427
+ self._retired_goal_hosts.remove(host)
428
+
377
429
  async def initialize_extensions(self) -> None:
378
430
  try:
379
431
  if self.extensions.enabled:
@@ -639,6 +691,8 @@ class AgentSession:
639
691
  async def _close_sdk_owner(self, controller: SessionController) -> None:
640
692
  if controller.inbox is not None:
641
693
  await controller.inbox.retire()
694
+ if self._sdk_disposing or self.children.goal_host is not None or self._retired_goal_hosts:
695
+ await self._aclose_resources()
642
696
  self._release_sdk_leases()
643
697
 
644
698
  async def _acquire_owner(self) -> tuple[SessionController, bool]:
@@ -664,7 +718,10 @@ class AgentSession:
664
718
  from xdog.coding.core.sessions.intake import attach_inbox
665
719
  attach_inbox(controller)
666
720
  controller._close_hook = lambda: self._close_sdk_owner(controller)
667
- controller.start()
721
+ # Optional callback capabilities outlive an individual
722
+ # SDK await/asyncio.run; retain the one controller's own
723
+ # supported loop, never a second controller or daemon.
724
+ controller.start(own_thread=find_spec("xdog.skills") is not None)
668
725
  self._sdk_controller = controller
669
726
  self._sdk_users += 1
670
727
  return self._sdk_controller, True
@@ -673,7 +730,8 @@ class AgentSession:
673
730
  def _release_sdk_owner(self, controller: SessionController) -> Future[None] | None:
674
731
  with self._sdk_lock:
675
732
  self._sdk_users -= 1
676
- if self._sdk_users == 0 and self._sdk_controller is controller:
733
+ if (self._sdk_users == 0 and self._sdk_controller is controller
734
+ and self.children.goal_host is None and not self._retired_goal_hosts):
677
735
  self._sdk_controller = None
678
736
  self._sdk_closing = controller.close()
679
737
  return self._sdk_closing
@@ -746,7 +804,10 @@ class AgentSession:
746
804
  raise ValueError('A turn requires distinct input messages')
747
805
  if not isinstance(batch_id, str) or not batch_id.strip() or len(batch_id.encode()) > 256 or '\x00' in batch_id:
748
806
  raise ValueError('Invalid batch identity')
749
- if sum(input_size(item) for item in inputs) > MAX_BATCH_BYTES:
807
+ owner = self.runtime.controller if self.runtime is not None else self._sdk_controller
808
+ maximum = (owner.input_byte_limit(inputs[0])
809
+ if len(inputs) == 1 and owner is not None and owner.owns_current_task else MAX_BATCH_BYTES)
810
+ if sum(input_size(item) for item in inputs) > maximum:
750
811
  raise ValueError('Batch input exceeds capacity')
751
812
  origins = tuple(item.input_origin or ('user' if item.value.origin == 'human' else 'session_input')
752
813
  for item in inputs)
@@ -756,8 +817,12 @@ class AgentSession:
756
817
  raise ValueError('Canonical continuation cannot share a batch')
757
818
  images = tuple(image for item in inputs for image in item.images)
758
819
  context_snapshot = await self.context_messages.capture() if 'user' in origins else None
820
+ self._user_operation_authorized = False
821
+ self._user_prompt_messages.clear()
822
+ self._authorized_messages.clear()
759
823
  try:
760
824
  self.handled_feedback = []
825
+ await self.initialize_goals()
761
826
  if images:
762
827
  from xdog.ai.utils.image_files import validate_references
763
828
  await asyncio.to_thread(validate_references, images, self.model_info)
@@ -794,6 +859,9 @@ class AgentSession:
794
859
  event_stream = await self.agent.continue_()
795
860
  else:
796
861
  messages = [agent_message(item) for item in inputs]
862
+ self._user_prompt_messages = {
863
+ id(message): message for message, origin in zip(messages, origins, strict=True)
864
+ if origin == "user" and isinstance(message, UserMessage)}
797
865
  event_stream = await self.agent.prompt(messages,
798
866
  initial_prompt_context=(lambda: self.context_messages.admit(context_snapshot))
799
867
  if context_snapshot is not None else None)
@@ -817,6 +885,9 @@ class AgentSession:
817
885
 
818
886
  return last_assistant
819
887
  finally:
888
+ self._user_operation_authorized = False
889
+ self._user_prompt_messages.clear()
890
+ self._authorized_messages.clear()
820
891
  await self._sync_extension_tools()
821
892
  self._expire_turn_scoped_skills()
822
893
 
@@ -1519,6 +1590,9 @@ class AgentSession:
1519
1590
  self.agent.set_system_prompt(prompt + self.access.state.prompt())
1520
1591
  def _on_agent_event(self, event: AgentEvent) -> None:
1521
1592
  """Handle agent lifecycle events."""
1593
+ if (isinstance(event, MessageEndEvent) and isinstance(event.message, UserMessage)
1594
+ and self._authorized_messages.get(id(event.message)) is event.message):
1595
+ self._user_operation_authorized = True
1522
1596
  if isinstance(event, AgentEndEvent):
1523
1597
  self._persist()
1524
1598
 
@@ -1607,6 +1681,9 @@ class AgentSession:
1607
1681
 
1608
1682
  async def _aclose_resources(self) -> None:
1609
1683
  await self.children.supervisor.aclose()
1684
+ if self.children.goal_host is not None:
1685
+ await self.children.goal_host.aclose()
1686
+ await self._settle_retired_goals()
1610
1687
  self.extension_dialogs.close()
1611
1688
  await self.extensions.aclose()
1612
1689
  if self.mcp is not None: