agex-cli 0.25.0__tar.gz → 0.26.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.github/workflows/publish.yml +5 -4
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.github/workflows/test.yml +41 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.gitignore +1 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/CHANGELOG.md +21 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/CLAUDE.md +24 -23
- {agex_cli-0.25.0 → agex_cli-0.26.1}/PKG-INFO +10 -10
- agex_cli-0.26.1/README.md +29 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/culture.yaml +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.1}/pyproject.toml +21 -6
- {agex_cli-0.25.0 → agex_cli-0.26.1}/sonar-project.properties +11 -12
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/__init__.py +5 -4
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/__main__.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/acp/probe.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/capabilities/codex.yaml +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/capabilities/copilot.yaml +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/claude_code/probe.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/codex/probe.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/copilot/probe.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/cli.py +65 -32
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/doctor/SKILL.md +9 -9
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/doctor/references/design.md +5 -5
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/doctor/scripts/doctor.py +34 -35
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/explain/SKILL.md +7 -7
- agex_cli-0.26.1/src/devex/commands/explain/assets/topics/devex.md +39 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/explain/scripts/explain.py +11 -5
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/gamify/SKILL.md +7 -7
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/gamify/scripts/install.py +6 -6
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/hook/SKILL.md +6 -6
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/hook/scripts/read.py +6 -6
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/hook/scripts/write.py +3 -3
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/learn/SKILL.md +3 -3
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/learn/assets/topics/cicd/SKILL.md +13 -13
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/learn/assets/topics/gamify/SKILL.md +5 -5
- {agex_cli-0.25.0/src/agent_experience/commands/learn/assets/topics/levelup → agex_cli-0.26.1/src/devex/commands/learn/assets/topics/gamify}/assets/skill-template/claude-code/SKILL.md +3 -3
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/learn/assets/topics/introspect/SKILL.md +3 -3
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/learn/assets/topics/introspect/assets/skill-template/claude-code/SKILL.md +1 -1
- agex_cli-0.26.1/src/devex/commands/learn/assets/topics/levelup/SKILL.md +31 -0
- {agex_cli-0.25.0/src/agent_experience/commands/learn/assets/topics/gamify → agex_cli-0.26.1/src/devex/commands/learn/assets/topics/levelup}/assets/skill-template/claude-code/SKILL.md +3 -3
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/learn/assets/topics/visualize/SKILL.md +2 -2
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/learn/assets/topics/visualize/assets/skill-template/claude-code/SKILL.md +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/learn/scripts/learn.py +6 -6
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/overview/SKILL.md +5 -5
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/overview/scripts/overview.py +8 -8
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/SKILL.md +45 -17
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/backends/acp.yaml +4 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/backends/claude-code.yaml +4 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/backends/codex.yaml +4 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/backends/copilot.yaml +4 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/rules/lint_rules.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/rules/next_step_rules.py +15 -1
- agex_cli-0.26.1/src/devex/commands/pr/assets/templates/pr_await_detached.md.j2 +29 -0
- agex_cli-0.26.1/src/devex/commands/pr/scripts/_await_worker.py +109 -0
- agex_cli-0.26.1/src/devex/commands/pr/scripts/_detach.py +129 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/scripts/_footer.py +5 -5
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/scripts/_journal.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/scripts/_qodo.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/scripts/_readiness.py +4 -6
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/scripts/_sonar.py +3 -3
- agex_cli-0.26.1/src/devex/commands/pr/scripts/await_.py +395 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/scripts/delta.py +8 -8
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/scripts/lint.py +7 -7
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/scripts/open_.py +21 -9
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/scripts/read.py +8 -8
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/scripts/reply.py +9 -9
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/scripts/review.py +9 -9
- agex_cli-0.25.0/src/agent_experience/core/hook_io.py → agex_cli-0.26.1/src/devex/core/_jsonl.py +23 -35
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/core/capabilities.py +1 -1
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/core/config.py +2 -2
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/core/github.py +2 -2
- agex_cli-0.26.1/src/devex/core/hook_io.py +46 -0
- agex_cli-0.26.1/src/devex/core/journal.py +39 -0
- agex_cli-0.26.1/src/devex/core/paths.py +50 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/core/prog.py +8 -8
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/core/render.py +1 -1
- agex_cli-0.26.1/tester-agents/claude/.claude/skills +1 -0
- agex_cli-0.26.1/tester-agents/claude/CLAUDE.md +30 -0
- agex_cli-0.26.1/tester-agents/claude/README.md +23 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tester-agents/claude/culture.yaml +5 -5
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/backends/test_claude_code_probe.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/backends/test_stub_probes.py +3 -3
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/fixtures/gh/qodo_summary_comment.html +3 -3
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/test_await.py +5 -5
- agex_cli-0.26.1/tests/commands/pr/test_await_detach.py +298 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/test_delta.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/test_deploy.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/test_footer.py +9 -7
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/test_lint.py +4 -4
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/test_lint_rules.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/test_open.py +71 -12
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/test_qodo.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/test_read.py +8 -8
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/test_readiness.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/test_reply.py +8 -8
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/test_review.py +5 -5
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/test_doctor.py +28 -28
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/test_explain.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/test_gamify.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/test_hook.py +8 -8
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/test_learn.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/test_overview.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/test_prog_propagation.py +6 -5
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/core/test_backend.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/core/test_capabilities.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/core/test_config.py +3 -3
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/core/test_github.py +5 -5
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/core/test_hook_io.py +13 -12
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/core/test_journal.py +4 -4
- agex_cli-0.26.1/tests/core/test_paths.py +59 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/core/test_prog.py +4 -4
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/core/test_render.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/core/test_resolve_backend.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/core/test_skill_loader.py +1 -1
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/core/test_version_lookup.py +11 -15
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/test_cli_dispatch.py +4 -4
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/test_cli_errors.py +9 -9
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/test_cli_smoke.py +2 -2
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/test_skill_md_consistency.py +8 -9
- {agex_cli-0.25.0 → agex_cli-0.26.1}/uv.lock +1 -1
- agex_cli-0.25.0/README.md +0 -29
- agex_cli-0.25.0/src/agent_experience/commands/explain/assets/topics/agex.md +0 -37
- agex_cli-0.25.0/src/agent_experience/commands/learn/assets/topics/levelup/SKILL.md +0 -31
- agex_cli-0.25.0/src/agent_experience/commands/pr/scripts/await_.py +0 -168
- agex_cli-0.25.0/src/agent_experience/core/journal.py +0 -90
- agex_cli-0.25.0/src/agent_experience/core/paths.py +0 -26
- agex_cli-0.25.0/tester-agents/claude/CLAUDE.md +0 -30
- agex_cli-0.25.0/tester-agents/claude/README.md +0 -23
- agex_cli-0.25.0/tests/core/test_paths.py +0 -31
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/agent-config/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/agent-config/data/backend-fingerprints.yaml +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/agent-config/scripts/show.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/assign-to-workforce/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/cicd/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/cicd/scripts/workflow.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/communicate/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/run-tests/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/sonarclaude/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/spec-to-plan/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/think/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/think/scripts/think.sh +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/version-bump/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.claude/skills/version-bump/scripts/bump.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.flake8 +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/.python-version +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/LICENSE +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/docs/skill-sources.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/docs/superpowers/plans/2026-04-18-agex-v0.1.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/docs/superpowers/plans/2026-05-10-agex-pr.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/docs/superpowers/specs/2026-04-18-agex-design.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/docs/superpowers/specs/2026-04-26-agex-doctor.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/docs/superpowers/specs/2026-05-10-agex-pr-design.md +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/acp/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/capabilities/acp.yaml +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/capabilities/claude-code.yaml +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/claude_code/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/codex/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/copilot/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/doctor/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/doctor/assets/report.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/doctor/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/explain/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/explain/references/.gitkeep +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/explain/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/gamify/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/gamify/assets/hooks/claude-code.json +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/gamify/references/.gitkeep +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/gamify/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/hook/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/hook/assets/table.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/hook/references/.gitkeep +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/hook/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/learn/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/learn/assets/menu.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/learn/references/.gitkeep +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/learn/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/overview/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/overview/assets/backends/acp.yaml +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/overview/assets/backends/claude-code.yaml +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/overview/assets/backends/codex.yaml +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/overview/assets/backends/copilot.yaml +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/overview/assets/sections.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/overview/references/.gitkeep +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/overview/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/backends/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/rules/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/templates/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/templates/delta.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/templates/footer.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/templates/lint_result.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/templates/pr_briefing.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/templates/pr_open_result.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/templates/pr_reply_result.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/assets/templates/pr_review_result.md.j2 +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/scripts/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/commands/pr/scripts/_deploy.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/core/__init__.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/core/backend.py +0 -0
- {agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/core/skill_loader.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tester-agents/claude/.claude/settings.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/__init__.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/backends/__init__.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/__init__.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/__init__.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/fixtures/gh/.gitkeep +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/fixtures/gh/pr_checks_42.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/fixtures/gh/pr_comments_42.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/commands/pr/fixtures/journals/dogfood_40.jsonl +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/core/__init__.py +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/fixtures/claude-code/empty/.gitkeep +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/fixtures/claude-code/malformed/.claude/hooks.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/fixtures/claude-code/malformed/.claude/settings.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/fixtures/claude-code/malformed/.claude/skills/bad/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/fixtures/claude-code/malformed/.claude/skills/broken-yaml/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/fixtures/claude-code/typical/.claude/hooks.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/fixtures/claude-code/typical/.claude/settings.json +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/fixtures/claude-code/typical/.claude/skills/example/SKILL.md +0 -0
- {agex_cli-0.25.0 → agex_cli-0.26.1}/tests/fixtures/claude-code/typical/CLAUDE.md +0 -0
|
@@ -73,8 +73,9 @@ jobs:
|
|
|
73
73
|
# because it needs to rewrite the version before building.
|
|
74
74
|
#
|
|
75
75
|
# The matrix exists so we can publish the same code under three PyPI
|
|
76
|
-
# distribution names: `
|
|
77
|
-
# `
|
|
76
|
+
# distribution names: `devex-cli` (canonical) plus the `agent-devex` and
|
|
77
|
+
# `agex-cli` aliases (`agex-cli` is the legacy canonical name, still
|
|
78
|
+
# published for back-compat). Each leg rewrites `[project].name` in pyproject.toml
|
|
78
79
|
# before building so each wheel is uploaded under its own Trusted Publishing
|
|
79
80
|
# project.
|
|
80
81
|
# --------------------------------------------------------------------------
|
|
@@ -97,9 +98,9 @@ jobs:
|
|
|
97
98
|
- run: uv venv
|
|
98
99
|
- run: uv pip install build
|
|
99
100
|
|
|
100
|
-
# Rewrite `[project].name` to the matrix dist name. For `
|
|
101
|
+
# Rewrite `[project].name` to the matrix dist name. For `devex-cli`
|
|
101
102
|
# (the canonical dist) the regex still has to match so we re-emit
|
|
102
|
-
# the line; for `agent-devex` / `
|
|
103
|
+
# the line; for `agent-devex` / `agex-cli` it produces an alias dist
|
|
103
104
|
# with identical contents. The post-rewrite re-parse is a fail-closed
|
|
104
105
|
# check: if a future formatting change breaks the regex match (or
|
|
105
106
|
# `[project].name` ends up wrong for any reason), the job aborts
|
|
@@ -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
|
|
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.26.1] - 2026-05-29
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- 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`).
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- 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.
|
|
19
|
+
|
|
20
|
+
## [0.26.0] - 2026-05-29
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **`devex pr await <PR> --detach` / `--check`** — non-blocking await (#64). `--detach` forks a detached background poller that runs the same readiness → CI → Sonar-gate → thread-tally logic, writes the verdict to a marker (`.devex/data/pr/<PR>/await.json`, atomic `os.replace`), and returns immediately — taking the in-session `time.sleep` (and the prompt-cache re-read tax past the ~5-min TTL) out of the agent's context. `--check` reads that marker back without sleeping or re-polling: the stored briefing + the same non-zero-on-blocked exit code when done, a "still polling (started Ns ago)" notice while running, and a clear notice (never a crash or false "clean") when no run exists or the marker schema is incompatible. The detached worker always leaves a marker — even on `gh` failure, and even if the spawn itself fails — so `--check` is never left hanging. The two flags are mutually exclusive. New per-backend footer keys (`await_detached`, `await_check_pending`, `await_check_missing`, `await_check_incompatible`) ship for all four backends.
|
|
25
|
+
- **`devex pr open --detached-await`** — auto-wait at open time: after creating the PR (and posting the Qodo trigger), fork the detached `pr await` poller and return immediately, so "open → walk away → `pr await <PR> --check`" is one command. The non-blocking counterpart to `--delayed-read` (the two are mutually exclusive).
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- **Renamed the tool from `agex` to `devex` end to end** — `devex` is now the canonical command, `devex-cli` the canonical PyPI distribution, and the Python module is `devex` (was `agent_experience`). The on-disk state directory is `.devex/` (was `.agex/`), with a transparent read-fallback to a pre-existing `.agex/` and a one-time migration on first write. **`agex` stays a fully working, non-breaking alias**: the `agex` console script and `agex-cli` distribution are still published, `agex` is still recognized as an invoked name, and `devex explain agex` resolves to the overview page. Kept stable for back-compat: the `agex_version` config-file key, the `agex:` gamify hook-fragment IDs, and the `agex hook write` command in the shipped hook asset.
|
|
30
|
+
|
|
10
31
|
## [0.25.0] - 2026-05-29
|
|
11
32
|
|
|
12
33
|
### Added
|
|
@@ -4,24 +4,24 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
|
4
4
|
|
|
5
5
|
## Project
|
|
6
6
|
|
|
7
|
-
`
|
|
7
|
+
`devex` — non-agentic Python CLI that emits deterministic per-backend markdown briefings for autonomous agents. Published on PyPI under three distribution names: `devex-cli` (canonical), `agent-devex`, and `agex-cli` (the legacy canonical name, still published) — the same wheel each time. CLI entry points: `devex` (canonical) and `agex` (legacy alias) — both invoke the same tool; emitted output reflects whichever name was typed. GitHub repo: `agentculture/devex`. Python module: `devex` (renamed from `agent_experience`).
|
|
8
8
|
|
|
9
9
|
**Source-of-truth documents:**
|
|
10
10
|
|
|
11
11
|
- Spec: `docs/superpowers/specs/2026-04-18-agex-design.md`
|
|
12
12
|
- Implementation plan: `docs/superpowers/plans/2026-04-18-agex-v0.1.md` — 33 tasks across 12 phases.
|
|
13
|
-
- Status: PR #1 merged Phases 1–3 (scaffolding, core, `
|
|
13
|
+
- Status: PR #1 merged Phases 1–3 (scaffolding, core, `devex explain`). Phases 4–12 (`overview`, `learn`, `gamify`, `hook`, backends, docs site, tester) remain.
|
|
14
14
|
|
|
15
15
|
Read the spec before any non-trivial change — the design invariants below are derived from it.
|
|
16
16
|
|
|
17
17
|
## Design invariants (non-negotiable)
|
|
18
18
|
|
|
19
|
-
1. **Zero LLM calls inside
|
|
19
|
+
1. **Zero LLM calls inside devex.** 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 review`, `pr read` (journal writes), and first-run `.
|
|
22
|
+
4. **Side effects only in** `gamify`, `gamify --uninstall`, `hook write`, `pr open`, `pr reply`, `pr review`, `pr read` (journal writes), `pr await` (journal + `--detach` marker writes under `.devex/data/pr/<pr>/` and the detached poller subprocess), and first-run `.devex/` init. Everything else is read-only. The `devex pr` namespace allows scoped network I/O (via `gh`), bounded `--wait` sleep, and — for `pr await --detach` — a detached background process that pays that sleep outside the agent session; 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
|
-
6. **Skills are authored by the agent, not shipped by
|
|
24
|
+
6. **Skills are authored by the agent, not shipped by devex.** `devex learn <topic>` teaches; `devex explain <topic>` describes; devex never writes a user skill file on the agent's behalf in v0.1.
|
|
25
25
|
|
|
26
26
|
## Architecture (3-stage pipeline)
|
|
27
27
|
|
|
@@ -36,17 +36,18 @@ cli.py ──► commands/<name>/scripts/<name>.py ──► core/render.py
|
|
|
36
36
|
(supported / unsupported)
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
- `cli.py` (Typer) routes `
|
|
40
|
-
- Each `commands/<name>/` is a **skill-folder**: `SKILL.md` + `scripts/` + `assets/` + `references/`. The `SKILL.md` doubles as the content emitted by `
|
|
41
|
-
- `core/` is shared plumbing — backend enum, `.
|
|
39
|
+
- `cli.py` (Typer) routes `devex <command> [args] --agent X`. No business logic.
|
|
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.
|
|
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
|
-
## `
|
|
44
|
+
## `devex pr` namespace (v0.17.0+)
|
|
45
45
|
|
|
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:
|
|
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`. `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:
|
|
47
47
|
|
|
48
48
|
- `core/github.py` — thin `gh` shellout wrapper; future zero-trust httpx swap touches only this file.
|
|
49
|
-
- `
|
|
49
|
+
- `commands/pr/scripts/_detach.py` — await-marker read/write (atomic) + the detached-subprocess spawn helper.
|
|
50
|
+
- `core/journal.py` — nested-stream JSONL append/load for `.devex/data/<dir>/<stream>.jsonl`.
|
|
50
51
|
- `core/backend.resolve_backend()` — `--agent` resolution with `culture.yaml` fallback.
|
|
51
52
|
- `commands/pr/assets/rules/next_step_rules.py` — "Next step:" footer decision logic, per-backend phrasing under `commands/pr/assets/backends/<backend>.yaml`.
|
|
52
53
|
|
|
@@ -57,8 +58,8 @@ Spec: `docs/superpowers/specs/2026-05-10-agex-pr-design.md`. Plan: `docs/superpo
|
|
|
57
58
|
- **Resource loading: use `importlib.resources.files(...)` and treat the result as a `Traversable`.** Call `.joinpath()` / `.is_file()` / `.read_text(encoding="utf-8")` directly. Wrap with `importlib.resources.as_file()` only when a third-party API needs a real `pathlib.Path`. Do NOT do `Path(str(files(...)))` — it's not zipapp/PEX safe.
|
|
58
59
|
- **File locking: use `portalocker.lock` / `portalocker.unlock`.** Reaching for `fcntl.flock` / `msvcrt.locking` directly is a known foot-gun on Windows (see commit `923f639`).
|
|
59
60
|
- **Always pass `encoding="utf-8"` to `read_text` / `write_text`.** Default locale on Windows corrupts non-ASCII output.
|
|
60
|
-
- **Validate user-controlled CLI args before joining into paths.** `
|
|
61
|
-
- **Single source of truth for the version:** `pyproject.toml`. `
|
|
61
|
+
- **Validate user-controlled CLI args before joining into paths.** `devex explain <topic>` rejects anything that doesn't match `^[a-z][a-z0-9-]*$` to block path traversal (commit `5ac796e`, test `test_explain_rejects_path_traversal`).
|
|
62
|
+
- **Single source of truth for the version:** `pyproject.toml`. `devex.__version__` derives from installed distribution metadata via `importlib.metadata.version("devex-cli")` (falling back to the `agent-devex` / `agex-cli` alias dists, then pyproject), and `Config.agex_version` derives from `__version__` via `field(default_factory=...)`. (The `agex_version` config-file key name is kept for back-compat with existing `.devex/config.toml` / `.agex/config.toml` files.) Bumping the version means editing `pyproject.toml` only — no `__init__.py` edit needed.
|
|
62
63
|
|
|
63
64
|
## Common commands
|
|
64
65
|
|
|
@@ -73,24 +74,24 @@ uv run pytest
|
|
|
73
74
|
uv run pytest tests/core/test_paths.py::test_ensure_init_creates_dir_and_gitignore -v
|
|
74
75
|
|
|
75
76
|
# Run the CLI
|
|
76
|
-
uv run
|
|
77
|
-
uv run
|
|
78
|
-
uv run
|
|
77
|
+
uv run devex --version
|
|
78
|
+
uv run devex explain devex
|
|
79
|
+
uv run devex explain explain
|
|
79
80
|
|
|
80
|
-
# Coverage (matches
|
|
81
|
-
uv run pytest --cov=src/
|
|
81
|
+
# Coverage (matches the `sonarcloud` job in test.yml; SonarCloud reads coverage.xml)
|
|
82
|
+
uv run pytest --cov=src/devex --cov-report=xml --cov-report=term
|
|
82
83
|
```
|
|
83
84
|
|
|
84
85
|
## CI surface
|
|
85
86
|
|
|
86
|
-
- `.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.
|
|
87
|
+
- `.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.
|
|
87
88
|
- `.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.
|
|
88
|
-
- SonarCloud
|
|
89
|
+
- 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.
|
|
89
90
|
- All third-party actions are **pinned to full commit SHAs** with trailing `# vN` comments (rule `githubactions:S7637`). Keep new actions pinned the same way.
|
|
90
91
|
|
|
91
92
|
## SonarCloud notes
|
|
92
93
|
|
|
93
|
-
- `python:S5496` is **narrowly suppressed** for `src/
|
|
94
|
+
- `python:S5496` is **narrowly suppressed** for `src/devex/core/render.py` only via `sonar.issue.ignore.multicriteria` in `sonar-project.properties`. Reason: `render_string()` renders Jinja templates that are always package-shipped; output is markdown, never HTML in a browser. See the comment in `render.py` above `render_string` for the rationale. Do not widen the suppression to other files.
|
|
94
95
|
- The `render.py` autoescape decision is explicit (`autoescape=select_autoescape([])`). Don't change it.
|
|
95
96
|
|
|
96
97
|
## Git workflow
|
|
@@ -100,6 +101,6 @@ uv run pytest --cov=src/agent_experience --cov-report=xml --cov-report=term
|
|
|
100
101
|
- Push, open a PR, let CI + SonarCloud + Qodo + Copilot run. Address inline comments + resolve threads before merge.
|
|
101
102
|
- Merging to `main` publishes to PyPI automatically (via `autotag` → `publish-pypi` → `github-release` in `publish.yml`). No manual tagging.
|
|
102
103
|
- When posting on GitHub on the user's behalf (PR descriptions, issue replies, review-thread replies), sign so it's clear the message came from an AI. Three conventions, in priority order:
|
|
103
|
-
- **`
|
|
104
|
+
- **`devex pr open` / `devex pr reply`** — auto-append `- devex-cli (Claude)` (the nick is resolved from `culture.yaml` via `core.github.resolve_nick`, falling back to the repo basename). Don't sign manually.
|
|
104
105
|
- **Inside `communicate` workflow scripts** (`post-issue.sh`, `post-comment.sh`) — `agtag` resolves the same nick from `culture.yaml`. Don't sign manually.
|
|
105
|
-
- **Manual posts the scripts didn't author** (a hand-typed `gh pr create --body …`, a one-off review reply) — sign explicitly as `-
|
|
106
|
+
- **Manual posts the scripts didn't author** (a hand-typed `gh pr create --body …`, a one-off review reply) — sign explicitly as `- devex-cli (Claude)`.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agex-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.26.1
|
|
4
4
|
Summary: Agent-operated developer-experience CLI — deterministic per-backend markdown briefings for autonomous agents.
|
|
5
|
-
Project-URL: Homepage, https://culture.dev/
|
|
5
|
+
Project-URL: Homepage, https://culture.dev/devex/
|
|
6
6
|
Project-URL: Repository, https://github.com/agentculture/devex
|
|
7
7
|
Project-URL: Issues, https://github.com/agentculture/devex/issues
|
|
8
8
|
Author: Ori Nachum
|
|
@@ -24,29 +24,29 @@ Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
|
24
24
|
Requires-Dist: syrupy>=4.6; extra == 'dev'
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
26
26
|
|
|
27
|
-
#
|
|
27
|
+
# devex
|
|
28
28
|
|
|
29
|
-
Agent-operated developer-experience CLI. Non-agentic, deterministic, markdown-first. The same wheel is published on PyPI under three distribution names — `
|
|
29
|
+
Agent-operated developer-experience CLI. Non-agentic, deterministic, markdown-first. The same wheel is published on PyPI under three distribution names — `devex-cli` (canonical), `agent-devex`, and `agex-cli` (the legacy canonical name, still published) — and installs two equivalent commands, `devex` (canonical) and `agex` (legacy alias) (emitted output reflects whichever name you invoke).
|
|
30
30
|
|
|
31
31
|
## Install
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
uv tool install
|
|
34
|
+
uv tool install devex-cli # or: agex-cli
|
|
35
35
|
# or
|
|
36
|
-
pipx install
|
|
36
|
+
pipx install devex-cli # or: pipx install agex-cli
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
## Quick start
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
devex explain devex
|
|
43
|
+
devex overview --agent claude-code
|
|
44
|
+
devex learn --agent claude-code
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
## Docs
|
|
48
48
|
|
|
49
|
-
[culture.dev/
|
|
49
|
+
[culture.dev/devex](https://culture.dev/devex/).
|
|
50
50
|
|
|
51
51
|
Spec: `docs/superpowers/specs/2026-04-18-agex-design.md`.
|
|
52
52
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# devex
|
|
2
|
+
|
|
3
|
+
Agent-operated developer-experience CLI. Non-agentic, deterministic, markdown-first. The same wheel is published on PyPI under three distribution names — `devex-cli` (canonical), `agent-devex`, and `agex-cli` (the legacy canonical name, still published) — and installs two equivalent commands, `devex` (canonical) and `agex` (legacy alias) (emitted output reflects whichever name you invoke).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv tool install devex-cli # or: agex-cli
|
|
9
|
+
# or
|
|
10
|
+
pipx install devex-cli # or: pipx install agex-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
devex explain devex
|
|
17
|
+
devex overview --agent claude-code
|
|
18
|
+
devex learn --agent claude-code
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Docs
|
|
22
|
+
|
|
23
|
+
[culture.dev/devex](https://culture.dev/devex/).
|
|
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.26.1"
|
|
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"}
|
|
@@ -26,11 +26,11 @@ dev = [
|
|
|
26
26
|
]
|
|
27
27
|
|
|
28
28
|
[project.scripts]
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
devex = "devex.cli:_main_entrypoint"
|
|
30
|
+
agex = "devex.cli:_main_entrypoint"
|
|
31
31
|
|
|
32
32
|
[project.urls]
|
|
33
|
-
Homepage = "https://culture.dev/
|
|
33
|
+
Homepage = "https://culture.dev/devex/"
|
|
34
34
|
Repository = "https://github.com/agentculture/devex"
|
|
35
35
|
Issues = "https://github.com/agentculture/devex/issues"
|
|
36
36
|
|
|
@@ -39,12 +39,27 @@ requires = ["hatchling"]
|
|
|
39
39
|
build-backend = "hatchling.build"
|
|
40
40
|
|
|
41
41
|
[tool.hatch.build.targets.wheel]
|
|
42
|
-
packages = ["src/
|
|
42
|
+
packages = ["src/devex"]
|
|
43
43
|
|
|
44
44
|
[tool.pytest.ini_options]
|
|
45
45
|
testpaths = ["tests"]
|
|
46
46
|
addopts = "-n auto -v"
|
|
47
47
|
|
|
48
|
+
[tool.coverage.run]
|
|
49
|
+
source = ["src/devex"]
|
|
50
|
+
# Emit repo-relative paths in coverage.xml so SonarCloud maps them to
|
|
51
|
+
# sonar.sources=src (absolute / .venv paths fail to map → empty coverage).
|
|
52
|
+
relative_files = true
|
|
53
|
+
|
|
54
|
+
[tool.coverage.report]
|
|
55
|
+
show_missing = true
|
|
56
|
+
fail_under = 60
|
|
57
|
+
exclude_lines = [
|
|
58
|
+
"pragma: no cover",
|
|
59
|
+
"if __name__ == .__main__.",
|
|
60
|
+
"if TYPE_CHECKING:",
|
|
61
|
+
]
|
|
62
|
+
|
|
48
63
|
[tool.black]
|
|
49
64
|
line-length = 100
|
|
50
65
|
|
|
@@ -54,7 +69,7 @@ line_length = 100
|
|
|
54
69
|
|
|
55
70
|
[tool.bandit]
|
|
56
71
|
# B311 flags any `random.*` usage as potentially unsafe for crypto purposes.
|
|
57
|
-
# `core/
|
|
72
|
+
# `core/_jsonl.acquire_lock_with_retry` uses `random.uniform` purely for
|
|
58
73
|
# backoff jitter between bounded retries -- not a security context, so the
|
|
59
74
|
# standard `random` module is the right choice (secrets would be misuse).
|
|
60
75
|
skips = ["B311"]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
sonar.projectKey=agentculture_devex
|
|
2
|
-
sonar.organization=
|
|
2
|
+
sonar.organization=agentculture
|
|
3
3
|
|
|
4
4
|
# Displayed in SonarCloud UI
|
|
5
5
|
sonar.projectName=devex
|
|
@@ -12,12 +12,11 @@ sonar.sourceEncoding=UTF-8
|
|
|
12
12
|
# Python: target versions (matches CI matrix)
|
|
13
13
|
sonar.python.version=3.10, 3.11, 3.12, 3.13
|
|
14
14
|
|
|
15
|
-
# Coverage report path. SonarCloud runs in
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
# coverage
|
|
19
|
-
#
|
|
20
|
-
# coverage and is what gates the PR quality gate today.
|
|
15
|
+
# Coverage report path. SonarCloud now runs in CI-based analysis mode
|
|
16
|
+
# (Automatic Analysis is OFF — the two are mutually exclusive). The `sonarcloud`
|
|
17
|
+
# job in .github/workflows/test.yml runs `pytest --cov` (repo-relative paths
|
|
18
|
+
# via pyproject [tool.coverage.run], so Sonar can match files) and the
|
|
19
|
+
# sonarqube-scan-action uploads this report. Requires the SONAR_TOKEN repo secret.
|
|
21
20
|
sonar.python.coverage.reportPaths=coverage.xml
|
|
22
21
|
|
|
23
22
|
# S5496 triggers on render_string() because it renders a Jinja template with a
|
|
@@ -30,17 +29,17 @@ sonar.python.coverage.reportPaths=coverage.xml
|
|
|
30
29
|
# S2083 (path injection) fires in commands/gamify/scripts/install.py because
|
|
31
30
|
# the hooks file path is `Path.cwd() / ".claude" / "hooks.json"`. `Path.cwd()`
|
|
32
31
|
# is the process's working directory (set by the user's shell before invoking
|
|
33
|
-
#
|
|
32
|
+
# devex); `.claude` and `hooks.json` are hardcoded literals. No HTTP body, CLI
|
|
34
33
|
# string argument, or other network/request input is ever joined into this
|
|
35
34
|
# path — the backend name is enum-validated by `parse_backend()` before reaching
|
|
36
35
|
# install.py and does not itself flow into the path. S2083 is designed for
|
|
37
36
|
# web contexts where a request-body filename taints a filesystem call; that
|
|
38
37
|
# threat model does not apply here. Writing `.claude/hooks.json` is the
|
|
39
|
-
# documented contract of `
|
|
38
|
+
# documented contract of `devex gamify` (design spec invariant #4: "Side
|
|
40
39
|
# effects only in gamify, gamify --uninstall, hook write, and first-run
|
|
41
|
-
# `.
|
|
40
|
+
# `.devex/` init"). Rule is disabled only for this one file.
|
|
42
41
|
sonar.issue.ignore.multicriteria=e1,e2
|
|
43
42
|
sonar.issue.ignore.multicriteria.e1.ruleKey=pythonsecurity:S5496
|
|
44
|
-
sonar.issue.ignore.multicriteria.e1.resourceKey=src/
|
|
43
|
+
sonar.issue.ignore.multicriteria.e1.resourceKey=src/devex/core/render.py
|
|
45
44
|
sonar.issue.ignore.multicriteria.e2.ruleKey=pythonsecurity:S2083
|
|
46
|
-
sonar.issue.ignore.multicriteria.e2.resourceKey=src/
|
|
45
|
+
sonar.issue.ignore.multicriteria.e2.resourceKey=src/devex/commands/gamify/scripts/install.py
|
|
@@ -2,14 +2,15 @@ from importlib.metadata import PackageNotFoundError, version
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
def _resolve_version() -> str:
|
|
5
|
-
# `
|
|
6
|
-
# `
|
|
7
|
-
# different names
|
|
5
|
+
# `devex-cli` is the canonical PyPI distribution name; `agent-devex` and
|
|
6
|
+
# `agex-cli` are alias distributions that ship the identical wheel under
|
|
7
|
+
# different names (`agex-cli` is the legacy canonical name, kept published
|
|
8
|
+
# for back-compat). Whichever one is installed, surface its metadata
|
|
8
9
|
# version. As a final fallback for unbuilt source checkouts (no installed
|
|
9
10
|
# dist metadata), read the version directly from the repo's pyproject.toml
|
|
10
11
|
# so the version stays single-sourced from pyproject.toml in every
|
|
11
12
|
# reachable code path.
|
|
12
|
-
for dist in ("
|
|
13
|
+
for dist in ("devex-cli", "agent-devex", "agex-cli"):
|
|
13
14
|
try:
|
|
14
15
|
return version(dist)
|
|
15
16
|
except PackageNotFoundError:
|
{agex_cli-0.25.0/src/agent_experience → agex_cli-0.26.1/src/devex}/backends/capabilities/codex.yaml
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
hooks: false
|
|
2
2
|
hooks_alternative: |
|
|
3
3
|
Codex does not expose a hook interface. Wrap your Codex invocation in a shell
|
|
4
|
-
script that calls `
|
|
4
|
+
script that calls `devex hook write` before/after each turn as a workaround.
|
|
5
5
|
mcp: true
|
|
6
6
|
skills: false
|
|
7
7
|
agents: false
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
hooks: false
|
|
2
2
|
hooks_alternative: |
|
|
3
3
|
GitHub Copilot CLI does not expose a hook interface in v0.1-era versions.
|
|
4
|
-
Track usage via a shell wrapper that calls `
|
|
4
|
+
Track usage via a shell wrapper that calls `devex hook write`.
|
|
5
5
|
mcp: false
|
|
6
6
|
skills: false
|
|
7
7
|
agents: false
|