ayder-cli 2.5.0__tar.gz → 2.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (349) hide show
  1. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/.github/workflows/python-package.yml +3 -0
  2. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/PKG-INFO +9 -7
  3. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/README.md +8 -6
  4. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/GATE.md +1 -1
  5. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/PROJECT_STRUCTURE.md +2 -2
  6. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/config.toml.example +2 -2
  7. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/pyproject.toml +1 -1
  8. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/registry.py +3 -1
  9. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/application/runtime_factory.py +26 -3
  10. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/context.py +65 -3
  11. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/skills.py +2 -1
  12. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/prompts.py +52 -0
  13. ayder_cli-2.5.1/src/ayder_cli/skills/development-workflow/SKILL.md +27 -0
  14. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/filesystem_definitions.py +4 -4
  15. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/shell_definitions.py +2 -1
  16. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/task_definitions.py +12 -5
  17. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/task_tool.py +107 -12
  18. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/definition.py +22 -1
  19. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/app.py +3 -2
  20. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_worktree_isolation.py +27 -0
  21. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/application/test_runtime_factory.py +3 -0
  22. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/conftest.py +9 -0
  23. ayder_cli-2.5.1/tests/core/test_scratch_dir.py +115 -0
  24. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_skills.py +4 -1
  25. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_skills_builtin_sync.py +4 -4
  26. ayder_cli-2.5.1/tests/test_prompts_environment.py +102 -0
  27. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_definition_discovery.py +39 -0
  28. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_skill_tool.py +1 -1
  29. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_task_tool.py +114 -3
  30. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_system_prompt_no_structure.py +10 -0
  31. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/uv.lock +2 -2
  32. ayder_cli-2.5.0/src/ayder_cli/skills/engineering/SKILL.md +0 -35
  33. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/.github/workflows/ci.yml +0 -0
  34. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/.gitignore +0 -0
  35. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/.python-version +0 -0
  36. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/AGENTS.md +0 -0
  37. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/LICENSE +0 -0
  38. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/README_AGENT_WORKFLOW.md +0 -0
  39. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/README_OLLAMA.md +0 -0
  40. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/cc.png +0 -0
  41. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/superpowers/plans/2026-06-26-file-editor-improvements.md +0 -0
  42. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/superpowers/plans/2026-06-26-session-save-resume.md +0 -0
  43. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/superpowers/specs/2026-06-26-file-editor-improvements-design.md +0 -0
  44. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/docs/superpowers/specs/2026-06-26-session-save-resume-design.md +0 -0
  45. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/check_exception_handlers.py +0 -0
  46. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/check_log_arguments.py +0 -0
  47. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/check_logging_imports.py +0 -0
  48. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/exception_baseline.txt +0 -0
  49. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/find_percent_logging.py +0 -0
  50. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/log_argument_baseline.txt +0 -0
  51. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/scripts/logging_gates.py +0 -0
  52. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/__init__.py +0 -0
  53. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/__main__.py +0 -0
  54. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/__init__.py +0 -0
  55. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/callbacks.py +0 -0
  56. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/config.py +0 -0
  57. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/run.py +0 -0
  58. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/runner.py +0 -0
  59. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/tool.py +0 -0
  60. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/agents/worktree.py +0 -0
  61. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/application/README.md +0 -0
  62. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/application/__init__.py +0 -0
  63. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/application/execution_policy.py +0 -0
  64. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/application/message_contract.py +0 -0
  65. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/application/validation.py +0 -0
  66. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/cli.py +0 -0
  67. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/cli_callbacks.py +0 -0
  68. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/cli_runner.py +0 -0
  69. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/console.py +0 -0
  70. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/cache_monitor.py +0 -0
  71. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/config.py +0 -0
  72. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/config_migration.py +0 -0
  73. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/context_manager.py +0 -0
  74. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/context_manager_factory.py +0 -0
  75. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/default_context_manager.py +0 -0
  76. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/ollama_context_manager.py +0 -0
  77. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/reasoning.py +0 -0
  78. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/result.py +0 -0
  79. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/core/session.py +0 -0
  80. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/diagnostics.py +0 -0
  81. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/log.py +0 -0
  82. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/logging_config.py +0 -0
  83. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/loops/__init__.py +0 -0
  84. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/loops/chat_loop.py +0 -0
  85. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/masking.py +0 -0
  86. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/parser.py +0 -0
  87. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/process_manager.py +0 -0
  88. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/__init__.py +0 -0
  89. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/base.py +0 -0
  90. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/evren.py +0 -0
  91. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/claude.py +0 -0
  92. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/deepseek.py +0 -0
  93. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/gemini.py +0 -0
  94. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/glm.py +0 -0
  95. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama.py +0 -0
  96. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/__init__.py +0 -0
  97. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/_errors.py +0 -0
  98. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/base.py +0 -0
  99. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/deepseek.py +0 -0
  100. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/generic_native.py +0 -0
  101. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/generic_xml.py +0 -0
  102. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/matrix.py +0 -0
  103. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/minimax.py +0 -0
  104. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/qwen3.py +0 -0
  105. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_drivers/registry.py +0 -0
  106. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/ollama_inspector.py +0 -0
  107. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/openai.py +0 -0
  108. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/impl/qwen.py +0 -0
  109. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/orchestrator.py +0 -0
  110. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/providers/retry.py +0 -0
  111. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/services/__init__.py +0 -0
  112. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/services/interactions.py +0 -0
  113. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/services/messaging_inbox.py +0 -0
  114. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/themes/__init__.py +0 -0
  115. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/themes/ayder.py +0 -0
  116. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/themes/claude.py +0 -0
  117. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/__init__.py +0 -0
  118. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/__init__.py +0 -0
  119. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/background_process_tool.py +0 -0
  120. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/context.py +0 -0
  121. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/context_definitions.py +0 -0
  122. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/filesystem.py +0 -0
  123. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/note_tool.py +0 -0
  124. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/notes.py +0 -0
  125. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/notes_definitions.py +0 -0
  126. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/process_manager_definitions.py +0 -0
  127. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/search.py +0 -0
  128. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/search_definitions.py +0 -0
  129. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/shell.py +0 -0
  130. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/skill.py +0 -0
  131. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/skill_definitions.py +0 -0
  132. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/tasks.py +0 -0
  133. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/utils_tools.py +0 -0
  134. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/utils_tools_definitions.py +0 -0
  135. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/web.py +0 -0
  136. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/builtins/web_definitions.py +0 -0
  137. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/execution.py +0 -0
  138. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/hooks.py +0 -0
  139. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/mcp.py +0 -0
  140. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/mcp_client.py +0 -0
  141. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/normalization.py +0 -0
  142. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/plugin_api.py +0 -0
  143. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/plugin_github.py +0 -0
  144. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/plugin_manager.py +0 -0
  145. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/plugin_status.py +0 -0
  146. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/registry.py +0 -0
  147. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/schemas.py +0 -0
  148. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tools/utils.py +0 -0
  149. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/__init__.py +0 -0
  150. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/adapter.py +0 -0
  151. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/commands.py +0 -0
  152. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/helpers.py +0 -0
  153. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/keybindings.py +0 -0
  154. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/parser.py +0 -0
  155. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/rendering.py +0 -0
  156. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/screens.py +0 -0
  157. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/theme_manager.py +0 -0
  158. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/types.py +0 -0
  159. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/tui/widgets.py +0 -0
  160. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/ui.py +0 -0
  161. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/src/ayder_cli/version.py +0 -0
  162. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/COVERAGE.md +0 -0
  163. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/__init__.py +0 -0
  164. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/__init__.py +0 -0
  165. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_agent_consolidated.py +0 -0
  166. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_agent_severity.py +0 -0
  167. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_agent_tools.py +0 -0
  168. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_callbacks.py +0 -0
  169. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_config.py +0 -0
  170. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_integration.py +0 -0
  171. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_queue.py +0 -0
  172. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_registry.py +0 -0
  173. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_run.py +0 -0
  174. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_runner.py +0 -0
  175. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_runner_provider_unavailable.py +0 -0
  176. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_tool.py +0 -0
  177. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/agents/test_worktree_helpers.py +0 -0
  178. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/application/test_argument_canonicalization.py +0 -0
  179. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/application/test_execution_result_truthfulness.py +0 -0
  180. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/application/test_message_contract.py +0 -0
  181. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/client/test_main.py +0 -0
  182. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/convergence/__init__.py +0 -0
  183. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/convergence/test_execution_policy_parity.py +0 -0
  184. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/convergence/test_runtime_wiring.py +0 -0
  185. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/convergence/test_validation_path.py +0 -0
  186. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_asyncio_bridge.py +0 -0
  187. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_cache_monitor.py +0 -0
  188. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config.py +0 -0
  189. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config_coverage.py +0 -0
  190. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config_migration.py +0 -0
  191. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config_provider_logging.py +0 -0
  192. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config_retry.py +0 -0
  193. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config_skills.py +0 -0
  194. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_config_v2.py +0 -0
  195. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_context_manager_factory.py +0 -0
  196. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_default_config_evren.py +0 -0
  197. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_default_context_manager.py +0 -0
  198. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_default_context_manager_should_compact.py +0 -0
  199. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_default_context_newest_unit.py +0 -0
  200. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_default_context_skill_resupply.py +0 -0
  201. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_event_emission.py +0 -0
  202. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_event_stream.py +0 -0
  203. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_exception_guarantee.py +0 -0
  204. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_exception_hooks.py +0 -0
  205. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_log_facade.py +0 -0
  206. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_logging_config_keys.py +0 -0
  207. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_logging_sinks.py +0 -0
  208. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_loguru_caplog.py +0 -0
  209. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_max_output_tokens_default.py +0 -0
  210. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_ollama_compaction_persistence.py +0 -0
  211. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_ollama_context_manager.py +0 -0
  212. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_ollama_context_manager_cache_monitor.py +0 -0
  213. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_ollama_context_manager_max_history.py +0 -0
  214. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_ollama_skill_resupply.py +0 -0
  215. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_parameter_aliasing.py +0 -0
  216. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_parser.py +0 -0
  217. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_reasoning_config.py +0 -0
  218. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_session.py +0 -0
  219. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_session_id_threading.py +0 -0
  220. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/core/test_sink_masking.py +0 -0
  221. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/__init__.py +0 -0
  222. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_base.py +0 -0
  223. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_chat_loop_hook.py +0 -0
  224. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_chat_loop_tool_truncation.py +0 -0
  225. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_loop_severity.py +0 -0
  226. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_required_args_aliases.py +0 -0
  227. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_tool_argument_integrity.py +0 -0
  228. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/loops/test_tool_batch_cancellation.py +0 -0
  229. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/__init__.py +0 -0
  230. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/__init__.py +0 -0
  231. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_base.py +0 -0
  232. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_deepseek.py +0 -0
  233. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_errors.py +0 -0
  234. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_fallback.py +0 -0
  235. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_generic_native.py +0 -0
  236. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_generic_xml.py +0 -0
  237. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_matrix.py +0 -0
  238. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_minimax.py +0 -0
  239. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_provider_integration.py +0 -0
  240. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_qwen3.py +0 -0
  241. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/ollama_drivers/test_registry.py +0 -0
  242. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_claude_stream_tool_calls.py +0 -0
  243. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_evren.py +0 -0
  244. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_gemini_function_calls.py +0 -0
  245. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_glm_async.py +0 -0
  246. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_ollama_inspector.py +0 -0
  247. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_ollama_native.py +0 -0
  248. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_ollama_parallel_tool_call_ids.py +0 -0
  249. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_ollama_xml.py +0 -0
  250. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_ollama_xml_autoroute.py +0 -0
  251. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_ollama_xml_usage.py +0 -0
  252. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_openai_list_models.py +0 -0
  253. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_orchestrator_capabilities.py +0 -0
  254. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_provider_channel_binding.py +0 -0
  255. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_provider_severity.py +0 -0
  256. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_qwen_async.py +0 -0
  257. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_reasoning_effort.py +0 -0
  258. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_retry_classifier.py +0 -0
  259. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_retry_integration.py +0 -0
  260. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_retrying_provider.py +0 -0
  261. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/providers/test_skill_load_prefix.py +0 -0
  262. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/scripts/test_exception_gate.py +0 -0
  263. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/scripts/test_log_argument_gate.py +0 -0
  264. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/scripts/test_logging_policy_gates.py +0 -0
  265. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/scripts/test_loguru_private_shape.py +0 -0
  266. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/services/test_boundary.py +0 -0
  267. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/services/test_interaction_sink.py +0 -0
  268. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/services/test_messaging_inbox.py +0 -0
  269. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_cli.py +0 -0
  270. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_cli_callbacks.py +0 -0
  271. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_context.py +0 -0
  272. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_env_manager.py +0 -0
  273. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_logging_config.py +0 -0
  274. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_notes.py +0 -0
  275. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_process_manager.py +0 -0
  276. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_prompts_general.py +0 -0
  277. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/test_tasks.py +0 -0
  278. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/__init__.py +0 -0
  279. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_agent_notes.py +0 -0
  280. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_background_process_tool.py +0 -0
  281. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_bash_tool.py +0 -0
  282. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_context_storage_confinement.py +0 -0
  283. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_di_injection.py +0 -0
  284. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_file_editor_hardening.py +0 -0
  285. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_file_editor_size_limit.py +0 -0
  286. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_impl.py +0 -0
  287. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_impl_coverage.py +0 -0
  288. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_mcp.py +0 -0
  289. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_mcp_client.py +0 -0
  290. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_note_tool.py +0 -0
  291. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_notes_api.py +0 -0
  292. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_notes_confinement.py +0 -0
  293. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_path_security.py +0 -0
  294. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_plugin_api.py +0 -0
  295. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_plugin_github.py +0 -0
  296. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_plugin_loading.py +0 -0
  297. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_plugin_manager.py +0 -0
  298. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_plugin_status.py +0 -0
  299. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_registry.py +0 -0
  300. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_registry_coverage.py +0 -0
  301. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_result.py +0 -0
  302. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_schemas.py +0 -0
  303. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_search_codebase.py +0 -0
  304. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_search_hardening.py +0 -0
  305. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_skill_catalog_and_filter.py +0 -0
  306. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_skill_scope_wiring.py +0 -0
  307. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_task_path_confinement.py +0 -0
  308. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_tool_severity.py +0 -0
  309. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_unexpected_args.py +0 -0
  310. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_utils.py +0 -0
  311. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tools/test_web.py +0 -0
  312. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/__init__.py +0 -0
  313. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_agent_list_screen.py +0 -0
  314. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_do_clear_coordination.py +0 -0
  315. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_evren_terms.py +0 -0
  316. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_follow_mode.py +0 -0
  317. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_help_screen.py +0 -0
  318. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_input_box.py +0 -0
  319. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_keybindings.py +0 -0
  320. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_multi_select_screen.py +0 -0
  321. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_multiline_input.py +0 -0
  322. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_paste.py +0 -0
  323. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_peer_message_turn.py +0 -0
  324. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_pending_compact_consumer.py +0 -0
  325. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_pull_delivery.py +0 -0
  326. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_resume.py +0 -0
  327. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_status_bar_badges.py +0 -0
  328. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_themes.py +0 -0
  329. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_turn_consumer.py +0 -0
  330. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/tui/test_widgets.py +0 -0
  331. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_confirm_screen.py +0 -0
  332. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_diff_preview.py +0 -0
  333. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_plugin_autoenable.py +0 -0
  334. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_provider_switch.py +0 -0
  335. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_run_tui_startup.py +0 -0
  336. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_assistant_sanitization.py +0 -0
  337. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_chat_loop.py +0 -0
  338. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_commands_agent.py +0 -0
  339. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_commands_effort.py +0 -0
  340. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_commands_logging.py +0 -0
  341. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_commands_plugin.py +0 -0
  342. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_commands_provider.py +0 -0
  343. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_commands_skill.py +0 -0
  344. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_helpers.py +0 -0
  345. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_temporal_command.py +0 -0
  346. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_tui_widgets.py +0 -0
  347. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_ui.py +0 -0
  348. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_ui_coverage.py +0 -0
  349. {ayder_cli-2.5.0 → ayder_cli-2.5.1}/tests/ui/test_ui_verbose.py +0 -0
@@ -11,6 +11,9 @@ on:
11
11
 
12
12
  jobs:
13
13
  build-and-publish:
14
+ # The pypi environment admits only main and release-*/beta-* tags, so on a
15
+ # pull request the job is refused before any step runs and the PR shows red.
16
+ if: github.event_name == 'push'
14
17
  runs-on: ubuntu-latest
15
18
  # This job only runs in the context of your 'pypi' environment
16
19
  environment: pypi
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ayder-cli
3
- Version: 2.5.0
3
+ Version: 2.5.1
4
4
  Summary: AI agent for any LLMs
5
5
  Project-URL: Homepage, https://github.com/ayder/ayder-cli
6
6
  Project-URL: Repository, https://github.com/ayder/ayder-cli.git
@@ -82,7 +82,7 @@ LLMs on their own can only generate text. To be a useful coding assistant, the m
82
82
 
83
83
  Each tool has an OpenAI-compatible JSON schema so models that support function calling can use them natively. For models that don't, ayder-cli also parses a custom XML-like syntax (`<function=name><parameter=key>value</parameter></function>`) as a fallback.
84
84
 
85
- - **Path sandboxing**: All file operations are confined to the project root via `ProjectContext`. Path traversal attacks (`../`) and absolute paths outside the project are blocked.
85
+ - **Path sandboxing**: All file operations are confined to the project root via `ProjectContext`. Path traversal attacks (`../`) and absolute paths outside the project are blocked. The one exception is the session scratch directory, `/tmp/ayder-<uid>/<project>-<hash>/<session>/` (mode 0700, one subdirectory per agent run), which the system prompt names as the place for temporary files and which the file tools accept. It is not cleaned up; the OS clears `/tmp`.
86
86
  - **Safe mode** (TUI): Blocks `file_editor`, `run_shell_command`, `run_background_process`, `kill_background_process`, and `fetch_web`.
87
87
  - Every tool call requires your confirmation before it runs -- you always stay in control. Use `-r`, `-w`, `-x` flags to auto-approve tool categories.
88
88
  - You may also prefer to run ayder-cli in a container for additional security.
@@ -208,7 +208,7 @@ max_output_tokens = 32768 # Max tokens in LLM response
208
208
  max_history_messages = 30 # Messages kept in history
209
209
  prompt = "STANDARD" # System prompt tier: MINIMAL, STANDARD, EXTENDED
210
210
  tool_tags = ["core", "metadata"] # Enabled tool tags (see /plugin)
211
- # skills = ["engineering"] # or "none"; default: the built-in skills
211
+ # skills = ["development-workflow"] # or "none"; default: the built-in skills
212
212
  agent_timeout = 300 # Seconds before a background agent is cancelled
213
213
 
214
214
  [logging]
@@ -354,7 +354,8 @@ ayder -f instructions.txt
354
354
  ayder --stdin < prompt.txt
355
355
 
356
356
  # Override the main LLM system prompt with a file
357
- # (tool instructions are still appended)
357
+ # (the environment section with working directory and start time,
358
+ # and the tool instructions, are still appended)
358
359
  ayder --system-prompt prompt-file.md "refactor this code"
359
360
  ```
360
361
 
@@ -478,8 +479,9 @@ later one overrides an earlier one with the same name:
478
479
  2. your skills in `~/.ayder/skills/<name>/`
479
480
  3. project skills in `<project>/.ayder/skills/<name>/`
480
481
 
481
- ayder ships an `engineering` skill (build, change, debug or review code;
482
- research; plan multi-step work). The system prompt is a general assistant;
482
+ ayder ships a `development-workflow` skill for multi-step software work: a plan
483
+ note and tasks, approval before any project file changes, then execution with
484
+ per-task status. Small edits and questions skip it. The system prompt is a general assistant;
483
485
  when a skill fits the request, the model loads it itself.
484
486
 
485
487
  The skills enabled for a session are listed in the system prompt under
@@ -488,7 +490,7 @@ model. The `skills` setting chooses them:
488
490
 
489
491
  | `skills` | Enabled skills |
490
492
  |---|---|
491
- | not set | the built-in skills (`engineering`), including your or the project's copy of the same name |
493
+ | not set | the built-in skills (`development-workflow`), including your or the project's copy of the same name |
492
494
  | `"none"` or `[]` | none: no skill tool, no catalog |
493
495
  | `["a", "b"]` | exactly these names, from any layer |
494
496
 
@@ -39,7 +39,7 @@ LLMs on their own can only generate text. To be a useful coding assistant, the m
39
39
 
40
40
  Each tool has an OpenAI-compatible JSON schema so models that support function calling can use them natively. For models that don't, ayder-cli also parses a custom XML-like syntax (`<function=name><parameter=key>value</parameter></function>`) as a fallback.
41
41
 
42
- - **Path sandboxing**: All file operations are confined to the project root via `ProjectContext`. Path traversal attacks (`../`) and absolute paths outside the project are blocked.
42
+ - **Path sandboxing**: All file operations are confined to the project root via `ProjectContext`. Path traversal attacks (`../`) and absolute paths outside the project are blocked. The one exception is the session scratch directory, `/tmp/ayder-<uid>/<project>-<hash>/<session>/` (mode 0700, one subdirectory per agent run), which the system prompt names as the place for temporary files and which the file tools accept. It is not cleaned up; the OS clears `/tmp`.
43
43
  - **Safe mode** (TUI): Blocks `file_editor`, `run_shell_command`, `run_background_process`, `kill_background_process`, and `fetch_web`.
44
44
  - Every tool call requires your confirmation before it runs -- you always stay in control. Use `-r`, `-w`, `-x` flags to auto-approve tool categories.
45
45
  - You may also prefer to run ayder-cli in a container for additional security.
@@ -165,7 +165,7 @@ max_output_tokens = 32768 # Max tokens in LLM response
165
165
  max_history_messages = 30 # Messages kept in history
166
166
  prompt = "STANDARD" # System prompt tier: MINIMAL, STANDARD, EXTENDED
167
167
  tool_tags = ["core", "metadata"] # Enabled tool tags (see /plugin)
168
- # skills = ["engineering"] # or "none"; default: the built-in skills
168
+ # skills = ["development-workflow"] # or "none"; default: the built-in skills
169
169
  agent_timeout = 300 # Seconds before a background agent is cancelled
170
170
 
171
171
  [logging]
@@ -311,7 +311,8 @@ ayder -f instructions.txt
311
311
  ayder --stdin < prompt.txt
312
312
 
313
313
  # Override the main LLM system prompt with a file
314
- # (tool instructions are still appended)
314
+ # (the environment section with working directory and start time,
315
+ # and the tool instructions, are still appended)
315
316
  ayder --system-prompt prompt-file.md "refactor this code"
316
317
  ```
317
318
 
@@ -435,8 +436,9 @@ later one overrides an earlier one with the same name:
435
436
  2. your skills in `~/.ayder/skills/<name>/`
436
437
  3. project skills in `<project>/.ayder/skills/<name>/`
437
438
 
438
- ayder ships an `engineering` skill (build, change, debug or review code;
439
- research; plan multi-step work). The system prompt is a general assistant;
439
+ ayder ships a `development-workflow` skill for multi-step software work: a plan
440
+ note and tasks, approval before any project file changes, then execution with
441
+ per-task status. Small edits and questions skip it. The system prompt is a general assistant;
440
442
  when a skill fits the request, the model loads it itself.
441
443
 
442
444
  The skills enabled for a session are listed in the system prompt under
@@ -445,7 +447,7 @@ model. The `skills` setting chooses them:
445
447
 
446
448
  | `skills` | Enabled skills |
447
449
  |---|---|
448
- | not set | the built-in skills (`engineering`), including your or the project's copy of the same name |
450
+ | not set | the built-in skills (`development-workflow`), including your or the project's copy of the same name |
449
451
  | `"none"` or `[]` | none: no skill tool, no catalog |
450
452
  | `["a", "b"]` | exactly these names, from any layer |
451
453
 
@@ -12,7 +12,7 @@ Input: the candidate SHA.
12
12
  gates and the test suite, and stops at the first failing task.
13
13
  4. Copy the final pytest summary line (`=== N passed, M skipped in …s ===`) verbatim.
14
14
 
15
- Last measured: `2707 passed, 2 skipped` on `chore/prompt-tests-injection-only` (2026-10-16).
15
+ Last measured: `2743 passed, 2 skipped` on `fix/session-environment-prompt` (2026-10-19, 2.5.1).
16
16
 
17
17
  ## Report format
18
18
 
@@ -100,7 +100,7 @@ ayder-cli is an AI agent chat client with a modular, layered architecture:
100
100
  4. **Single Loop**: `ChatLoop` (in `loops/chat_loop.py`) owns the full async LLM + tool execution loop; both CLI and TUI route through it
101
101
  5. **Single Execution Path**: `ExecutionPolicy.execute_with_registry()` is the sole tool execution entry point; validation → permission → execute, no inline policy in loop code
102
102
  6. **Single Validation Path**: `ValidationAuthority → SchemaValidator` is the only validation stage; schema derived from live `TOOL_DEFINITIONS` registry (no hardcoded lists)
103
- 7. **Sandboxed Paths**: All file operations go through `ProjectContext` for security
103
+ 7. **Sandboxed Paths**: All file operations go through `ProjectContext` for security (project root plus the session scratch directory from `new_scratch_dir`)
104
104
  8. **Single Execution Engine**: Both TUI and CLI drive `ChatLoop.run()` through the `ChatCallbacks` protocol (`AppCallbacks` and `CliCallbacks` respectively); CLI runs it via `asyncio.run`
105
105
 
106
106
  ---
@@ -594,7 +594,7 @@ AyderApp is the main Textual application implementing a chat-style interface:
594
594
  The application manages:
595
595
  - LLM provider setup and configuration
596
596
  - Tool registry initialization with middleware
597
- - System prompt construction (base prompt + tool prompts + skill catalog; no project tree)
597
+ - System prompt construction (base prompt + environment section + tool prompts + skill catalog; no project tree). The environment section (`prompts.build_environment_prompt`) gives the absolute working directory and the session start date and time (ISO 8601, local time with UTC offset). It is built once per session and reused on `/model` rebuilds.
598
598
  - Process manager for background operations
599
599
 
600
600
  ### Chat Loop Summary (src/ayder_cli/loops/chat_loop.py)
@@ -100,7 +100,7 @@ tool_tags = ["core", "metadata", "background", "http"]
100
100
  # Skills the session's model may load (listed under "### Skills" in the system
101
101
  # prompt). Not set = the built-in skills; "none" = no skill tool; or a strict
102
102
  # list. A [llm.*] profile's skills wins over this one for the session.
103
- # skills = ["engineering"]
103
+ # skills = ["development-workflow"]
104
104
 
105
105
  [ui]
106
106
  # TUI layout (theme) — picks the chrome/layout:
@@ -229,7 +229,7 @@ think = true # default; set false if the selected model r
229
229
  [agents.pm_spec]
230
230
  provider = "ollama_cloud"
231
231
  model = "glm-5.2:cloud"
232
- # skills = ["engineering"] # wins over the provider profile's skills; [app] is never read
232
+ # skills = ["development-workflow"] # wins over the provider profile's skills; [app] is never read
233
233
  temperature = 0.4
234
234
  max_output_tokens = 8192
235
235
  reasoning_effort = "high"
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ayder-cli"
7
- version = "2.5.0"
7
+ version = "2.5.1"
8
8
  description = "AI agent for any LLMs"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -384,7 +384,9 @@ class AgentRegistry:
384
384
  worktree_path = wt_dir
385
385
  self._session_worktrees.add(wt_dir)
386
386
  run.worktree_path = wt_dir
387
- project_ctx = ProjectContext(wt_dir)
387
+ project_ctx = ProjectContext(
388
+ wt_dir, scratch_dir=self._project_ctx.scratch_dir
389
+ )
388
390
  head_before = await asyncio.to_thread(
389
391
  branch_head, repo_root, run.branch_name
390
392
  )
@@ -6,7 +6,9 @@ eliminating the duplicate `_build_services()` / `AyderApp.__init__()` wiring.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
+ import re
9
10
  from dataclasses import dataclass, field
11
+ from datetime import datetime
10
12
  from pathlib import Path
11
13
  from typing import TYPE_CHECKING, Any
12
14
 
@@ -16,13 +18,14 @@ from ayder_cli.core.context_manager_factory import context_manager_factory
16
18
 
17
19
  if TYPE_CHECKING:
18
20
  from ayder_cli.agents.config import AgentConfig
19
- from ayder_cli.core.context import ProjectContext
21
+ from ayder_cli.core.context import ProjectContext, new_scratch_dir
20
22
  from ayder_cli.core.skills import build_scope
21
23
  from ayder_cli.providers import AIProvider, provider_orchestrator
22
24
  from ayder_cli.providers.retry import RetryConfig, RetryingProvider
23
25
  from ayder_cli.tools.registry import ToolRegistry, create_default_registry
24
26
  from ayder_cli.process_manager import ProcessManager
25
27
  from ayder_cli.prompts import (
28
+ build_environment_prompt,
26
29
  get_system_prompt,
27
30
  )
28
31
  from ayder_cli.log import get_logger
@@ -41,6 +44,7 @@ class RuntimeComponents:
41
44
  tool_registry: ToolRegistry
42
45
  system_prompt: str
43
46
  context_manager: Any = field(default=None) # ContextManagerProtocol
47
+ environment_prompt: str = "" # frozen for the session; reused by TUI rebuilds
44
48
 
45
49
 
46
50
  def apply_skill_setting(
@@ -95,6 +99,9 @@ def create_runtime(
95
99
 
96
100
  llm_provider: AIProvider = provider_orchestrator.create(cfg)
97
101
  project_ctx = ProjectContext(project_root)
102
+ scratch_dir = new_scratch_dir(project_ctx.root)
103
+ if scratch_dir is not None:
104
+ project_ctx.scratch_dir = scratch_dir.resolve()
98
105
  process_manager = ProcessManager(max_processes=cfg.max_background_processes)
99
106
 
100
107
  # Create context manager before registry so tools can receive it via DI.
@@ -111,9 +118,12 @@ def create_runtime(
111
118
  base_prompt = system_prompt_override
112
119
  else:
113
120
  base_prompt = get_system_prompt(cfg.prompt)
121
+ environment_prompt = build_environment_prompt(
122
+ project_ctx.root, datetime.now().astimezone(), project_ctx.scratch_dir
123
+ )
114
124
  tool_tags = frozenset(cfg.tool_tags) if cfg.tool_tags else None
115
125
  tool_prompts = tool_registry.get_system_prompts(tags=tool_tags)
116
- system_prompt = base_prompt + tool_prompts
126
+ system_prompt = base_prompt + environment_prompt + tool_prompts
117
127
 
118
128
  # Freeze system prompt after tool schemas are known.
119
129
  tool_schemas = tool_registry.get_schemas(tags=tool_tags)
@@ -129,6 +139,7 @@ def create_runtime(
129
139
  tool_registry=tool_registry,
130
140
  system_prompt=system_prompt,
131
141
  context_manager=context_mgr,
142
+ environment_prompt=environment_prompt,
132
143
  )
133
144
 
134
145
 
@@ -232,7 +243,19 @@ def create_agent_runtime(
232
243
  )
233
244
  tool_tags = frozenset(cfg.tool_tags) if cfg.tool_tags else None
234
245
  tool_prompts = tool_registry.get_system_prompts(tags=tool_tags)
235
- system_prompt = identity_prefix + agent_config.system_prompt + tool_prompts + deliverable_directive
246
+ # Each run gets its own directory inside the session's scratch directory,
247
+ # which the shared ProjectContext already admits.
248
+ agent_scratch = None
249
+ if project_ctx.scratch_dir is not None:
250
+ label = "agent-" + re.sub(r"[^A-Za-z0-9_-]", "-", agent_config.name)
251
+ agent_scratch = new_scratch_dir(project_ctx.root, parent=project_ctx.scratch_dir, label=label)
252
+ environment_prompt = build_environment_prompt(
253
+ project_ctx.root, datetime.now().astimezone(), agent_scratch
254
+ )
255
+ system_prompt = (
256
+ identity_prefix + agent_config.system_prompt + environment_prompt
257
+ + tool_prompts + deliverable_directive
258
+ )
236
259
 
237
260
  # Freeze agent system prompt after tool schemas are known.
238
261
  tool_schemas = tool_registry.get_schemas(tags=tool_tags)
@@ -1,7 +1,64 @@
1
+ import getpass
2
+ import hashlib
1
3
  import os
4
+ import secrets
5
+ import stat
6
+ import tempfile
7
+ from datetime import datetime
2
8
  from pathlib import Path
3
9
 
4
10
 
11
+ def _default_scratch_base() -> Path:
12
+ """``/tmp/ayder-<uid>``: where models already look for temporary space."""
13
+ if hasattr(os, "getuid"):
14
+ return Path("/tmp") / f"ayder-{os.getuid()}"
15
+ return Path(tempfile.gettempdir()) / f"ayder-{getpass.getuser()}"
16
+
17
+
18
+ # Per-user parent of every session scratch directory; tests point it elsewhere.
19
+ SCRATCH_BASE = _default_scratch_base()
20
+
21
+
22
+ def _owned_private_dir(path: Path) -> bool:
23
+ """True when ``path`` itself (not a symlink) is a directory this user owns."""
24
+ st = os.lstat(path)
25
+ if not stat.S_ISDIR(st.st_mode):
26
+ return False
27
+ return not hasattr(os, "getuid") or st.st_uid == os.getuid()
28
+
29
+
30
+ def new_scratch_dir(
31
+ project_root: Path | str, parent: Path | None = None, label: str = "agent"
32
+ ) -> Path | None:
33
+ """Create a private (0700) scratch directory and return it.
34
+
35
+ Without ``parent`` it is a session directory,
36
+ ``SCRATCH_BASE/<project>-<hash>/<YYYYmmdd-HHMMSS>-<hex>``; with ``parent``
37
+ it is ``<parent>/<label>-<hex>``. Returns None when the per-user base is a
38
+ symlink, belongs to someone else, or cannot be created: the session then
39
+ runs without one and the sandbox stays the project root.
40
+ """
41
+ try:
42
+ if parent is None:
43
+ SCRATCH_BASE.mkdir(mode=0o700, parents=True, exist_ok=True)
44
+ if not _owned_private_dir(SCRATCH_BASE):
45
+ return None
46
+ os.chmod(SCRATCH_BASE, 0o700)
47
+ root = Path(project_root).resolve()
48
+ digest = hashlib.sha256(str(root).encode("utf-8")).hexdigest()[:8]
49
+ folder = SCRATCH_BASE / f"{root.name}-{digest}"
50
+ folder.mkdir(mode=0o700, exist_ok=True)
51
+ name = f"{datetime.now():%Y%m%d-%H%M%S}-{secrets.token_hex(3)}"
52
+ else:
53
+ folder = Path(parent)
54
+ name = f"{label}-{secrets.token_hex(3)}"
55
+ path = folder / name
56
+ path.mkdir(mode=0o700)
57
+ return path
58
+ except OSError:
59
+ return None
60
+
61
+
5
62
  class ProjectContext:
6
63
  """Handles path validation and translation between relative and absolute paths.
7
64
 
@@ -9,17 +66,21 @@ class ProjectContext:
9
66
  macOS ~ paths.
10
67
  """
11
68
 
12
- def __init__(self, root_dir: str = "."):
69
+ def __init__(self, root_dir: str = ".", scratch_dir: Path | str | None = None):
13
70
  """Initialize ProjectContext with a root directory.
14
71
 
15
72
  Args:
16
73
  root_dir: Root directory path (defaults to current directory)
74
+ scratch_dir: The session scratch directory, a second root the file
75
+ tools may use (see ``new_scratch_dir``); None allows only the root.
17
76
  """
18
77
  expanded_root = os.path.expanduser(root_dir)
19
78
  self.root = Path(expanded_root).resolve()
79
+ self.scratch_dir = Path(scratch_dir).resolve() if scratch_dir is not None else None
20
80
 
21
81
  def validate_path(self, file_path: str) -> Path:
22
- """Validate and resolve a file path, ensuring it stays within the project root.
82
+ """Validate and resolve a file path, ensuring it stays within the project root
83
+ or the session scratch directory.
23
84
 
24
85
  Args:
25
86
  file_path: Path to validate (relative or absolute)
@@ -37,7 +98,8 @@ class ProjectContext:
37
98
  else:
38
99
  target_path = (self.root / clean_path).resolve()
39
100
 
40
- if not target_path.is_relative_to(self.root):
101
+ in_scratch = self.scratch_dir is not None and target_path.is_relative_to(self.scratch_dir)
102
+ if not target_path.is_relative_to(self.root) and not in_scratch:
41
103
  raise ValueError(
42
104
  f"Security Alert: Path '{target_path}' is outside project root '{self.root}'"
43
105
  )
@@ -365,7 +365,8 @@ def render_skill_block(info: SkillInfo) -> str | ToolError:
365
365
  _, body = parse_frontmatter(text)
366
366
  lines = [
367
367
  f"{LOADED_MARKER}{info.name}",
368
- f"Source: {info.layer} ({info.path.parent})",
368
+ # Layer only: models took the skill's absolute path for the project root.
369
+ f"Source: {info.layer}",
369
370
  ]
370
371
  resources = skill_resources(info)
371
372
  if resources:
@@ -4,6 +4,9 @@ Each prompt template is labeled with a comment indicating which module/function
4
4
  is responsible for using it, along with the REASON for prompting the LLM.
5
5
  """
6
6
 
7
+ from datetime import datetime
8
+ from pathlib import Path
9
+
7
10
  # =============================================================================
8
11
  # CORE SYSTEM PROMPT
9
12
  # =============================================================================
@@ -34,6 +37,55 @@ MINIMAL_SYSTEM_PROMPT = """You are a developer and coding assistant. Analyze und
34
37
 
35
38
  EXTENDED_SYSTEM_PROMPT = STANDARD_SYSTEM_PROMPT
36
39
 
40
+ # =============================================================================
41
+ # SESSION ENVIRONMENT SECTION
42
+ # =============================================================================
43
+ # Used by: runtime_factory.create_runtime() / create_agent_runtime(), after the
44
+ # base prompt and before the tool prompts, for every tier and override.
45
+ # REASON: Without the project's absolute path a model guessed one (the home
46
+ # directory, from a skill header) and ran `git init` there. Built once per
47
+ # session so the frozen prompt and its cache prefix never change.
48
+
49
+ ENVIRONMENT_PROMPT = """
50
+
51
+ ## Environment
52
+ Working directory: {working_directory}
53
+ Session start: {started_at}{scratch_line}
54
+
55
+ Your workspace is {workspace}.
56
+ Outside it, read only paths the user names or the task requires, and create,
57
+ modify or initialize nothing (including `git init`) without the user's consent.{scratch_rule}
58
+ """
59
+
60
+ # REASON: Models put temporary files in /tmp by habit. A per-session directory
61
+ # there (core/context.py:new_scratch_dir) gives them a sanctioned place, and
62
+ # the file tools accept it. Omitted when the directory could not be created.
63
+ SCRATCH_LINE = "\nScratch directory: {scratch_dir}"
64
+
65
+ SCRATCH_RULE = "\nPut temporary files in the scratch directory, not in /tmp or ~/tmp."
66
+
67
+
68
+ def build_environment_prompt(
69
+ working_directory: Path, started_at: datetime, scratch_dir: Path | None = None
70
+ ) -> str:
71
+ """Render the session environment section for the system prompt.
72
+
73
+ ``started_at`` should be timezone-aware local time; it renders as ISO 8601
74
+ to the minute with its UTC offset (e.g. 2026-10-19T03:33+03:00).
75
+ ``scratch_dir`` adds the scratch directory line and its rule.
76
+ """
77
+ return ENVIRONMENT_PROMPT.format(
78
+ working_directory=working_directory,
79
+ started_at=started_at.isoformat(timespec="minutes"),
80
+ workspace=(
81
+ "the working directory and the scratch directory"
82
+ if scratch_dir
83
+ else "the working directory"
84
+ ),
85
+ scratch_line=SCRATCH_LINE.format(scratch_dir=scratch_dir) if scratch_dir else "",
86
+ scratch_rule=SCRATCH_RULE if scratch_dir else "",
87
+ )
88
+
37
89
  # =============================================================================
38
90
  # AGENTIC ORCHESTRATOR SYSTEM PROMPT
39
91
  # =============================================================================
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: development-workflow
3
+ description: Multi-step software work - a new feature, a refactor, a bug whose cause is unknown, a change across several files. Not for small, obvious edits, quick fixes or questions that need no change.
4
+ ---
5
+
6
+ # Development workflow
7
+
8
+ 1. Orient: read `AGENTS.md` and `README.md` if they exist, then the code the task touches.
9
+ 2. Plan: write the plan with `note(action="create", note_id="plan-<slug>")`: the steps,
10
+ the files each step touches, and how each step is verified. Create one task per step,
11
+ in dependency order, with `task(action="create", title=..., body=..., dependencies=...)`.
12
+ Change no project files before the plan is approved.
13
+ 3. Approve: show the user the steps and their verification, name the plan note, and end
14
+ your turn until the user approves. When the user asks for a reviewer agent, it
15
+ approves instead: find it with `agent(action="list")`, send it the plan with
16
+ `agent(action="call", name=..., task=...)`, and collect the verdict with
17
+ `agent(action="read_result", run_id=..., wait=true)`. On requested changes, update
18
+ the note and the tasks and ask again.
19
+ 4. Execute: work through the tasks in order. Set each one `in_progress` with
20
+ `task(action="update_status", identifier=..., status="in_progress")` when you start
21
+ it, `done` when its verification passes, or `blocked` when you need the user, and
22
+ tell the user why. A large, parallelizable or specialized task can go to an agent with
23
+ `agent(action="call", task_id=...)`.
24
+ 5. Report: one short line at plan created, task started, task done and final delivery.
25
+ The final delivery says what changed and how it was verified.
26
+ 6. Finish: ask before committing, unless the user gave commit instructions. Then unload
27
+ this skill with `skill(action="unload", name="development-workflow")`.
@@ -115,21 +115,21 @@ TOOL_DEFINITIONS: Tuple[ToolDefinition, ...] = (
115
115
  "content": {
116
116
  "type": "string",
117
117
  "description": (
118
- "Content for 'write' (the complete file) or 'insert' (the line). "
118
+ "Required for 'write' (the complete file) and 'insert' (the line). "
119
119
  "Accepted up to 10MB."
120
120
  ),
121
121
  },
122
122
  "old_string": {
123
123
  "type": "string",
124
- "description": "Exact string to find for 'replace' operation",
124
+ "description": "Required for 'replace'. Exact string to find.",
125
125
  },
126
126
  "new_string": {
127
127
  "type": "string",
128
- "description": "New string to substitute for 'replace' operation",
128
+ "description": "Required for 'replace'. New string to substitute.",
129
129
  },
130
130
  "line_number": {
131
131
  "type": "integer",
132
- "description": "Line number (1-based) for 'insert' or 'delete' operations",
132
+ "description": "Required for 'insert' and 'delete'. Line number (1-based).",
133
133
  },
134
134
  "replace_all": {
135
135
  "type": "boolean",
@@ -13,7 +13,8 @@ TOOL_DEFINITIONS: Tuple[ToolDefinition, ...] = (
13
13
  name="bash",
14
14
  description=(
15
15
  "Run a shell command and return its exit code, stdout, and stderr. "
16
- "Use for builds, tests, git, file inspection, and other terminal tasks."
16
+ "Use for builds, tests, git, file inspection, and other terminal tasks. "
17
+ "Each call starts in the working directory; a `cd` does not carry over."
17
18
  ),
18
19
  description_template="Command `{command}` will be executed",
19
20
  tags=("core",),
@@ -18,7 +18,8 @@ TOOL_DEFINITIONS: Tuple[ToolDefinition, ...] = (
18
18
  name="task",
19
19
  description=(
20
20
  "Manage .ayder/tasks/ task files. Single tool, dispatched on "
21
- "`action`: create | list | show | status | update_status | update. "
21
+ "`action`: create | list | show | status | update_status | update | "
22
+ "update_dependencies. "
22
23
  "Output is bounded plain text (use offset/limit/max_chars/section to "
23
24
  "page); prefer this over file_editor for all task operations."
24
25
  ),
@@ -39,12 +40,14 @@ TOOL_DEFINITIONS: Tuple[ToolDefinition, ...] = (
39
40
  "status",
40
41
  "update_status",
41
42
  "update",
43
+ "update_dependencies",
42
44
  ],
43
45
  "description": (
44
46
  "Operation to perform. create: new task. list: paged "
45
47
  "rows. show: bounded body/section. status: current "
46
48
  "status. update_status: change status. update: replace "
47
- "one PRD section."
49
+ "one PRD section. update_dependencies: replace the "
50
+ "dependency list."
48
51
  ),
49
52
  },
50
53
  "title": {
@@ -63,8 +66,11 @@ TOOL_DEFINITIONS: Tuple[ToolDefinition, ...] = (
63
66
  "dependencies": {
64
67
  "type": "string",
65
68
  "description": (
66
- "[create] Comma-separated task IDs this depends on, e.g. "
67
- "'TASK-003,TASK-004' or '3,4'."
69
+ "[create/update_dependencies] Comma-separated IDs of "
70
+ "existing tasks this one depends on, e.g. 'TASK-003,TASK-004' "
71
+ "or '3,4'. A task cannot depend on itself, on a task not yet "
72
+ "created, or close a cycle. [update_dependencies] Empty "
73
+ "clears the list."
68
74
  ),
69
75
  },
70
76
  "branch": {
@@ -85,7 +91,8 @@ TOOL_DEFINITIONS: Tuple[ToolDefinition, ...] = (
85
91
  "identifier": {
86
92
  "type": "string",
87
93
  "description": (
88
- "[show/status/update_status/update] Task identifier: ID "
94
+ "[show/status/update_status/update/update_dependencies] Task "
95
+ "identifier: ID "
89
96
  "('7', '007', 'TASK-007'), filename, path, or slug."
90
97
  ),
91
98
  },