agex-cli 0.26.0__tar.gz → 0.27.0__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 (278) hide show
  1. agex_cli-0.27.0/.devague/frames/every-devex-command-now-closes-with-a-deterministi.json +208 -0
  2. agex_cli-0.27.0/.devague/plans/every-devex-command-now-closes-with-a-deterministi.json +307 -0
  3. {agex_cli-0.26.0 → agex_cli-0.27.0}/.github/workflows/test.yml +41 -0
  4. {agex_cli-0.26.0 → agex_cli-0.27.0}/.gitignore +9 -0
  5. {agex_cli-0.26.0 → agex_cli-0.27.0}/CHANGELOG.md +29 -0
  6. {agex_cli-0.26.0 → agex_cli-0.27.0}/CLAUDE.md +8 -4
  7. {agex_cli-0.26.0 → agex_cli-0.27.0}/PKG-INFO +1 -1
  8. agex_cli-0.27.0/docs/plans/2026-05-29-every-devex-command-now-closes-with-a-deterministi.md +92 -0
  9. agex_cli-0.27.0/docs/specs/2026-05-29-every-devex-command-now-closes-with-a-deterministi.md +56 -0
  10. {agex_cli-0.26.0 → agex_cli-0.27.0}/pyproject.toml +16 -1
  11. {agex_cli-0.26.0 → agex_cli-0.27.0}/sonar-project.properties +6 -7
  12. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/cli.py +32 -2
  13. agex_cli-0.27.0/src/devex/commands/doctor/assets/backends/acp.yaml +3 -0
  14. agex_cli-0.27.0/src/devex/commands/doctor/assets/backends/claude-code.yaml +3 -0
  15. agex_cli-0.27.0/src/devex/commands/doctor/assets/backends/codex.yaml +3 -0
  16. agex_cli-0.27.0/src/devex/commands/doctor/assets/backends/copilot.yaml +3 -0
  17. agex_cli-0.27.0/src/devex/commands/doctor/scripts/_footer.py +22 -0
  18. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/doctor/scripts/doctor.py +27 -1
  19. agex_cli-0.27.0/src/devex/commands/doctor/scripts/next_step.py +33 -0
  20. agex_cli-0.27.0/src/devex/commands/explain/assets/backends/acp.yaml +4 -0
  21. agex_cli-0.27.0/src/devex/commands/explain/assets/backends/claude-code.yaml +4 -0
  22. agex_cli-0.27.0/src/devex/commands/explain/assets/backends/codex.yaml +4 -0
  23. agex_cli-0.27.0/src/devex/commands/explain/assets/backends/copilot.yaml +4 -0
  24. agex_cli-0.27.0/src/devex/commands/explain/scripts/_footer.py +22 -0
  25. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/explain/scripts/explain.py +33 -5
  26. agex_cli-0.27.0/src/devex/commands/explain/scripts/next_step.py +46 -0
  27. agex_cli-0.27.0/src/devex/commands/gamify/assets/backends/acp.yaml +5 -0
  28. agex_cli-0.27.0/src/devex/commands/gamify/assets/backends/claude-code.yaml +5 -0
  29. agex_cli-0.27.0/src/devex/commands/gamify/assets/backends/codex.yaml +5 -0
  30. agex_cli-0.27.0/src/devex/commands/gamify/assets/backends/copilot.yaml +5 -0
  31. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/gamify/scripts/install.py +32 -13
  32. agex_cli-0.27.0/src/devex/commands/gamify/scripts/next_step.py +32 -0
  33. agex_cli-0.27.0/src/devex/commands/hook/assets/backends/acp.yaml +3 -0
  34. agex_cli-0.27.0/src/devex/commands/hook/assets/backends/claude-code.yaml +3 -0
  35. agex_cli-0.27.0/src/devex/commands/hook/assets/backends/codex.yaml +3 -0
  36. agex_cli-0.27.0/src/devex/commands/hook/assets/backends/copilot.yaml +3 -0
  37. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/hook/assets/table.md.j2 +2 -0
  38. agex_cli-0.27.0/src/devex/commands/hook/scripts/_footer.py +22 -0
  39. agex_cli-0.27.0/src/devex/commands/hook/scripts/next_step.py +20 -0
  40. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/hook/scripts/read.py +9 -1
  41. agex_cli-0.27.0/src/devex/commands/learn/assets/backends/acp.yaml +3 -0
  42. agex_cli-0.27.0/src/devex/commands/learn/assets/backends/claude-code.yaml +3 -0
  43. agex_cli-0.27.0/src/devex/commands/learn/assets/backends/codex.yaml +3 -0
  44. agex_cli-0.27.0/src/devex/commands/learn/assets/backends/copilot.yaml +3 -0
  45. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/learn/assets/menu.md.j2 +1 -0
  46. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/learn/assets/topics/cicd/SKILL.md +2 -0
  47. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/learn/assets/topics/gamify/SKILL.md +2 -0
  48. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/learn/assets/topics/introspect/SKILL.md +2 -0
  49. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/learn/assets/topics/levelup/SKILL.md +2 -0
  50. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/learn/assets/topics/visualize/SKILL.md +2 -0
  51. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/learn/scripts/learn.py +18 -2
  52. agex_cli-0.27.0/src/devex/commands/learn/scripts/next_step.py +21 -0
  53. agex_cli-0.27.0/src/devex/commands/overview/assets/backends/acp.yaml +9 -0
  54. agex_cli-0.27.0/src/devex/commands/overview/assets/backends/claude-code.yaml +9 -0
  55. agex_cli-0.27.0/src/devex/commands/overview/assets/backends/codex.yaml +9 -0
  56. agex_cli-0.27.0/src/devex/commands/overview/assets/backends/copilot.yaml +9 -0
  57. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/overview/assets/sections.md.j2 +2 -0
  58. agex_cli-0.27.0/src/devex/commands/overview/scripts/_footer.py +22 -0
  59. agex_cli-0.27.0/src/devex/commands/overview/scripts/next_step.py +20 -0
  60. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/overview/scripts/overview.py +11 -1
  61. agex_cli-0.27.0/src/devex/commands/pr/scripts/_footer.py +22 -0
  62. agex_cli-0.27.0/src/devex/core/assets/__init__.py +0 -0
  63. agex_cli-0.27.0/src/devex/core/assets/backends/__init__.py +1 -0
  64. agex_cli-0.27.0/src/devex/core/assets/backends/neutral.yaml +37 -0
  65. agex_cli-0.27.0/src/devex/core/footer.py +97 -0
  66. agex_cli-0.27.0/tests/__init__.py +0 -0
  67. agex_cli-0.27.0/tests/backends/__init__.py +0 -0
  68. agex_cli-0.27.0/tests/commands/__init__.py +0 -0
  69. agex_cli-0.27.0/tests/commands/pr/__init__.py +0 -0
  70. agex_cli-0.27.0/tests/commands/pr/fixtures/gh/.gitkeep +0 -0
  71. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/test_doctor.py +96 -0
  72. agex_cli-0.27.0/tests/commands/test_explain.py +124 -0
  73. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/test_gamify.py +74 -0
  74. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/test_hook.py +74 -0
  75. agex_cli-0.27.0/tests/commands/test_learn.py +113 -0
  76. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/test_overview.py +46 -0
  77. agex_cli-0.27.0/tests/core/__init__.py +0 -0
  78. agex_cli-0.27.0/tests/core/test_footer.py +74 -0
  79. agex_cli-0.27.0/tests/fixtures/claude-code/empty/.gitkeep +0 -0
  80. agex_cli-0.27.0/tests/test_footer_guarantee.py +608 -0
  81. agex_cli-0.27.0/tests/test_footer_hints.py +324 -0
  82. {agex_cli-0.26.0 → agex_cli-0.27.0}/uv.lock +1 -1
  83. agex_cli-0.26.0/src/devex/commands/overview/assets/backends/acp.yaml +0 -7
  84. agex_cli-0.26.0/src/devex/commands/overview/assets/backends/claude-code.yaml +0 -7
  85. agex_cli-0.26.0/src/devex/commands/overview/assets/backends/codex.yaml +0 -7
  86. agex_cli-0.26.0/src/devex/commands/overview/assets/backends/copilot.yaml +0 -7
  87. agex_cli-0.26.0/src/devex/commands/pr/scripts/_footer.py +0 -32
  88. agex_cli-0.26.0/tests/commands/test_explain.py +0 -31
  89. agex_cli-0.26.0/tests/commands/test_learn.py +0 -55
  90. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/agent-config/SKILL.md +0 -0
  91. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/agent-config/data/backend-fingerprints.yaml +0 -0
  92. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/agent-config/scripts/show.sh +0 -0
  93. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/assign-to-workforce/SKILL.md +0 -0
  94. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
  95. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/cicd/SKILL.md +0 -0
  96. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/cicd/scripts/workflow.sh +0 -0
  97. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/communicate/SKILL.md +0 -0
  98. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
  99. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
  100. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
  101. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
  102. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
  103. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
  104. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
  105. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
  106. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/run-tests/SKILL.md +0 -0
  107. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
  108. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/sonarclaude/SKILL.md +0 -0
  109. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
  110. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/spec-to-plan/SKILL.md +0 -0
  111. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
  112. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/think/SKILL.md +0 -0
  113. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/think/scripts/think.sh +0 -0
  114. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/version-bump/SKILL.md +0 -0
  115. {agex_cli-0.26.0 → agex_cli-0.27.0}/.claude/skills/version-bump/scripts/bump.py +0 -0
  116. {agex_cli-0.26.0 → agex_cli-0.27.0}/.flake8 +0 -0
  117. {agex_cli-0.26.0 → agex_cli-0.27.0}/.github/workflows/publish.yml +0 -0
  118. {agex_cli-0.26.0 → agex_cli-0.27.0}/.python-version +0 -0
  119. {agex_cli-0.26.0 → agex_cli-0.27.0}/LICENSE +0 -0
  120. {agex_cli-0.26.0 → agex_cli-0.27.0}/README.md +0 -0
  121. {agex_cli-0.26.0 → agex_cli-0.27.0}/culture.yaml +0 -0
  122. {agex_cli-0.26.0 → agex_cli-0.27.0}/docs/skill-sources.md +0 -0
  123. {agex_cli-0.26.0 → agex_cli-0.27.0}/docs/superpowers/plans/2026-04-18-agex-v0.1.md +0 -0
  124. {agex_cli-0.26.0 → agex_cli-0.27.0}/docs/superpowers/plans/2026-05-10-agex-pr.md +0 -0
  125. {agex_cli-0.26.0 → agex_cli-0.27.0}/docs/superpowers/specs/2026-04-18-agex-design.md +0 -0
  126. {agex_cli-0.26.0 → agex_cli-0.27.0}/docs/superpowers/specs/2026-04-26-agex-doctor.md +0 -0
  127. {agex_cli-0.26.0 → agex_cli-0.27.0}/docs/superpowers/specs/2026-05-10-agex-pr-design.md +0 -0
  128. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/__init__.py +0 -0
  129. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/__main__.py +0 -0
  130. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/backends/__init__.py +0 -0
  131. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/backends/acp/__init__.py +0 -0
  132. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/backends/acp/probe.py +0 -0
  133. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/backends/capabilities/acp.yaml +0 -0
  134. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/backends/capabilities/claude-code.yaml +0 -0
  135. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/backends/capabilities/codex.yaml +0 -0
  136. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/backends/capabilities/copilot.yaml +0 -0
  137. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/backends/claude_code/__init__.py +0 -0
  138. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/backends/claude_code/probe.py +0 -0
  139. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/backends/codex/__init__.py +0 -0
  140. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/backends/codex/probe.py +0 -0
  141. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/backends/copilot/__init__.py +0 -0
  142. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/backends/copilot/probe.py +0 -0
  143. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/__init__.py +0 -0
  144. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/doctor/SKILL.md +0 -0
  145. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/doctor/__init__.py +0 -0
  146. {agex_cli-0.26.0/src/devex/commands/doctor/scripts → agex_cli-0.27.0/src/devex/commands/doctor/assets/backends}/__init__.py +0 -0
  147. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/doctor/assets/report.md.j2 +0 -0
  148. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/doctor/references/design.md +0 -0
  149. {agex_cli-0.26.0/src/devex/commands/explain → agex_cli-0.27.0/src/devex/commands/doctor/scripts}/__init__.py +0 -0
  150. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/explain/SKILL.md +0 -0
  151. {agex_cli-0.26.0/src/devex/commands/explain/scripts → agex_cli-0.27.0/src/devex/commands/explain}/__init__.py +0 -0
  152. {agex_cli-0.26.0/src/devex/commands/gamify → agex_cli-0.27.0/src/devex/commands/explain/assets/backends}/__init__.py +0 -0
  153. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/explain/assets/topics/devex.md +0 -0
  154. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/explain/references/.gitkeep +0 -0
  155. {agex_cli-0.26.0/src/devex/commands/gamify → agex_cli-0.27.0/src/devex/commands/explain}/scripts/__init__.py +0 -0
  156. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/gamify/SKILL.md +0 -0
  157. {agex_cli-0.26.0/src/devex/commands/hook → agex_cli-0.27.0/src/devex/commands/gamify}/__init__.py +0 -0
  158. {agex_cli-0.26.0/src/devex/commands/hook/scripts → agex_cli-0.27.0/src/devex/commands/gamify/assets/backends}/__init__.py +0 -0
  159. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/gamify/assets/hooks/claude-code.json +0 -0
  160. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/gamify/references/.gitkeep +0 -0
  161. {agex_cli-0.26.0/src/devex/commands/learn → agex_cli-0.27.0/src/devex/commands/gamify/scripts}/__init__.py +0 -0
  162. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/hook/SKILL.md +0 -0
  163. {agex_cli-0.26.0/src/devex/commands/learn/scripts → agex_cli-0.27.0/src/devex/commands/hook}/__init__.py +0 -0
  164. {agex_cli-0.26.0/src/devex/commands/overview → agex_cli-0.27.0/src/devex/commands/hook/assets/backends}/__init__.py +0 -0
  165. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/hook/references/.gitkeep +0 -0
  166. {agex_cli-0.26.0/src/devex/commands/overview → agex_cli-0.27.0/src/devex/commands/hook}/scripts/__init__.py +0 -0
  167. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/hook/scripts/write.py +0 -0
  168. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/learn/SKILL.md +0 -0
  169. {agex_cli-0.26.0/src/devex/commands/pr → agex_cli-0.27.0/src/devex/commands/learn}/__init__.py +0 -0
  170. {agex_cli-0.26.0/src/devex/commands/pr/assets → agex_cli-0.27.0/src/devex/commands/learn/assets/backends}/__init__.py +0 -0
  171. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/learn/assets/topics/gamify/assets/skill-template/claude-code/SKILL.md +0 -0
  172. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/learn/assets/topics/introspect/assets/skill-template/claude-code/SKILL.md +0 -0
  173. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/learn/assets/topics/levelup/assets/skill-template/claude-code/SKILL.md +0 -0
  174. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/learn/assets/topics/visualize/assets/skill-template/claude-code/SKILL.md +0 -0
  175. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/learn/references/.gitkeep +0 -0
  176. {agex_cli-0.26.0/src/devex/commands/pr/assets/backends → agex_cli-0.27.0/src/devex/commands/learn/scripts}/__init__.py +0 -0
  177. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/overview/SKILL.md +0 -0
  178. {agex_cli-0.26.0/src/devex/commands/pr/assets/rules → agex_cli-0.27.0/src/devex/commands/overview}/__init__.py +0 -0
  179. {agex_cli-0.26.0/src/devex/commands/pr/assets/templates → agex_cli-0.27.0/src/devex/commands/overview/assets}/__init__.py +0 -0
  180. {agex_cli-0.26.0/src/devex/commands/pr/scripts → agex_cli-0.27.0/src/devex/commands/overview/assets/backends}/__init__.py +0 -0
  181. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/overview/references/.gitkeep +0 -0
  182. {agex_cli-0.26.0/src/devex/core → agex_cli-0.27.0/src/devex/commands/overview/scripts}/__init__.py +0 -0
  183. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/SKILL.md +0 -0
  184. {agex_cli-0.26.0/tests → agex_cli-0.27.0/src/devex/commands/pr}/__init__.py +0 -0
  185. {agex_cli-0.26.0/tests/backends → agex_cli-0.27.0/src/devex/commands/pr/assets}/__init__.py +0 -0
  186. {agex_cli-0.26.0/tests/commands → agex_cli-0.27.0/src/devex/commands/pr/assets/backends}/__init__.py +0 -0
  187. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/assets/backends/acp.yaml +0 -0
  188. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/assets/backends/claude-code.yaml +0 -0
  189. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/assets/backends/codex.yaml +0 -0
  190. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/assets/backends/copilot.yaml +0 -0
  191. {agex_cli-0.26.0/tests/commands/pr → agex_cli-0.27.0/src/devex/commands/pr/assets/rules}/__init__.py +0 -0
  192. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/assets/rules/lint_rules.py +0 -0
  193. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/assets/rules/next_step_rules.py +0 -0
  194. {agex_cli-0.26.0/tests/core → agex_cli-0.27.0/src/devex/commands/pr/assets/templates}/__init__.py +0 -0
  195. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/assets/templates/delta.md.j2 +0 -0
  196. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/assets/templates/lint_result.md.j2 +0 -0
  197. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/assets/templates/pr_await_detached.md.j2 +0 -0
  198. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/assets/templates/pr_briefing.md.j2 +0 -0
  199. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/assets/templates/pr_open_result.md.j2 +0 -0
  200. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/assets/templates/pr_reply_result.md.j2 +0 -0
  201. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/assets/templates/pr_review_result.md.j2 +0 -0
  202. /agex_cli-0.26.0/tests/commands/pr/fixtures/gh/.gitkeep → /agex_cli-0.27.0/src/devex/commands/pr/scripts/__init__.py +0 -0
  203. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/_await_worker.py +0 -0
  204. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/_deploy.py +0 -0
  205. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/_detach.py +0 -0
  206. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/_journal.py +0 -0
  207. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/_qodo.py +0 -0
  208. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/_readiness.py +0 -0
  209. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/_sonar.py +0 -0
  210. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/await_.py +0 -0
  211. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/delta.py +0 -0
  212. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/lint.py +0 -0
  213. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/open_.py +0 -0
  214. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/read.py +0 -0
  215. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/reply.py +0 -0
  216. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/commands/pr/scripts/review.py +0 -0
  217. /agex_cli-0.26.0/tests/fixtures/claude-code/empty/.gitkeep → /agex_cli-0.27.0/src/devex/core/__init__.py +0 -0
  218. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/core/_jsonl.py +0 -0
  219. {agex_cli-0.26.0/src/devex/commands/pr/assets/templates → agex_cli-0.27.0/src/devex/core/assets}/footer.md.j2 +0 -0
  220. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/core/backend.py +0 -0
  221. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/core/capabilities.py +0 -0
  222. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/core/config.py +0 -0
  223. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/core/github.py +0 -0
  224. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/core/hook_io.py +0 -0
  225. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/core/journal.py +0 -0
  226. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/core/paths.py +0 -0
  227. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/core/prog.py +0 -0
  228. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/core/render.py +0 -0
  229. {agex_cli-0.26.0 → agex_cli-0.27.0}/src/devex/core/skill_loader.py +0 -0
  230. {agex_cli-0.26.0 → agex_cli-0.27.0}/tester-agents/claude/.claude/settings.json +0 -0
  231. {agex_cli-0.26.0 → agex_cli-0.27.0}/tester-agents/claude/.claude/skills +0 -0
  232. {agex_cli-0.26.0 → agex_cli-0.27.0}/tester-agents/claude/CLAUDE.md +0 -0
  233. {agex_cli-0.26.0 → agex_cli-0.27.0}/tester-agents/claude/README.md +0 -0
  234. {agex_cli-0.26.0 → agex_cli-0.27.0}/tester-agents/claude/culture.yaml +0 -0
  235. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/backends/test_claude_code_probe.py +0 -0
  236. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/backends/test_stub_probes.py +0 -0
  237. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/fixtures/gh/pr_checks_42.json +0 -0
  238. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/fixtures/gh/pr_comments_42.json +0 -0
  239. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/fixtures/gh/qodo_summary_comment.html +0 -0
  240. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/fixtures/journals/dogfood_40.jsonl +0 -0
  241. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/test_await.py +0 -0
  242. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/test_await_detach.py +0 -0
  243. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/test_delta.py +0 -0
  244. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/test_deploy.py +0 -0
  245. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/test_footer.py +0 -0
  246. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/test_lint.py +0 -0
  247. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/test_lint_rules.py +0 -0
  248. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/test_open.py +0 -0
  249. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/test_qodo.py +0 -0
  250. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/test_read.py +0 -0
  251. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/test_readiness.py +0 -0
  252. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/test_reply.py +0 -0
  253. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/pr/test_review.py +0 -0
  254. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/commands/test_prog_propagation.py +0 -0
  255. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/core/test_backend.py +0 -0
  256. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/core/test_capabilities.py +0 -0
  257. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/core/test_config.py +0 -0
  258. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/core/test_github.py +0 -0
  259. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/core/test_hook_io.py +0 -0
  260. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/core/test_journal.py +0 -0
  261. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/core/test_paths.py +0 -0
  262. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/core/test_prog.py +0 -0
  263. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/core/test_render.py +0 -0
  264. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/core/test_resolve_backend.py +0 -0
  265. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/core/test_skill_loader.py +0 -0
  266. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/core/test_version_lookup.py +0 -0
  267. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/fixtures/claude-code/malformed/.claude/hooks.json +0 -0
  268. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/fixtures/claude-code/malformed/.claude/settings.json +0 -0
  269. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/fixtures/claude-code/malformed/.claude/skills/bad/SKILL.md +0 -0
  270. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/fixtures/claude-code/malformed/.claude/skills/broken-yaml/SKILL.md +0 -0
  271. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/fixtures/claude-code/typical/.claude/hooks.json +0 -0
  272. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/fixtures/claude-code/typical/.claude/settings.json +0 -0
  273. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/fixtures/claude-code/typical/.claude/skills/example/SKILL.md +0 -0
  274. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/fixtures/claude-code/typical/CLAUDE.md +0 -0
  275. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/test_cli_dispatch.py +0 -0
  276. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/test_cli_errors.py +0 -0
  277. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/test_cli_smoke.py +0 -0
  278. {agex_cli-0.26.0 → agex_cli-0.27.0}/tests/test_skill_md_consistency.py +0 -0
@@ -0,0 +1,208 @@
1
+ {
2
+ "slug": "every-devex-command-now-closes-with-a-deterministi",
3
+ "title": "Every devex command now closes with a deterministic, per-backend Next step micro-prompt telling the running agent exactly how to continue \u2014 the pr namespace footer convention becomes a cross-command guarantee.",
4
+ "schema_version": 1,
5
+ "status": "exported",
6
+ "created": "2026-05-29T14:19:33Z",
7
+ "updated": "2026-05-29T15:05:05Z",
8
+ "claims": [
9
+ {
10
+ "id": "c1",
11
+ "kind": "announcement",
12
+ "text": "Every devex command now closes with a deterministic, per-backend Next step micro-prompt telling the running agent exactly how to continue \u2014 the pr namespace footer convention becomes a cross-command guarantee.",
13
+ "origin": "user",
14
+ "status": "confirmed",
15
+ "honesty_conditions": [
16
+ {
17
+ "id": "h4",
18
+ "text": "Every command path that reaches stdout terminates in exactly one Next step footer block \u2014 the guarantee is total, not best-effort \u2014 verified by a test that runs every non-silent command and asserts a trailing footer.",
19
+ "status": "confirmed"
20
+ }
21
+ ],
22
+ "hard_questions": [],
23
+ "links": []
24
+ },
25
+ {
26
+ "id": "c2",
27
+ "kind": "audience",
28
+ "text": "Autonomous coding agents (claude-code, codex, copilot, acp backends) that invoke devex commands non-interactively and must pick their next move without an LLM in the loop.",
29
+ "origin": "llm",
30
+ "status": "confirmed",
31
+ "honesty_conditions": [
32
+ {
33
+ "id": "h6",
34
+ "text": "Every footer hint is phrased as an actionable instruction to the running agent (an imperative naming a concrete next command/move), never human-facing prose \u2014 asserted by a test/lint on hint form.",
35
+ "status": "confirmed"
36
+ }
37
+ ],
38
+ "hard_questions": [],
39
+ "links": []
40
+ },
41
+ {
42
+ "id": "c3",
43
+ "kind": "after_state",
44
+ "text": "Every non-silent devex command (explain, learn, overview, doctor, gamify, hook read, plus the existing pr namespace) ends its markdown with a Next step footer naming a concrete next move, so the agent never has to infer what to run next.",
45
+ "origin": "llm",
46
+ "status": "confirmed",
47
+ "honesty_conditions": [
48
+ {
49
+ "id": "h3",
50
+ "text": "For each non-silent command there is a deterministic mapping from its observable end-state to exactly one rule_key, so the footer is reproducible across identical inputs.",
51
+ "status": "confirmed"
52
+ }
53
+ ],
54
+ "hard_questions": [],
55
+ "links": []
56
+ },
57
+ {
58
+ "id": "c4",
59
+ "kind": "before_state",
60
+ "text": "Today only the pr namespace ends with a Next step footer. explain, learn, overview, doctor and hook read end at EOF; gamify install has a one-off ad-hoc Next line. After every other command the agent must guess the next move.",
61
+ "origin": "llm",
62
+ "status": "confirmed",
63
+ "honesty_conditions": [
64
+ {
65
+ "id": "h7",
66
+ "text": "A snapshot test of current non-pr command output confirms none emits a Next step footer today, so the gap this feature closes is demonstrated, not assumed.",
67
+ "status": "confirmed"
68
+ }
69
+ ],
70
+ "hard_questions": [],
71
+ "links": []
72
+ },
73
+ {
74
+ "id": "c5",
75
+ "kind": "why_it_matters",
76
+ "text": "devex exists to give autonomous agents deterministic guidance. A command that ends without a next-move prompt leaves a decision gap the agent fills by guessing \u2014 non-deterministic behaviour in a tool whose whole premise is determinism. A closing micro-prompt makes the command surface self-chaining.",
77
+ "origin": "llm",
78
+ "status": "confirmed",
79
+ "honesty_conditions": [
80
+ {
81
+ "id": "h8",
82
+ "text": "The footer is fully determined by command inputs plus project state with zero LLM/network/random input \u2014 identical inputs always yield an identical footer, asserted by a reproducibility test.",
83
+ "status": "confirmed"
84
+ }
85
+ ],
86
+ "hard_questions": [],
87
+ "links": []
88
+ },
89
+ {
90
+ "id": "c6",
91
+ "kind": "boundary",
92
+ "text": "Out of scope: rewriting command body content; LLM-generated footers; adding a footer to deliberately-silent commands such as hook write which emits empty stdout; and auto-executing the suggested command \u2014 the footer is a prompt, not an action, so no new side effects are introduced.",
93
+ "origin": "llm",
94
+ "status": "confirmed",
95
+ "honesty_conditions": [
96
+ {
97
+ "id": "h9",
98
+ "text": "After the change hook write still emits empty stdout and no command gains a new network/file-write/sleep side effect from the footer \u2014 verified by the existing side-effect/invariant tests staying green.",
99
+ "status": "confirmed"
100
+ }
101
+ ],
102
+ "hard_questions": [],
103
+ "links": []
104
+ },
105
+ {
106
+ "id": "c7",
107
+ "kind": "success_signal",
108
+ "text": "A test asserts every non-silent command stdout ends with the footer block, and that each backend YAML defines a hint for every rule key its command can emit, so there is no missing-hint KeyError at runtime.",
109
+ "origin": "llm",
110
+ "status": "confirmed",
111
+ "honesty_conditions": [
112
+ {
113
+ "id": "h10",
114
+ "text": "Both guard tests (every-command-ends-with-a-footer; every reachable rule_key has a hint) exist, run in CI, and fail loudly when a command or rule_key is added without a hint.",
115
+ "status": "confirmed"
116
+ }
117
+ ],
118
+ "hard_questions": [],
119
+ "links": []
120
+ },
121
+ {
122
+ "id": "c8",
123
+ "kind": "requirement",
124
+ "text": "The footer-rendering machinery now under commands/pr (the _footer renderer, the rule_key plus context decision pattern, and footer.md.j2) is promoted to core so every command shares one implementation.",
125
+ "origin": "llm",
126
+ "status": "confirmed",
127
+ "honesty_conditions": [
128
+ {
129
+ "id": "h1",
130
+ "text": "After the machinery moves to core, the pr namespace footers are byte-identical and every existing pr footer test passes unchanged (pure relocation, no behaviour change).",
131
+ "status": "confirmed"
132
+ }
133
+ ],
134
+ "hard_questions": [],
135
+ "links": []
136
+ },
137
+ {
138
+ "id": "c9",
139
+ "kind": "requirement",
140
+ "text": "Each non-pr command gains a small next-step decision function returning rule_key plus context, and a hints block in its per-command assets/backends/backend.yaml, mirroring how the pr namespace is structured.",
141
+ "origin": "llm",
142
+ "status": "confirmed",
143
+ "honesty_conditions": [
144
+ {
145
+ "id": "h2",
146
+ "text": "One enumerating test walks every (command, backend, reachable rule_key) triple and fails if any hint string is missing, proving coverage rather than assuming it.",
147
+ "status": "confirmed"
148
+ }
149
+ ],
150
+ "hard_questions": [],
151
+ "links": []
152
+ },
153
+ {
154
+ "id": "c10",
155
+ "kind": "requirement",
156
+ "text": "Backend-agnostic commands that do not take --agent today (explain, doctor) must still end with a coherent Next step footer.",
157
+ "origin": "llm",
158
+ "status": "confirmed",
159
+ "honesty_conditions": [
160
+ {
161
+ "id": "h5",
162
+ "text": "With --agent provided, explain/doctor render that backend's hint; with it omitted they render a neutral hint from a shared default; both paths are test-covered so the optional flag never yields a missing or empty footer.",
163
+ "status": "confirmed"
164
+ }
165
+ ],
166
+ "hard_questions": [
167
+ {
168
+ "id": "q1",
169
+ "text": "How do explain and doctor (no --agent flag today) emit a per-backend Next step footer? (a) add optional --agent, neutral footer when omitted; (b) stay agnostic, emit one neutral footer with no per-backend phrasing; (c) make --agent required on them too, breaking their agnostic contract.",
170
+ "resolved": false,
171
+ "blocking": false
172
+ }
173
+ ],
174
+ "links": []
175
+ },
176
+ {
177
+ "id": "c11",
178
+ "kind": "decision",
179
+ "text": "Reuse the existing mechanism unchanged \u2014 rule_key plus context resolved against a per-backend hints YAML and rendered through footer.md.j2 as a Next step block under a horizontal rule \u2014 rather than inventing a new footer format.",
180
+ "origin": "llm",
181
+ "status": "confirmed",
182
+ "honesty_conditions": [],
183
+ "hard_questions": [],
184
+ "links": []
185
+ },
186
+ {
187
+ "id": "c12",
188
+ "kind": "non_goal",
189
+ "text": "This is not a generalized workflow or command-graph engine; the footer suggests a single sensible next move, it does not model, validate or enforce a sequence of commands.",
190
+ "origin": "llm",
191
+ "status": "confirmed",
192
+ "honesty_conditions": [],
193
+ "hard_questions": [],
194
+ "links": []
195
+ },
196
+ {
197
+ "id": "c13",
198
+ "kind": "decision",
199
+ "text": "explain and doctor gain an OPTIONAL --agent flag: when provided the footer uses that backend's hints YAML, when omitted a backend-neutral footer is emitted from a shared default. Existing flagless calls keep working unchanged (non-breaking). [resolves q1, user choice]",
200
+ "origin": "user",
201
+ "status": "confirmed",
202
+ "honesty_conditions": [],
203
+ "hard_questions": [],
204
+ "links": []
205
+ }
206
+ ],
207
+ "open_vagueness": []
208
+ }
@@ -0,0 +1,307 @@
1
+ {
2
+ "slug": "every-devex-command-now-closes-with-a-deterministi",
3
+ "title": "Every devex command now closes with a deterministic, per-backend Next step micro-prompt telling the running agent exactly how to continue \u2014 the pr namespace footer convention becomes a cross-command guarantee.",
4
+ "frame_slug": "every-devex-command-now-closes-with-a-deterministi",
5
+ "schema_version": 1,
6
+ "status": "exported",
7
+ "created": "2026-05-29T15:12:32Z",
8
+ "updated": "2026-05-29T15:18:39Z",
9
+ "targets": [
10
+ {
11
+ "id": "c1",
12
+ "kind": "announcement",
13
+ "text": "Every devex command now closes with a deterministic, per-backend Next step micro-prompt telling the running agent exactly how to continue \u2014 the pr namespace footer convention becomes a cross-command guarantee."
14
+ },
15
+ {
16
+ "id": "h4",
17
+ "kind": "honesty",
18
+ "text": "Every command path that reaches stdout terminates in exactly one Next step footer block \u2014 the guarantee is total, not best-effort \u2014 verified by a test that runs every non-silent command and asserts a trailing footer."
19
+ },
20
+ {
21
+ "id": "c2",
22
+ "kind": "audience",
23
+ "text": "Autonomous coding agents (claude-code, codex, copilot, acp backends) that invoke devex commands non-interactively and must pick their next move without an LLM in the loop."
24
+ },
25
+ {
26
+ "id": "h6",
27
+ "kind": "honesty",
28
+ "text": "Every footer hint is phrased as an actionable instruction to the running agent (an imperative naming a concrete next command/move), never human-facing prose \u2014 asserted by a test/lint on hint form."
29
+ },
30
+ {
31
+ "id": "c3",
32
+ "kind": "after_state",
33
+ "text": "Every non-silent devex command (explain, learn, overview, doctor, gamify, hook read, plus the existing pr namespace) ends its markdown with a Next step footer naming a concrete next move, so the agent never has to infer what to run next."
34
+ },
35
+ {
36
+ "id": "h3",
37
+ "kind": "honesty",
38
+ "text": "For each non-silent command there is a deterministic mapping from its observable end-state to exactly one rule_key, so the footer is reproducible across identical inputs."
39
+ },
40
+ {
41
+ "id": "c4",
42
+ "kind": "before_state",
43
+ "text": "Today only the pr namespace ends with a Next step footer. explain, learn, overview, doctor and hook read end at EOF; gamify install has a one-off ad-hoc Next line. After every other command the agent must guess the next move."
44
+ },
45
+ {
46
+ "id": "h7",
47
+ "kind": "honesty",
48
+ "text": "A snapshot test of current non-pr command output confirms none emits a Next step footer today, so the gap this feature closes is demonstrated, not assumed."
49
+ },
50
+ {
51
+ "id": "c5",
52
+ "kind": "why_it_matters",
53
+ "text": "devex exists to give autonomous agents deterministic guidance. A command that ends without a next-move prompt leaves a decision gap the agent fills by guessing \u2014 non-deterministic behaviour in a tool whose whole premise is determinism. A closing micro-prompt makes the command surface self-chaining."
54
+ },
55
+ {
56
+ "id": "h8",
57
+ "kind": "honesty",
58
+ "text": "The footer is fully determined by command inputs plus project state with zero LLM/network/random input \u2014 identical inputs always yield an identical footer, asserted by a reproducibility test."
59
+ },
60
+ {
61
+ "id": "c6",
62
+ "kind": "boundary",
63
+ "text": "Out of scope: rewriting command body content; LLM-generated footers; adding a footer to deliberately-silent commands such as hook write which emits empty stdout; and auto-executing the suggested command \u2014 the footer is a prompt, not an action, so no new side effects are introduced."
64
+ },
65
+ {
66
+ "id": "h9",
67
+ "kind": "honesty",
68
+ "text": "After the change hook write still emits empty stdout and no command gains a new network/file-write/sleep side effect from the footer \u2014 verified by the existing side-effect/invariant tests staying green."
69
+ },
70
+ {
71
+ "id": "c7",
72
+ "kind": "success_signal",
73
+ "text": "A test asserts every non-silent command stdout ends with the footer block, and that each backend YAML defines a hint for every rule key its command can emit, so there is no missing-hint KeyError at runtime."
74
+ },
75
+ {
76
+ "id": "h10",
77
+ "kind": "honesty",
78
+ "text": "Both guard tests (every-command-ends-with-a-footer; every reachable rule_key has a hint) exist, run in CI, and fail loudly when a command or rule_key is added without a hint."
79
+ },
80
+ {
81
+ "id": "c8",
82
+ "kind": "requirement",
83
+ "text": "The footer-rendering machinery now under commands/pr (the _footer renderer, the rule_key plus context decision pattern, and footer.md.j2) is promoted to core so every command shares one implementation."
84
+ },
85
+ {
86
+ "id": "h1",
87
+ "kind": "honesty",
88
+ "text": "After the machinery moves to core, the pr namespace footers are byte-identical and every existing pr footer test passes unchanged (pure relocation, no behaviour change)."
89
+ },
90
+ {
91
+ "id": "c9",
92
+ "kind": "requirement",
93
+ "text": "Each non-pr command gains a small next-step decision function returning rule_key plus context, and a hints block in its per-command assets/backends/backend.yaml, mirroring how the pr namespace is structured."
94
+ },
95
+ {
96
+ "id": "h2",
97
+ "kind": "honesty",
98
+ "text": "One enumerating test walks every (command, backend, reachable rule_key) triple and fails if any hint string is missing, proving coverage rather than assuming it."
99
+ },
100
+ {
101
+ "id": "c10",
102
+ "kind": "requirement",
103
+ "text": "Backend-agnostic commands that do not take --agent today (explain, doctor) must still end with a coherent Next step footer."
104
+ },
105
+ {
106
+ "id": "h5",
107
+ "kind": "honesty",
108
+ "text": "With --agent provided, explain/doctor render that backend's hint; with it omitted they render a neutral hint from a shared default; both paths are test-covered so the optional flag never yields a missing or empty footer."
109
+ }
110
+ ],
111
+ "tasks": [
112
+ {
113
+ "id": "t1",
114
+ "summary": "Promote the footer-rendering machinery from commands/pr into core (pure relocation, no behaviour change)",
115
+ "origin": "llm",
116
+ "status": "confirmed",
117
+ "acceptance_criteria": [
118
+ "A new core module (core/footer.py) exposes render_footer plus hint-loading, and footer.md.j2 moves to a core assets location",
119
+ "All pr scripts import the footer renderer from core and pr footer output is byte-identical to before (snapshot diff empty)",
120
+ "The entire existing pr footer test suite passes unchanged"
121
+ ],
122
+ "deps": [],
123
+ "covers": [
124
+ "c8",
125
+ "h1"
126
+ ]
127
+ },
128
+ {
129
+ "id": "t2",
130
+ "summary": "Add neutral-default footer resolution to the core renderer for when no backend is supplied",
131
+ "origin": "llm",
132
+ "status": "confirmed",
133
+ "acceptance_criteria": [
134
+ "When render_footer is called with no backend it resolves hints from a shared neutral source and returns a valid Next step block",
135
+ "Unit test: the neutral path yields a non-empty footer and the backend-specific path is unchanged"
136
+ ],
137
+ "deps": [
138
+ "t1"
139
+ ],
140
+ "covers": [
141
+ "c10",
142
+ "h5"
143
+ ]
144
+ },
145
+ {
146
+ "id": "t3",
147
+ "summary": "Add an optional --agent flag to explain and doctor and wire their Next step footers (backend hint when given, neutral when omitted)",
148
+ "origin": "llm",
149
+ "status": "confirmed",
150
+ "acceptance_criteria": [
151
+ "devex explain TOPIC and devex doctor accept an optional --agent and existing flagless invocations keep working unchanged",
152
+ "With --agent the footer uses that backend per-command hints, without it the neutral footer is emitted, and both paths are covered by tests",
153
+ "Each of explain and doctor has a next-step decision function and a hints block (backend yamls plus neutral)"
154
+ ],
155
+ "deps": [
156
+ "t2"
157
+ ],
158
+ "covers": [
159
+ "c10",
160
+ "h5",
161
+ "c9"
162
+ ]
163
+ },
164
+ {
165
+ "id": "t4",
166
+ "summary": "Add a Next step footer to learn (menu and topic views) with a decision function and per-backend hints",
167
+ "origin": "llm",
168
+ "status": "confirmed",
169
+ "acceptance_criteria": [
170
+ "learn menu and learn TOPIC both end with a Next step footer chosen by a decision function returning a rule_key plus context",
171
+ "commands/learn/assets/backends per-backend yaml defines a hint for every rule_key learn can emit, for all four backends",
172
+ "Unit tests cover the menu and topic footers for at least one backend"
173
+ ],
174
+ "deps": [
175
+ "t1"
176
+ ],
177
+ "covers": [
178
+ "c9",
179
+ "c3"
180
+ ]
181
+ },
182
+ {
183
+ "id": "t5",
184
+ "summary": "Add a Next step footer to overview with a decision function and per-backend hints",
185
+ "origin": "llm",
186
+ "status": "confirmed",
187
+ "acceptance_criteria": [
188
+ "overview ends with a Next step footer chosen by a decision function returning a rule_key plus context",
189
+ "commands/overview/assets/backends per-backend yaml defines a hint for every rule_key overview can emit, for all four backends",
190
+ "A unit test asserts the overview footer for at least one backend"
191
+ ],
192
+ "deps": [
193
+ "t1"
194
+ ],
195
+ "covers": [
196
+ "c9",
197
+ "c3"
198
+ ]
199
+ },
200
+ {
201
+ "id": "t6",
202
+ "summary": "Replace gamify ad-hoc Next line with the structured Next step footer for install and uninstall",
203
+ "origin": "llm",
204
+ "status": "confirmed",
205
+ "acceptance_criteria": [
206
+ "gamify install and uninstall end with the structured footer and the old ad-hoc Next line is removed",
207
+ "commands/gamify/assets/backends per-backend yaml defines a hint for every rule_key gamify can emit, for all four backends",
208
+ "Unit tests cover the install and uninstall footers for at least one backend"
209
+ ],
210
+ "deps": [
211
+ "t1"
212
+ ],
213
+ "covers": [
214
+ "c9",
215
+ "c3"
216
+ ]
217
+ },
218
+ {
219
+ "id": "t7",
220
+ "summary": "Add a Next step footer to hook read while keeping hook write silent",
221
+ "origin": "llm",
222
+ "status": "confirmed",
223
+ "acceptance_criteria": [
224
+ "hook read ends with a Next step footer chosen by a decision function, and hook write still emits empty stdout with no footer",
225
+ "commands/hook/assets/backends per-backend yaml defines a hint for every rule_key hook read can emit, for all four backends",
226
+ "Unit tests assert the hook read footer and that hook write output stays empty"
227
+ ],
228
+ "deps": [
229
+ "t1"
230
+ ],
231
+ "covers": [
232
+ "c9",
233
+ "c3"
234
+ ]
235
+ },
236
+ {
237
+ "id": "t8",
238
+ "summary": "Add cross-command footer-guarantee tests: total coverage, determinism, no new side effects, and the pre-change gap",
239
+ "origin": "llm",
240
+ "status": "confirmed",
241
+ "acceptance_criteria": [
242
+ "A parametrized test runs every non-silent command and asserts stdout ends with exactly one Next step footer block",
243
+ "A determinism test runs each command twice on identical project state and asserts byte-identical footers (no LLM, network, or randomness)",
244
+ "A test asserts hook write emits empty stdout and that no command performs network, file-write, or sleep to build its footer",
245
+ "A test demonstrates the pre-change gap: with the footer block absent each command body contains no Next step marker"
246
+ ],
247
+ "deps": [
248
+ "t3",
249
+ "t4",
250
+ "t5",
251
+ "t6",
252
+ "t7"
253
+ ],
254
+ "covers": [
255
+ "c1",
256
+ "c3",
257
+ "c4",
258
+ "c5",
259
+ "c6",
260
+ "h3",
261
+ "h4",
262
+ "h7",
263
+ "h8",
264
+ "h9"
265
+ ]
266
+ },
267
+ {
268
+ "id": "t9",
269
+ "summary": "Add hint-coverage and hint-form guard tests wired into the existing CI test job",
270
+ "origin": "llm",
271
+ "status": "confirmed",
272
+ "acceptance_criteria": [
273
+ "An enumerating test walks every command-backend-rule_key triple and fails if any hint string is missing",
274
+ "A hint-form test asserts each hint is an imperative addressed to the agent that names a concrete devex command or move, not human prose",
275
+ "Both guard tests run under the existing pytest CI job and fail loudly when a command or rule_key is added without a hint"
276
+ ],
277
+ "deps": [
278
+ "t3",
279
+ "t4",
280
+ "t5",
281
+ "t6",
282
+ "t7"
283
+ ],
284
+ "covers": [
285
+ "c2",
286
+ "c7",
287
+ "h2",
288
+ "h6",
289
+ "h10"
290
+ ]
291
+ }
292
+ ],
293
+ "risks": [
294
+ {
295
+ "id": "r1",
296
+ "text": "Exact neutral-footer hint phrasing for explain and doctor is unspecified; builder picks concise agent-facing wording",
297
+ "kind": "unknown_nonblocking",
298
+ "task_id": "t3"
299
+ },
300
+ {
301
+ "id": "r2",
302
+ "text": "The hint-form check (imperative naming a command) is heuristic and may need tuning to avoid false positives",
303
+ "kind": "follow_up",
304
+ "task_id": "t9"
305
+ }
306
+ ]
307
+ }
@@ -23,6 +23,47 @@ jobs:
23
23
  - run: uv pip install -e ".[dev]"
24
24
  - run: uv run pytest
25
25
 
26
+ # --------------------------------------------------------------------------
27
+ # SonarCloud CI-based analysis + coverage. SonarCloud is no longer in
28
+ # Automatic Analysis mode (the two modes are mutually exclusive), so this job
29
+ # is the sole analysis path: it generates coverage.xml (with repo-relative
30
+ # paths via pyproject [tool.coverage.run] so Sonar can match files) and runs
31
+ # the scanner, which
32
+ # reads sonar-project.properties (projectKey / organization / reportPaths)
33
+ # and the SONAR_TOKEN repo secret. Runs on PRs (new-code decoration) and on
34
+ # pushes to main (baseline). fetch-depth: 0 gives Sonar the full history it
35
+ # needs for accurate new-code / blame attribution.
36
+ # --------------------------------------------------------------------------
37
+ sonarcloud:
38
+ name: SonarCloud
39
+ runs-on: ubuntu-latest
40
+ # Promote a *presence flag* (not the secret) to job env so the scan step
41
+ # can gate on it — `secrets.*` isn't allowed in `if:`. Lets forks /
42
+ # token-less runs skip the scan rather than hard-fail. (Pattern from the
43
+ # sibling agentfront repo, whose CI-based SonarCloud scan is green.)
44
+ env:
45
+ SONAR_TOKEN_PRESENT: ${{ secrets.SONAR_TOKEN != '' }}
46
+ steps:
47
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
48
+ with:
49
+ fetch-depth: 0
50
+ - uses: astral-sh/setup-uv@caf0cab7a618c569241d31dcd442f54681755d39 # v3
51
+ - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
52
+ with:
53
+ python-version: "3.12"
54
+ - run: uv venv
55
+ - run: uv pip install -e ".[dev]"
56
+ - run: uv run pytest --cov=src/devex --cov-report=xml --cov-report=term
57
+ # Pinned to v6 to match the sibling agentfront repo's working scan.
58
+ # The v7+/v8 scanner engine 404s on `api.sonarcloud.io/analysis/analyses`
59
+ # against SonarQube Cloud; v6 posts to sonarcloud.io directly.
60
+ - name: SonarCloud Scan
61
+ if: env.SONAR_TOKEN_PRESENT == 'true'
62
+ uses: SonarSource/sonarqube-scan-action@fd88b7d7ccbaefd23d8f36f73b59db7a3d246602 # v6
63
+ env:
64
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
65
+ SONAR_HOST_URL: https://sonarcloud.io
66
+
26
67
  # --------------------------------------------------------------------------
27
68
  # Enforces that every PR touching code (src/, tests/, pyproject.toml) also
28
69
  # bumps the version in pyproject.toml. Without this, a merge to main that
@@ -213,3 +213,12 @@ __marimo__/
213
213
 
214
214
  # Worktrees
215
215
  .worktrees/
216
+
217
+ # devague working state (not committed by default)
218
+ .devague/questions/
219
+
220
+ .devague/reviews/
221
+
222
+ # devague session pointers (transient)
223
+ .devague/current
224
+ .devague/current_plan
@@ -7,6 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.27.0] - 2026-05-29
11
+
12
+ ### Added
13
+
14
+ - Cross-command `Next step:` footers: every non-silent command (`explain`, `learn`, `overview`, `doctor`, `gamify`, `hook read`, plus the `pr` namespace) now ends with a deterministic, per-backend agent-facing micro-prompt telling the running agent how to continue.
15
+ - Optional `--agent` on `explain` and `doctor`: backend-specific footer when supplied, neutral footer when omitted (non-breaking; flagless calls keep working).
16
+ - `core/footer.py` — shared, command-agnostic footer renderer (`render_footer` + `render_neutral_footer`) plus a neutral hints source `core/assets/backends/neutral.yaml`.
17
+ - Per-command next-step decision functions and `hints:` blocks under `commands/<cmd>/assets/backends/<backend>.yaml`.
18
+ - Footer-guarantee + hint-coverage guard tests (every command ends with one footer; every reachable rule_key has a hint; deterministic, no new side effects).
19
+
20
+ ### Changed
21
+
22
+ - Footer-rendering machinery promoted from `commands/pr/` into `core/` (pure relocation; pr footers byte-identical).
23
+ - `gamify` now emits the structured footer for install/uninstall, replacing the prior ad-hoc `Next:` line.
24
+
25
+ ### Fixed
26
+
27
+ - `gamify` unsupported-backend notice (codex/copilot/acp) now ends with a `Next step:` footer, closing a gap in the cross-command guarantee.
28
+
29
+ ## [0.26.1] - 2026-05-29
30
+
31
+ ### Added
32
+
33
+ - SonarCloud CI-based analysis + coverage upload: a `sonarcloud` job in test.yml runs `pytest --cov` and the SHA-pinned `sonarqube-scan-action` (v6), reading `sonar-project.properties` + the `SONAR_TOKEN` secret. Coverage config lives in `pyproject.toml [tool.coverage.run]` (`relative_files` so coverage.xml paths map to `sonar.sources=src`).
34
+
35
+ ### Changed
36
+
37
+ - SonarCloud moved from Automatic Analysis to CI-based analysis (the two are mutually exclusive); project now under the `agentculture` org. Updated CLAUDE.md / sonar-project.properties notes accordingly.
38
+
10
39
  ## [0.26.0] - 2026-05-29
11
40
 
12
41
  ### Added
@@ -38,9 +38,13 @@ cli.py ──► commands/<name>/scripts/<name>.py ──► core/render.py
38
38
 
39
39
  - `cli.py` (Typer) routes `devex <command> [args] --agent X`. No business logic.
40
40
  - Each `commands/<name>/` is a **skill-folder**: `SKILL.md` + `scripts/` + `assets/` + `references/`. The `SKILL.md` doubles as the content emitted by `devex explain <command>`.
41
- - `core/` is shared plumbing — backend enum, `.devex/` paths, Jinja renderer (`StrictUndefined`), TOML config, SKILL.md frontmatter parser, capability matrix loader, hook JSON I/O. Command- and content-agnostic.
41
+ - `core/` is shared plumbing — backend enum, `.devex/` paths, Jinja renderer (`StrictUndefined`), TOML config, SKILL.md frontmatter parser, capability matrix loader, hook JSON I/O, footer renderer (`core/footer.py`). Command- and content-agnostic.
42
42
  - A backend lives in three places: `core/backend.Backend` (enum entry), `backends/<name>/probe.py` (optional Python probe), and one YAML per relevant command under `commands/*/assets/backends/<name>.yaml`. Adding a backend touches only those locations.
43
43
 
44
+ ## Cross-command "Next step:" footers (v0.27.0+)
45
+
46
+ Every non-silent command ends with a deterministic, per-backend **"Next step:"** footer — an agent-facing micro-prompt telling the running agent how to continue. The renderer is shared in `core/footer.py`: `render_footer(rule_key, backend, context, backends_pkg)` (backend path) and `render_neutral_footer(rule_key, context)` (no-backend path; hints from `core/assets/backends/neutral.yaml`); the block template is `core/assets/footer.md.j2` (`---\n**Next step:** <hint>`). Each command supplies a decision function (`commands/<cmd>/scripts/next_step.py`, returns `(rule_key, context)`) and per-backend `hints:` under `commands/<cmd>/assets/backends/<backend>.yaml`. `explain` and `doctor` take an **optional** `--agent` (backend footer when given, neutral when omitted; flagless calls unchanged). `hook write` stays **silent** (no footer) — the deliberate exception. Two guard tests enforce the guarantee: `tests/test_footer_guarantee.py` (every command ends with exactly one footer; deterministic; no new side effects) and `tests/test_footer_hints.py` (every reachable `(command, backend, rule_key)` has a hint; hints are agent-imperative).
47
+
44
48
  ## `devex pr` namespace (v0.17.0+)
45
49
 
46
50
  `lint`, `open`, `read`, `reply`, `review`, `await`, `delta`. Each command ends with a deterministic "Next step:" footer. The `pr` namespace allows scoped network I/O (via `gh`) and bounded `--wait` sleep — a deliberate carve-out from the no-network/no-sleep invariants. `pr open` (non-draft, new PR) and `pr review` post the Qodo `/agentic_review` trigger comment; the legacy `/improve` is deprecated and never emitted. The trigger string lives in one place: `commands/pr/scripts/review.QODO_REVIEW_TRIGGER`. `pr await --detach` / `--check` (issue #64) move the bounded poll out of the agent session: `--detach` forks a detached worker (`commands/pr/scripts/_await_worker.py`) that writes the verdict to a marker (`commands/pr/scripts/_detach.py`, atomic `os.replace`), and `--check` reads it back without sleeping. Key modules:
@@ -78,15 +82,15 @@ uv run devex --version
78
82
  uv run devex explain devex
79
83
  uv run devex explain explain
80
84
 
81
- # Coverage (matches what build.yml runs; SonarCloud reads this file)
85
+ # Coverage (matches the `sonarcloud` job in test.yml; SonarCloud reads coverage.xml)
82
86
  uv run pytest --cov=src/devex --cov-report=xml --cov-report=term
83
87
  ```
84
88
 
85
89
  ## CI surface
86
90
 
87
- - `.github/workflows/test.yml` — matrix: 3 OS × 4 Python (3.10–3.13) running `uv run pytest`. Also runs a `version-check` job on PRs that fails (with a sticky `<!-- version-check -->` comment) when `pyproject.toml`'s version on the PR matches the one on `main` and any code file under `src/` / `tests/` / `pyproject.toml` changed. Docs-only PRs skip the check.
91
+ - `.github/workflows/test.yml` — matrix: 3 OS × 4 Python (3.10–3.13) running `uv run pytest`. Also runs (1) a `sonarcloud` job that generates `coverage.xml` (`pytest --cov`, repo-relative paths via `pyproject [tool.coverage.run]`) and runs the SHA-pinned `sonarqube-scan-action` (needs the `SONAR_TOKEN` repo secret); and (2) a `version-check` job on PRs that fails (with a sticky `<!-- version-check -->` comment) when `pyproject.toml`'s version on the PR matches the one on `main` and any code file under `src/` / `tests/` / `pyproject.toml` changed. Docs-only PRs skip the version check.
88
92
  - `.github/workflows/publish.yml` — builds sdist + wheel. PRs publish a per-PR dev version to TestPyPI (sticky install-command comment); pushes to `main` publish the stable version to TestPyPI (canary), then an `autotag` job pushes `v<version>` if missing, which gates the inline `publish-pypi` + `github-release` jobs. No manual tagging — bumping `pyproject.toml` is the release signal.
89
- - SonarCloud is configured as **Automatic Analysis** on the repo (no CI workflow). Coverage and quality are read by SonarCloud directly.
93
+ - SonarCloud runs in **CI-based analysis** mode (Automatic Analysis is off — the two are mutually exclusive). The `sonarcloud` job in `test.yml` uploads coverage + triggers the scan via `sonarqube-scan-action`, reading `sonar-project.properties` and the `SONAR_TOKEN` secret. The quality gate decorates PRs and gates merges.
90
94
  - All third-party actions are **pinned to full commit SHAs** with trailing `# vN` comments (rule `githubactions:S7637`). Keep new actions pinned the same way.
91
95
 
92
96
  ## SonarCloud notes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agex-cli
3
- Version: 0.26.0
3
+ Version: 0.27.0
4
4
  Summary: Agent-operated developer-experience CLI — deterministic per-backend markdown briefings for autonomous agents.
5
5
  Project-URL: Homepage, https://culture.dev/devex/
6
6
  Project-URL: Repository, https://github.com/agentculture/devex