agex-cli 0.22.0__tar.gz → 0.24.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.
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.github/workflows/publish.yml +19 -13
- {agex_cli-0.22.0 → agex_cli-0.24.0}/CHANGELOG.md +28 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/CLAUDE.md +3 -3
- {agex_cli-0.22.0 → agex_cli-0.24.0}/PKG-INFO +6 -6
- agex_cli-0.24.0/README.md +29 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/pyproject.toml +4 -3
- {agex_cli-0.22.0 → agex_cli-0.24.0}/sonar-project.properties +2 -2
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/__init__.py +8 -7
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/cli.py +48 -15
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/doctor/assets/report.md.j2 +2 -2
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/doctor/scripts/doctor.py +12 -9
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/explain/assets/topics/agex.md +1 -1
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/explain/scripts/explain.py +2 -1
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/gamify/scripts/install.py +7 -5
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/hook/scripts/write.py +2 -1
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/assets/menu.md.j2 +1 -1
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/scripts/learn.py +3 -2
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/SKILL.md +24 -3
- agex_cli-0.24.0/src/agent_experience/commands/pr/assets/backends/acp.yaml +21 -0
- agex_cli-0.24.0/src/agent_experience/commands/pr/assets/backends/claude-code.yaml +21 -0
- agex_cli-0.24.0/src/agent_experience/commands/pr/assets/backends/codex.yaml +21 -0
- agex_cli-0.24.0/src/agent_experience/commands/pr/assets/backends/copilot.yaml +21 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/assets/rules/next_step_rules.py +4 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/assets/templates/delta.md.j2 +1 -1
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/assets/templates/lint_result.md.j2 +2 -2
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/assets/templates/pr_briefing.md.j2 +1 -1
- agex_cli-0.24.0/src/agent_experience/commands/pr/assets/templates/pr_open_result.md.j2 +17 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/assets/templates/pr_reply_result.md.j2 +1 -1
- agex_cli-0.24.0/src/agent_experience/commands/pr/assets/templates/pr_review_result.md.j2 +5 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/scripts/_readiness.py +5 -1
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/scripts/await_.py +1 -10
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/scripts/delta.py +4 -2
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/scripts/open_.py +23 -1
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/scripts/read.py +1 -10
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/scripts/reply.py +6 -4
- agex_cli-0.24.0/src/agent_experience/commands/pr/scripts/review.py +59 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/core/capabilities.py +1 -1
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/core/github.py +15 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/core/hook_io.py +1 -1
- agex_cli-0.24.0/src/agent_experience/core/prog.py +44 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/core/render.py +9 -1
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/test_footer.py +16 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/test_open.py +90 -0
- agex_cli-0.24.0/tests/commands/pr/test_review.py +97 -0
- agex_cli-0.24.0/tests/commands/test_prog_propagation.py +45 -0
- agex_cli-0.24.0/tests/core/test_prog.py +39 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/core/test_version_lookup.py +13 -6
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/test_cli_dispatch.py +11 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/uv.lock +1 -1
- agex_cli-0.22.0/README.md +0 -29
- agex_cli-0.22.0/src/agent_experience/commands/pr/assets/backends/acp.yaml +0 -20
- agex_cli-0.22.0/src/agent_experience/commands/pr/assets/backends/claude-code.yaml +0 -20
- agex_cli-0.22.0/src/agent_experience/commands/pr/assets/backends/codex.yaml +0 -20
- agex_cli-0.22.0/src/agent_experience/commands/pr/assets/backends/copilot.yaml +0 -20
- agex_cli-0.22.0/src/agent_experience/commands/pr/assets/templates/pr_open_result.md.j2 +0 -13
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/agent-config/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/agent-config/data/backend-fingerprints.yaml +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/agent-config/scripts/show.sh +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/assign-to-workforce/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/cicd/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/cicd/scripts/workflow.sh +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/communicate/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/run-tests/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/sonarclaude/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/spec-to-plan/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/think/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/think/scripts/think.sh +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/version-bump/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.claude/skills/version-bump/scripts/bump.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.flake8 +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.github/workflows/test.yml +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.gitignore +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/.python-version +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/LICENSE +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/culture.yaml +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/docs/skill-sources.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/docs/superpowers/plans/2026-04-18-agex-v0.1.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/docs/superpowers/plans/2026-05-10-agex-pr.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/docs/superpowers/specs/2026-04-18-agex-design.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/docs/superpowers/specs/2026-04-26-agex-doctor.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/docs/superpowers/specs/2026-05-10-agex-pr-design.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/__main__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/backends/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/backends/acp/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/backends/acp/probe.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/backends/capabilities/acp.yaml +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/backends/capabilities/claude-code.yaml +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/backends/capabilities/codex.yaml +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/backends/capabilities/copilot.yaml +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/backends/claude_code/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/backends/claude_code/probe.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/backends/codex/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/backends/codex/probe.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/backends/copilot/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/backends/copilot/probe.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/doctor/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/doctor/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/doctor/references/design.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/doctor/scripts/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/explain/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/explain/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/explain/references/.gitkeep +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/explain/scripts/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/gamify/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/gamify/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/gamify/assets/hooks/claude-code.json +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/gamify/references/.gitkeep +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/gamify/scripts/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/hook/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/hook/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/hook/assets/table.md.j2 +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/hook/references/.gitkeep +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/hook/scripts/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/hook/scripts/read.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/assets/topics/cicd/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/assets/topics/gamify/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/assets/topics/gamify/assets/skill-template/claude-code/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/assets/topics/introspect/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/assets/topics/introspect/assets/skill-template/claude-code/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/assets/topics/levelup/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/assets/topics/levelup/assets/skill-template/claude-code/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/assets/topics/visualize/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/assets/topics/visualize/assets/skill-template/claude-code/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/references/.gitkeep +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/learn/scripts/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/overview/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/overview/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/overview/assets/backends/acp.yaml +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/overview/assets/backends/claude-code.yaml +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/overview/assets/backends/codex.yaml +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/overview/assets/backends/copilot.yaml +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/overview/assets/sections.md.j2 +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/overview/references/.gitkeep +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/overview/scripts/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/overview/scripts/overview.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/assets/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/assets/backends/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/assets/rules/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/assets/rules/lint_rules.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/assets/templates/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/assets/templates/footer.md.j2 +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/scripts/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/scripts/_footer.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/scripts/_journal.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/scripts/_qodo.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/scripts/_sonar.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/pr/scripts/lint.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/core/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/core/backend.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/core/config.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/core/journal.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/core/paths.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/core/skill_loader.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tester-agents/claude/.claude/settings.json +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tester-agents/claude/CLAUDE.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tester-agents/claude/README.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tester-agents/claude/culture.yaml +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/backends/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/backends/test_claude_code_probe.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/backends/test_stub_probes.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/fixtures/gh/.gitkeep +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/fixtures/gh/pr_checks_42.json +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/fixtures/gh/pr_comments_42.json +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/fixtures/gh/qodo_summary_comment.html +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/fixtures/journals/dogfood_40.jsonl +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/test_await.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/test_delta.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/test_lint.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/test_lint_rules.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/test_qodo.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/test_read.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/pr/test_reply.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/test_doctor.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/test_explain.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/test_gamify.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/test_hook.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/test_learn.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/commands/test_overview.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/core/__init__.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/core/test_backend.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/core/test_capabilities.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/core/test_config.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/core/test_github.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/core/test_hook_io.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/core/test_journal.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/core/test_paths.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/core/test_render.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/core/test_resolve_backend.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/core/test_skill_loader.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/fixtures/claude-code/empty/.gitkeep +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/fixtures/claude-code/malformed/.claude/hooks.json +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/fixtures/claude-code/malformed/.claude/settings.json +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/fixtures/claude-code/malformed/.claude/skills/bad/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/fixtures/claude-code/malformed/.claude/skills/broken-yaml/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/fixtures/claude-code/typical/.claude/hooks.json +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/fixtures/claude-code/typical/.claude/settings.json +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/fixtures/claude-code/typical/.claude/skills/example/SKILL.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/fixtures/claude-code/typical/CLAUDE.md +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/test_cli_errors.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/test_cli_smoke.py +0 -0
- {agex_cli-0.22.0 → agex_cli-0.24.0}/tests/test_skill_md_consistency.py +0 -0
|
@@ -27,15 +27,20 @@ name: publish
|
|
|
27
27
|
# One-time setup on pypi.org / test.pypi.org and in the repo's Environments
|
|
28
28
|
# (`pypi`, `testpypi`) is documented in the original header below:
|
|
29
29
|
#
|
|
30
|
-
# - PyPI project `agex-cli`
|
|
31
|
-
#
|
|
30
|
+
# - For EACH PyPI project (`agex-cli`, `agent-devex`, `devex-cli`)
|
|
31
|
+
# → Publishing → Add a GitHub pending publisher
|
|
32
|
+
# Owner: agentculture Repo: devex
|
|
32
33
|
# Workflow: publish.yml Environment: pypi
|
|
33
34
|
#
|
|
34
|
-
# -
|
|
35
|
+
# - Same for EACH TestPyPI project, Environment: testpypi
|
|
35
36
|
#
|
|
36
37
|
# - GitHub repo → Settings → Environments → create `pypi` and `testpypi`
|
|
37
38
|
# (any required reviewers / wait timers live there)
|
|
38
39
|
#
|
|
40
|
+
# NOTE: the repo was renamed agentculture/agex-cli → agentculture/devex.
|
|
41
|
+
# The pre-existing `agex-cli` / `agent-devex` publishers must have their
|
|
42
|
+
# Repo updated to `devex` too, or those legs start failing OIDC.
|
|
43
|
+
#
|
|
39
44
|
# The PR job rewrites `version = "X.Y.Z"` to `"X.Y.Z.devN"` where N is
|
|
40
45
|
# the workflow run number. PEP 440's dev segment is a single integer
|
|
41
46
|
# (internal dots aren't allowed), so run_attempt is NOT encoded in the
|
|
@@ -67,10 +72,11 @@ jobs:
|
|
|
67
72
|
# pull_request -- the PR path has its own build inside `publish-pr-testpypi`
|
|
68
73
|
# because it needs to rewrite the version before building.
|
|
69
74
|
#
|
|
70
|
-
# The matrix exists so we can publish the same code under
|
|
71
|
-
# distribution names: `agex-cli` (canonical)
|
|
72
|
-
# Each leg rewrites `[project].name` in pyproject.toml
|
|
73
|
-
# each wheel is uploaded under its own Trusted Publishing
|
|
75
|
+
# The matrix exists so we can publish the same code under three PyPI
|
|
76
|
+
# distribution names: `agex-cli` (canonical) plus the `agent-devex` and
|
|
77
|
+
# `devex-cli` aliases. Each leg rewrites `[project].name` in pyproject.toml
|
|
78
|
+
# before building so each wheel is uploaded under its own Trusted Publishing
|
|
79
|
+
# project.
|
|
74
80
|
# --------------------------------------------------------------------------
|
|
75
81
|
build:
|
|
76
82
|
if: github.event_name == 'push'
|
|
@@ -78,7 +84,7 @@ jobs:
|
|
|
78
84
|
strategy:
|
|
79
85
|
fail-fast: false
|
|
80
86
|
matrix:
|
|
81
|
-
dist_name: [agex-cli, agent-devex]
|
|
87
|
+
dist_name: [agex-cli, agent-devex, devex-cli]
|
|
82
88
|
permissions:
|
|
83
89
|
contents: read # actions/checkout
|
|
84
90
|
steps:
|
|
@@ -93,8 +99,8 @@ jobs:
|
|
|
93
99
|
|
|
94
100
|
# Rewrite `[project].name` to the matrix dist name. For `agex-cli`
|
|
95
101
|
# (the canonical dist) the regex still has to match so we re-emit
|
|
96
|
-
# the line; for `agent-devex` it produces an alias dist
|
|
97
|
-
# identical contents. The post-rewrite re-parse is a fail-closed
|
|
102
|
+
# the line; for `agent-devex` / `devex-cli` it produces an alias dist
|
|
103
|
+
# with identical contents. The post-rewrite re-parse is a fail-closed
|
|
98
104
|
# check: if a future formatting change breaks the regex match (or
|
|
99
105
|
# `[project].name` ends up wrong for any reason), the job aborts
|
|
100
106
|
# before uploading mis-named artifacts.
|
|
@@ -150,7 +156,7 @@ jobs:
|
|
|
150
156
|
strategy:
|
|
151
157
|
fail-fast: false
|
|
152
158
|
matrix:
|
|
153
|
-
dist_name: [agex-cli, agent-devex]
|
|
159
|
+
dist_name: [agex-cli, agent-devex, devex-cli]
|
|
154
160
|
environment: testpypi
|
|
155
161
|
permissions:
|
|
156
162
|
id-token: write # OIDC -- Trusted Publishing
|
|
@@ -273,7 +279,7 @@ jobs:
|
|
|
273
279
|
strategy:
|
|
274
280
|
fail-fast: false
|
|
275
281
|
matrix:
|
|
276
|
-
dist_name: [agex-cli, agent-devex]
|
|
282
|
+
dist_name: [agex-cli, agent-devex, devex-cli]
|
|
277
283
|
environment: testpypi
|
|
278
284
|
permissions:
|
|
279
285
|
id-token: write # OIDC; no API token needed
|
|
@@ -372,7 +378,7 @@ jobs:
|
|
|
372
378
|
strategy:
|
|
373
379
|
fail-fast: false
|
|
374
380
|
matrix:
|
|
375
|
-
dist_name: [agex-cli, agent-devex]
|
|
381
|
+
dist_name: [agex-cli, agent-devex, devex-cli]
|
|
376
382
|
environment: pypi
|
|
377
383
|
permissions:
|
|
378
384
|
id-token: write # OIDC; no API token needed
|
|
@@ -7,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.24.0] - 2026-05-28
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `agex pr review [<PR>]` verb — posts the Qodo agentic-review trigger (`/agentic_review`) on demand; re-triggers a review on an existing PR or triggers a draft once ready.
|
|
15
|
+
- `agex pr open` now auto-posts `/agentic_review` out of the box for a freshly created, non-draft PR (skipped for drafts and already-open PRs) so the review trigger is never hand-typed (#60).
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Centralized the Qodo review-trigger command string in one place (`commands/pr/scripts/review.QODO_REVIEW_TRIGGER`). agex emits the current `/agentic_review`; the legacy `/improve` command is deprecated by Qodo and is never emitted by agex (#60).
|
|
20
|
+
|
|
21
|
+
## [0.23.0] - 2026-05-28
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- `devex` console command — second entry point alongside `agex`; both invoke the same CLI and emitted output (Next-step footers, briefing/template headers, error prefixes) reflects whichever name was typed, via the new single-source-of-truth `core.prog.prog_name()` injected into the render context.
|
|
26
|
+
- Third PyPI distribution name `devex-cli` — the same wheel now publishes under `agex-cli` (canonical), `agent-devex`, and `devex-cli`; version resolution and the publish matrices cover all three.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- Repo renamed `agentculture/agex-cli` → `agentculture/devex`; updated in-code issue/repo URLs, README, CLAUDE.md, and the publish workflow OIDC setup notes.
|
|
31
|
+
- SonarCloud project key → `agentculture_devex` (display name `devex`; organization unchanged).
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- "Output follows invocation" now also covers **plain-string** stdout/stderr in command scripts (`explain`/`learn`/`hook`/`doctor`/`gamify`/`pr delta`/`pr reply` error prefixes, status lines, and command examples), not just Jinja-rendered templates — added `core.prog.error_prefix()` and routed those paths through `prog_name()` (agex-cli#61 Qodo review).
|
|
36
|
+
- `prog_name()` now strips entry-point wrapper suffixes (`.exe`, `.py`, `-script`) before matching, so a real `devex` invocation via the Windows console script `devex.exe` no longer falls back to `agex` (agex-cli#61 Qodo review).
|
|
37
|
+
|
|
10
38
|
## [0.22.0] - 2026-05-25
|
|
11
39
|
|
|
12
40
|
### Added
|
|
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
|
4
4
|
|
|
5
5
|
## Project
|
|
6
6
|
|
|
7
|
-
`agex` — non-agentic Python CLI that emits deterministic per-backend markdown briefings for autonomous agents. PyPI distribution
|
|
7
|
+
`agex` — non-agentic Python CLI that emits deterministic per-backend markdown briefings for autonomous agents. Published on PyPI under three distribution names: `agex-cli` (canonical), `agent-devex`, and `devex-cli` — the same wheel each time. CLI entry points: `agex` and `devex` (both invoke the same tool; emitted output reflects whichever name was typed). GitHub repo: `agentculture/devex`. Python module (unchanged): `agent_experience`.
|
|
8
8
|
|
|
9
9
|
**Source-of-truth documents:**
|
|
10
10
|
|
|
@@ -19,7 +19,7 @@ Read the spec before any non-trivial change — the design invariants below are
|
|
|
19
19
|
1. **Zero LLM calls inside agex.** All output is deterministic markdown from Jinja templates + Python.
|
|
20
20
|
2. **Markdown is the only output format.** No `--json` flag.
|
|
21
21
|
3. **`--agent <backend>` is required** on backend-sensitive commands. The CLI never auto-detects.
|
|
22
|
-
4. **Side effects only in** `gamify`, `gamify --uninstall`, `hook write`, `pr open`, `pr reply`, `pr read` (journal writes), and first-run `.agex/` init. Everything else is read-only. The `agex pr` namespace allows scoped network I/O (via `gh`) and bounded `--wait` sleep — a deliberate carve-out from the no-network/no-sleep invariants.
|
|
22
|
+
4. **Side effects only in** `gamify`, `gamify --uninstall`, `hook write`, `pr open`, `pr reply`, `pr review`, `pr read` (journal writes), and first-run `.agex/` init. Everything else is read-only. The `agex pr` namespace allows scoped network I/O (via `gh`) and bounded `--wait` sleep — a deliberate carve-out from the no-network/no-sleep invariants.
|
|
23
23
|
5. **"Unsupported" is success** — exit 0 with a markdown notice that links to the issue tracker, not a non-zero exit.
|
|
24
24
|
6. **Skills are authored by the agent, not shipped by agex.** `agex learn <topic>` teaches; `agex explain <topic>` describes; agex never writes a user skill file on the agent's behalf in v0.1.
|
|
25
25
|
|
|
@@ -43,7 +43,7 @@ cli.py ──► commands/<name>/scripts/<name>.py ──► core/render.py
|
|
|
43
43
|
|
|
44
44
|
## `agex pr` namespace (v0.17.0+)
|
|
45
45
|
|
|
46
|
-
`lint`, `open`, `read`, `reply`, `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. Key modules:
|
|
46
|
+
`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`. Key modules:
|
|
47
47
|
|
|
48
48
|
- `core/github.py` — thin `gh` shellout wrapper; future zero-trust httpx swap touches only this file.
|
|
49
49
|
- `core/journal.py` — nested-stream JSONL append/load for `.agex/data/<dir>/<stream>.jsonl`.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agex-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.24.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/agex/
|
|
6
|
-
Project-URL: Repository, https://github.com/agentculture/
|
|
7
|
-
Project-URL: Issues, https://github.com/agentculture/
|
|
6
|
+
Project-URL: Repository, https://github.com/agentculture/devex
|
|
7
|
+
Project-URL: Issues, https://github.com/agentculture/devex/issues
|
|
8
8
|
Author: Ori Nachum
|
|
9
9
|
License: MIT
|
|
10
10
|
License-File: LICENSE
|
|
@@ -26,14 +26,14 @@ Description-Content-Type: text/markdown
|
|
|
26
26
|
|
|
27
27
|
# agex
|
|
28
28
|
|
|
29
|
-
Agent-operated developer-experience CLI. Non-agentic, deterministic, markdown-first.
|
|
29
|
+
Agent-operated developer-experience CLI. Non-agentic, deterministic, markdown-first. The same wheel is published on PyPI under three distribution names — `agex-cli` (canonical), `agent-devex`, and `devex-cli` — and installs two equivalent commands, `agex` and `devex` (emitted output reflects whichever name you invoke).
|
|
30
30
|
|
|
31
31
|
## Install
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
uv tool install agex-cli
|
|
34
|
+
uv tool install agex-cli # or: devex-cli
|
|
35
35
|
# or
|
|
36
|
-
pipx install agex-cli
|
|
36
|
+
pipx install agex-cli # or: pipx install devex-cli
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
## Quick start
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# agex
|
|
2
|
+
|
|
3
|
+
Agent-operated developer-experience CLI. Non-agentic, deterministic, markdown-first. The same wheel is published on PyPI under three distribution names — `agex-cli` (canonical), `agent-devex`, and `devex-cli` — and installs two equivalent commands, `agex` and `devex` (emitted output reflects whichever name you invoke).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv tool install agex-cli # or: devex-cli
|
|
9
|
+
# or
|
|
10
|
+
pipx install agex-cli # or: pipx install devex-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
agex explain agex
|
|
17
|
+
agex overview --agent claude-code
|
|
18
|
+
agex learn --agent claude-code
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Docs
|
|
22
|
+
|
|
23
|
+
[culture.dev/agex](https://culture.dev/agex/).
|
|
24
|
+
|
|
25
|
+
Spec: `docs/superpowers/specs/2026-04-18-agex-design.md`.
|
|
26
|
+
|
|
27
|
+
## License
|
|
28
|
+
|
|
29
|
+
MIT.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "agex-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.24.0"
|
|
4
4
|
description = "Agent-operated developer-experience CLI — deterministic per-backend markdown briefings for autonomous agents."
|
|
5
5
|
authors = [{name = "Ori Nachum"}]
|
|
6
6
|
license = {text = "MIT"}
|
|
@@ -27,11 +27,12 @@ dev = [
|
|
|
27
27
|
|
|
28
28
|
[project.scripts]
|
|
29
29
|
agex = "agent_experience.cli:_main_entrypoint"
|
|
30
|
+
devex = "agent_experience.cli:_main_entrypoint"
|
|
30
31
|
|
|
31
32
|
[project.urls]
|
|
32
33
|
Homepage = "https://culture.dev/agex/"
|
|
33
|
-
Repository = "https://github.com/agentculture/
|
|
34
|
-
Issues = "https://github.com/agentculture/
|
|
34
|
+
Repository = "https://github.com/agentculture/devex"
|
|
35
|
+
Issues = "https://github.com/agentculture/devex/issues"
|
|
35
36
|
|
|
36
37
|
[build-system]
|
|
37
38
|
requires = ["hatchling"]
|
|
@@ -2,13 +2,14 @@ from importlib.metadata import PackageNotFoundError, version
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
def _resolve_version() -> str:
|
|
5
|
-
# `agex-cli` is the canonical PyPI distribution name; `agent-devex`
|
|
6
|
-
# alias
|
|
7
|
-
# Whichever one is installed, surface its metadata
|
|
8
|
-
# fallback for unbuilt source checkouts (no installed
|
|
9
|
-
# read the version directly from the repo's pyproject.toml
|
|
10
|
-
# stays single-sourced from pyproject.toml in every
|
|
11
|
-
|
|
5
|
+
# `agex-cli` is the canonical PyPI distribution name; `agent-devex` and
|
|
6
|
+
# `devex-cli` are alias distributions that ship the identical wheel under
|
|
7
|
+
# different names. Whichever one is installed, surface its metadata
|
|
8
|
+
# version. As a final fallback for unbuilt source checkouts (no installed
|
|
9
|
+
# dist metadata), read the version directly from the repo's pyproject.toml
|
|
10
|
+
# so the version stays single-sourced from pyproject.toml in every
|
|
11
|
+
# reachable code path.
|
|
12
|
+
for dist in ("agex-cli", "agent-devex", "devex-cli"):
|
|
12
13
|
try:
|
|
13
14
|
return version(dist)
|
|
14
15
|
except PackageNotFoundError:
|
|
@@ -27,12 +27,18 @@ from agent_experience.commands.pr.scripts import lint as pr_lint_script
|
|
|
27
27
|
from agent_experience.commands.pr.scripts import open_ as pr_open_script
|
|
28
28
|
from agent_experience.commands.pr.scripts import read as pr_read_script
|
|
29
29
|
from agent_experience.commands.pr.scripts import reply as pr_reply_script
|
|
30
|
+
from agent_experience.commands.pr.scripts import review as pr_review_script
|
|
30
31
|
from agent_experience.core.backend import parse_backend
|
|
32
|
+
from agent_experience.core.prog import prog_name
|
|
31
33
|
|
|
32
|
-
_GH_RERUN_HINT = "agex: rerun once network is reachable (gh failed)"
|
|
33
34
|
_AGENT_HELP = "Backend: claude-code, codex, copilot, or acp."
|
|
34
35
|
|
|
35
36
|
|
|
37
|
+
def _gh_rerun_hint() -> str:
|
|
38
|
+
"""``<prog>: rerun once network is reachable`` — phrased with the invoked name."""
|
|
39
|
+
return f"{prog_name()}: rerun once network is reachable (gh failed)"
|
|
40
|
+
|
|
41
|
+
|
|
36
42
|
class _AgexArgumentParser(argparse.ArgumentParser):
|
|
37
43
|
"""ArgumentParser used everywhere via ``parser_class=``.
|
|
38
44
|
|
|
@@ -71,7 +77,7 @@ def _parse_backend_or_report(agent: Optional[str]):
|
|
|
71
77
|
try:
|
|
72
78
|
return parse_backend(agent), None
|
|
73
79
|
except ValueError as exc:
|
|
74
|
-
print(f"
|
|
80
|
+
print(f"{prog_name()}: error: {exc}", file=sys.stderr)
|
|
75
81
|
return None, 2
|
|
76
82
|
|
|
77
83
|
|
|
@@ -156,7 +162,7 @@ def _cmd_pr_lint(args: argparse.Namespace) -> int:
|
|
|
156
162
|
agent=args.agent, project_dir=Path.cwd(), exit_on_violation=args.exit_on_violation
|
|
157
163
|
)
|
|
158
164
|
except ValueError as exc:
|
|
159
|
-
print(f"
|
|
165
|
+
print(f"{prog_name()}: {exc}", file=sys.stderr)
|
|
160
166
|
return 2
|
|
161
167
|
_emit(stdout, stderr)
|
|
162
168
|
return exit_code
|
|
@@ -173,11 +179,12 @@ def _cmd_pr_open(args: argparse.Namespace) -> int:
|
|
|
173
179
|
delayed_read=args.delayed_read,
|
|
174
180
|
)
|
|
175
181
|
except ValueError as exc:
|
|
176
|
-
print(f"
|
|
182
|
+
print(f"{prog_name()}: {exc}", file=sys.stderr)
|
|
177
183
|
return 2
|
|
178
184
|
except RuntimeError as exc:
|
|
185
|
+
prog = prog_name()
|
|
179
186
|
print(str(exc), file=sys.stderr)
|
|
180
|
-
print("
|
|
187
|
+
print(f"{prog}: rerun '{prog} pr open ...' once network is reachable", file=sys.stderr)
|
|
181
188
|
return 1
|
|
182
189
|
_emit(stdout, stderr)
|
|
183
190
|
return exit_code
|
|
@@ -189,11 +196,11 @@ def _cmd_pr_reply(args: argparse.Namespace) -> int:
|
|
|
189
196
|
agent=args.agent, project_dir=Path.cwd(), pr=args.pr
|
|
190
197
|
)
|
|
191
198
|
except ValueError as exc:
|
|
192
|
-
print(f"
|
|
199
|
+
print(f"{prog_name()}: {exc}", file=sys.stderr)
|
|
193
200
|
return 2
|
|
194
201
|
except RuntimeError as exc:
|
|
195
202
|
print(str(exc), file=sys.stderr)
|
|
196
|
-
print(
|
|
203
|
+
print(_gh_rerun_hint(), file=sys.stderr)
|
|
197
204
|
return 1
|
|
198
205
|
_emit(stdout, stderr, stderr_newline=False)
|
|
199
206
|
return exit_code
|
|
@@ -205,11 +212,11 @@ def _cmd_pr_read(args: argparse.Namespace) -> int:
|
|
|
205
212
|
agent=args.agent, project_dir=Path.cwd(), pr=args.pr, wait=args.wait
|
|
206
213
|
)
|
|
207
214
|
except ValueError as exc:
|
|
208
|
-
print(f"
|
|
215
|
+
print(f"{prog_name()}: {exc}", file=sys.stderr)
|
|
209
216
|
return 2
|
|
210
217
|
except RuntimeError as exc:
|
|
211
218
|
print(str(exc), file=sys.stderr)
|
|
212
|
-
print(
|
|
219
|
+
print(_gh_rerun_hint(), file=sys.stderr)
|
|
213
220
|
return 1
|
|
214
221
|
_emit(stdout, stderr)
|
|
215
222
|
return exit_code
|
|
@@ -221,11 +228,27 @@ def _cmd_pr_await(args: argparse.Namespace) -> int:
|
|
|
221
228
|
agent=args.agent, project_dir=Path.cwd(), pr=args.pr, max_wait=args.max_wait
|
|
222
229
|
)
|
|
223
230
|
except ValueError as exc:
|
|
224
|
-
print(f"
|
|
231
|
+
print(f"{prog_name()}: {exc}", file=sys.stderr)
|
|
232
|
+
return 2
|
|
233
|
+
except RuntimeError as exc:
|
|
234
|
+
print(str(exc), file=sys.stderr)
|
|
235
|
+
print(_gh_rerun_hint(), file=sys.stderr)
|
|
236
|
+
return 1
|
|
237
|
+
_emit(stdout, stderr)
|
|
238
|
+
return exit_code
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def _cmd_pr_review(args: argparse.Namespace) -> int:
|
|
242
|
+
try:
|
|
243
|
+
stdout, exit_code, stderr = pr_review_script.run(
|
|
244
|
+
agent=args.agent, project_dir=Path.cwd(), pr=args.pr
|
|
245
|
+
)
|
|
246
|
+
except ValueError as exc:
|
|
247
|
+
print(f"{prog_name()}: {exc}", file=sys.stderr)
|
|
225
248
|
return 2
|
|
226
249
|
except RuntimeError as exc:
|
|
227
250
|
print(str(exc), file=sys.stderr)
|
|
228
|
-
print(
|
|
251
|
+
print(_gh_rerun_hint(), file=sys.stderr)
|
|
229
252
|
return 1
|
|
230
253
|
_emit(stdout, stderr)
|
|
231
254
|
return exit_code
|
|
@@ -235,11 +258,11 @@ def _cmd_pr_delta(args: argparse.Namespace) -> int:
|
|
|
235
258
|
try:
|
|
236
259
|
stdout, exit_code, stderr = pr_delta_script.run(agent=args.agent, project_dir=Path.cwd())
|
|
237
260
|
except ValueError as exc:
|
|
238
|
-
print(f"
|
|
261
|
+
print(f"{prog_name()}: {exc}", file=sys.stderr)
|
|
239
262
|
return 2
|
|
240
263
|
except RuntimeError as exc:
|
|
241
264
|
print(str(exc), file=sys.stderr)
|
|
242
|
-
print(
|
|
265
|
+
print(_gh_rerun_hint(), file=sys.stderr)
|
|
243
266
|
return 1
|
|
244
267
|
_emit(stdout, stderr, stderr_newline=False)
|
|
245
268
|
return exit_code
|
|
@@ -270,7 +293,7 @@ def _group_help(parser: argparse.ArgumentParser):
|
|
|
270
293
|
|
|
271
294
|
def _build_parser() -> argparse.ArgumentParser:
|
|
272
295
|
parser = _AgexArgumentParser(
|
|
273
|
-
prog=
|
|
296
|
+
prog=prog_name(),
|
|
274
297
|
description="Agent-operated developer-experience CLI.",
|
|
275
298
|
)
|
|
276
299
|
parser.add_argument("--version", action="version", version=__version__)
|
|
@@ -397,6 +420,14 @@ def _register_pr(sub: argparse._SubParsersAction) -> None:
|
|
|
397
420
|
_add_agent_option(p_await, required=False, help_text=_AGENT_HELP)
|
|
398
421
|
p_await.set_defaults(func=_cmd_pr_await)
|
|
399
422
|
|
|
423
|
+
p_review = pr_sub.add_parser(
|
|
424
|
+
"review",
|
|
425
|
+
help="Post the Qodo agentic-review trigger (/agentic_review) on a PR.",
|
|
426
|
+
)
|
|
427
|
+
p_review.add_argument("pr", type=int, nargs="?", default=None)
|
|
428
|
+
_add_agent_option(p_review, required=False, help_text=_AGENT_HELP)
|
|
429
|
+
p_review.set_defaults(func=_cmd_pr_review)
|
|
430
|
+
|
|
400
431
|
p_delta = pr_sub.add_parser("delta", help="Show the delta since the last PR read.")
|
|
401
432
|
_add_agent_option(p_delta, required=False, help_text=_AGENT_HELP)
|
|
402
433
|
p_delta.set_defaults(func=_cmd_pr_delta)
|
|
@@ -441,7 +472,9 @@ def _main_entrypoint() -> None:
|
|
|
441
472
|
"""
|
|
442
473
|
argv = sys.argv[1:]
|
|
443
474
|
if argv and not argv[0].startswith("-") and argv[0] not in _KNOWN_COMMANDS:
|
|
444
|
-
print(f"
|
|
475
|
+
print(f"{prog_name()}: error: unknown command '{argv[0]}'", file=sys.stderr)
|
|
476
|
+
# `agex` here is the explain-topic identifier (topics/agex.md), not the
|
|
477
|
+
# invoked command name — the canonical "what is this tool" page.
|
|
445
478
|
stdout, _, _ = explain_script.run("agex")
|
|
446
479
|
sys.stdout.write(stdout)
|
|
447
480
|
sys.exit(2)
|
|
@@ -24,6 +24,7 @@ from agent_experience.core.paths import (
|
|
|
24
24
|
config_path,
|
|
25
25
|
data_dir,
|
|
26
26
|
)
|
|
27
|
+
from agent_experience.core.prog import error_prefix
|
|
27
28
|
from agent_experience.core.render import render_string
|
|
28
29
|
from agent_experience.core.skill_loader import load_skill
|
|
29
30
|
|
|
@@ -74,8 +75,8 @@ def _check_version() -> CheckResult:
|
|
|
74
75
|
_NAME_AGEX_VERSION,
|
|
75
76
|
"fail",
|
|
76
77
|
"Could not resolve `agent_experience.__version__`. Reinstall with "
|
|
77
|
-
"`uv pip install -e .[dev]`, `pipx install agex-cli`,
|
|
78
|
-
"`pipx install agent-devex`.",
|
|
78
|
+
"`uv pip install -e .[dev]`, `pipx install agex-cli`, "
|
|
79
|
+
"`pipx install agent-devex`, or `pipx install devex-cli`.",
|
|
79
80
|
)
|
|
80
81
|
return CheckResult(_NAME_AGEX_VERSION, "ok", __version__)
|
|
81
82
|
|
|
@@ -341,24 +342,24 @@ def run(role: str | None = None) -> tuple[str, int, str]:
|
|
|
341
342
|
Read-only. Never initializes ``.agex/``.
|
|
342
343
|
"""
|
|
343
344
|
if role is not None and _ROLE_RE.match(role) is None:
|
|
344
|
-
return ("", 2, f"
|
|
345
|
+
return ("", 2, error_prefix(f"invalid role slug '{role}'"))
|
|
345
346
|
|
|
346
347
|
role_section: str | None = None
|
|
347
348
|
if role is not None:
|
|
348
349
|
trav = _resolve_role(role)
|
|
349
350
|
if trav is None:
|
|
350
|
-
return ("", 2, f"
|
|
351
|
+
return ("", 2, error_prefix(f"unknown role '{role}'"))
|
|
351
352
|
try:
|
|
352
353
|
role_text = trav.read_text(encoding="utf-8")
|
|
353
354
|
except (OSError, UnicodeDecodeError) as exc:
|
|
354
|
-
return ("", 1, f"
|
|
355
|
+
return ("", 1, error_prefix(f"could not read role asset for '{role}': {exc}"))
|
|
355
356
|
# Role assets are Jinja templates per the addendum spec; v0.1 passes
|
|
356
357
|
# an empty context but rendering still resolves any `{% raw %}` /
|
|
357
358
|
# `{{ }}` markup the role file may use, rather than dumping it raw.
|
|
358
359
|
try:
|
|
359
360
|
role_section = render_string(role_text, {})
|
|
360
361
|
except Exception as exc:
|
|
361
|
-
return ("", 1, f"
|
|
362
|
+
return ("", 1, error_prefix(f"failed to render role '{role}': {exc}"))
|
|
362
363
|
|
|
363
364
|
categories = _build_categories()
|
|
364
365
|
summary = _summarize(categories)
|
|
@@ -369,8 +370,10 @@ def run(role: str | None = None) -> tuple[str, int, str]:
|
|
|
369
370
|
return (
|
|
370
371
|
"",
|
|
371
372
|
1,
|
|
372
|
-
|
|
373
|
-
|
|
373
|
+
error_prefix(
|
|
374
|
+
f"could not read `doctor/assets/report.md.j2`: {exc}. "
|
|
375
|
+
"Reinstall the package."
|
|
376
|
+
),
|
|
374
377
|
)
|
|
375
378
|
out = render_string(
|
|
376
379
|
template_text,
|
|
@@ -386,6 +389,6 @@ def run(role: str | None = None) -> tuple[str, int, str]:
|
|
|
386
389
|
)
|
|
387
390
|
|
|
388
391
|
if summary["fail"] > 0:
|
|
389
|
-
stderr = f"
|
|
392
|
+
stderr = error_prefix(f"{summary['fail']} health check(s) failed")
|
|
390
393
|
return (out, 1, stderr)
|
|
391
394
|
return (out, 0, "")
|
{agex_cli-0.22.0 → agex_cli-0.24.0}/src/agent_experience/commands/explain/scripts/explain.py
RENAMED
|
@@ -2,6 +2,7 @@ import re
|
|
|
2
2
|
from importlib.resources import files
|
|
3
3
|
from importlib.resources.abc import Traversable
|
|
4
4
|
|
|
5
|
+
from agent_experience.core.prog import error_prefix
|
|
5
6
|
from agent_experience.core.skill_loader import Skill, load_skill
|
|
6
7
|
|
|
7
8
|
_TOPIC_RE = re.compile(r"^[a-z][a-z0-9-]*$")
|
|
@@ -54,7 +55,7 @@ def run(topic: str) -> tuple[str, int, str]:
|
|
|
54
55
|
if resolved is None:
|
|
55
56
|
agex_page = _commands_root().joinpath("explain", "assets", "topics", "agex.md")
|
|
56
57
|
body = agex_page.read_text(encoding="utf-8") if agex_page.is_file() else ""
|
|
57
|
-
return (body, 2, f"
|
|
58
|
+
return (body, 2, error_prefix(f"unknown topic '{topic}'"))
|
|
58
59
|
|
|
59
60
|
kind, trav = resolved
|
|
60
61
|
if kind == "concept":
|
|
@@ -8,6 +8,7 @@ from agent_experience.core.backend import Backend
|
|
|
8
8
|
from agent_experience.core.config import load as load_config
|
|
9
9
|
from agent_experience.core.config import save as save_config
|
|
10
10
|
from agent_experience.core.paths import ensure_init
|
|
11
|
+
from agent_experience.core.prog import error_prefix, prog_name
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
def _fragments_file() -> Traversable:
|
|
@@ -110,7 +111,7 @@ def install(backend: Backend) -> tuple[str, int, str]:
|
|
|
110
111
|
try:
|
|
111
112
|
hooks = _load_hooks_file(hooks_file)
|
|
112
113
|
except ValueError as e:
|
|
113
|
-
return ("", 2,
|
|
114
|
+
return ("", 2, error_prefix(str(e)))
|
|
114
115
|
|
|
115
116
|
written_ids, added_count = _merge_fragments(hooks, fragments)
|
|
116
117
|
if added_count:
|
|
@@ -142,7 +143,8 @@ def install(backend: Backend) -> tuple[str, int, str]:
|
|
|
142
143
|
status_line,
|
|
143
144
|
"- Fragment IDs: " + ", ".join(f"`{i}`" for i in written_ids),
|
|
144
145
|
"",
|
|
145
|
-
f"Next: run `
|
|
146
|
+
f"Next: run `{prog_name()} learn gamify --agent {backend.value}`"
|
|
147
|
+
" to set up the levelup skill.",
|
|
146
148
|
"",
|
|
147
149
|
]
|
|
148
150
|
return ("\n".join(lines), 0, "")
|
|
@@ -176,7 +178,7 @@ def uninstall(backend: Backend) -> tuple[str, int, str]:
|
|
|
176
178
|
try:
|
|
177
179
|
hooks = _load_hooks_file(hooks_file)
|
|
178
180
|
except ValueError as e:
|
|
179
|
-
return ("", 2,
|
|
181
|
+
return ("", 2, error_prefix(str(e)))
|
|
180
182
|
|
|
181
183
|
removed_count = _remove_ids_from_hooks(hooks, ids_to_remove)
|
|
182
184
|
if removed_count:
|
|
@@ -196,6 +198,6 @@ def _unsupported_notice(backend: Backend) -> str:
|
|
|
196
198
|
return (
|
|
197
199
|
f"## `gamify` is not supported on {backend.value}\n\n"
|
|
198
200
|
f"Hooks are required to track usage events, and {backend.value} does not expose "
|
|
199
|
-
f"a hook interface
|
|
200
|
-
"Want this supported? Open an issue: <https://github.com/agentculture/
|
|
201
|
+
f"a hook interface {prog_name()} can write to.\n\n"
|
|
202
|
+
"Want this supported? Open an issue: <https://github.com/agentculture/devex/issues>\n"
|
|
201
203
|
)
|
|
@@ -2,6 +2,7 @@ from datetime import datetime, timezone
|
|
|
2
2
|
|
|
3
3
|
from agent_experience.core.hook_io import append_event
|
|
4
4
|
from agent_experience.core.paths import ensure_init
|
|
5
|
+
from agent_experience.core.prog import error_prefix
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
def run(event: str, args: list[str]) -> tuple[str, int, str]:
|
|
@@ -20,5 +21,5 @@ def run(event: str, args: list[str]) -> tuple[str, int, str]:
|
|
|
20
21
|
except ValueError as e:
|
|
21
22
|
# append_event → _stream_path rejects names that don't match the
|
|
22
23
|
# `^[a-z][a-z0-9-]*$` slug whitelist (path-traversal guard).
|
|
23
|
-
return ("", 2,
|
|
24
|
+
return ("", 2, error_prefix(str(e)))
|
|
24
25
|
return ("", 0, "")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Lessons — {{ backend }}
|
|
2
2
|
|
|
3
|
-
Run `
|
|
3
|
+
Run `{{ prog }} learn <topic> --agent {{ backend }}` to learn one.
|
|
4
4
|
|
|
5
5
|
{% for topic in topics -%}
|
|
6
6
|
- **`{{ topic.name }}`** — {{ topic.description }}{% if topic.unsupported %} _(unsupported on {{ backend }}: {{ topic.unsupported }})_{% endif %}
|
|
@@ -3,6 +3,7 @@ from importlib.resources import as_file, files
|
|
|
3
3
|
from importlib.resources.abc import Traversable
|
|
4
4
|
|
|
5
5
|
from agent_experience.core.backend import Backend
|
|
6
|
+
from agent_experience.core.prog import error_prefix
|
|
6
7
|
from agent_experience.core.render import render_string
|
|
7
8
|
from agent_experience.core.skill_loader import Skill, load_skill
|
|
8
9
|
|
|
@@ -54,13 +55,13 @@ def run_topic(topic: str, backend: Backend) -> tuple[str, int, str]:
|
|
|
54
55
|
"""Return (stdout, exit_code, stderr) for a specific lesson topic."""
|
|
55
56
|
if not _TOPIC_RE.match(topic):
|
|
56
57
|
menu_out, _, _ = run_menu(backend)
|
|
57
|
-
return (menu_out, 2, f"
|
|
58
|
+
return (menu_out, 2, error_prefix(f"unknown topic '{topic}'"))
|
|
58
59
|
|
|
59
60
|
topic_dir = _learn_assets().joinpath("topics", topic)
|
|
60
61
|
skill_md = topic_dir.joinpath(_SKILL_FILENAME)
|
|
61
62
|
if not skill_md.is_file():
|
|
62
63
|
menu_out, _, _ = run_menu(backend)
|
|
63
|
-
return (menu_out, 2, f"
|
|
64
|
+
return (menu_out, 2, error_prefix(f"unknown topic '{topic}'"))
|
|
64
65
|
|
|
65
66
|
skill = _load_skill_from_traversable(skill_md)
|
|
66
67
|
template_path = topic_dir.joinpath("assets", "skill-template", backend.value, _SKILL_FILENAME)
|