pulse-orchestrator 0.3.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.
- pulse_orchestrator-0.3.0/.agents/.skill-lock.json +33 -0
- pulse_orchestrator-0.3.0/.claude/skills/python-quality/SKILL.MD +465 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/SKILL.md +228 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/cors-auditor/auditor.py +162 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/cors-auditor/tests/test_auditor.py +164 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/dependency-check/checker.py +312 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/dependency-check/tests/test_checker.py +188 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/dockerfile-scan/scanner.py +248 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/dockerfile-scan/tests/test_scanner.py +126 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/http-sec-audit/audit.py +255 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/http-sec-audit/tests/test_audit.py +209 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/jwt-inspector/inspector.py +228 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/jwt-inspector/tests/test_inspector.py +187 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/prompt-injection-tester/attacker.py +323 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/prompt-injection-tester/tests/test_attacker.py +119 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/sast-lite/analyzer.py +590 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/sast-lite/tests/test_analyzer.py +335 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/secret-scanner/engine.py +396 -0
- pulse_orchestrator-0.3.0/.claude/skills/security-audit/tools/secret-scanner/tests/test_engine.py +224 -0
- pulse_orchestrator-0.3.0/.claude/skills/software-architect/SKILL.md +344 -0
- pulse_orchestrator-0.3.0/.claude/skills/software-architect/references/adr-templates.md +248 -0
- pulse_orchestrator-0.3.0/.claude/skills/software-architect/references/anti-patterns.md +938 -0
- pulse_orchestrator-0.3.0/.claude/skills/software-architect/references/arc42-template.md +622 -0
- pulse_orchestrator-0.3.0/.claude/skills/software-architect/references/architecture-patterns.md +754 -0
- pulse_orchestrator-0.3.0/.claude/skills/software-architect/references/architecture-review-framework.md +535 -0
- pulse_orchestrator-0.3.0/.claude/skills/software-architect/references/c4-diagramming.md +636 -0
- pulse_orchestrator-0.3.0/.claude/skills/software-architect/references/design-review-scorecard.md +676 -0
- pulse_orchestrator-0.3.0/.claude/skills/software-architect/references/elite-blueprint.md +1194 -0
- pulse_orchestrator-0.3.0/.claude/skills/software-architect/references/fitness-functions.md +979 -0
- pulse_orchestrator-0.3.0/.claude/skills/software-architect/references/migration-playbooks.md +550 -0
- pulse_orchestrator-0.3.0/.claude/skills/software-architect/references/quality-attributes.md +410 -0
- pulse_orchestrator-0.3.0/.claude/skills/software-architect/references/technical-debt-assessment.md +396 -0
- pulse_orchestrator-0.3.0/.claude/skills/tactical-ddd/.skill-meta.json +4 -0
- pulse_orchestrator-0.3.0/.claude/skills/tactical-ddd/SKILL.md +87 -0
- pulse_orchestrator-0.3.0/.claude/skills/tactical-ddd/detection.md +78 -0
- pulse_orchestrator-0.3.0/.claude/skills/tactical-ddd/refactoring.md +191 -0
- pulse_orchestrator-0.3.0/.claude/skills/tactical-ddd/reference.md +193 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/SKILL.md +262 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/antipatterns.md +356 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/characterization-testing.md +32 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/combinatorial-testing.md +208 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/correctness-by-construction.md +384 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/deterministic-time.md +257 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/differential-testing.md +173 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/doc-sync-testing.md +55 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/exhaustive-testing.md +121 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/fuzzing.md +33 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/gate-integrity.md +184 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/go.md +321 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/golden-file-testing.md +291 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/mathematical-properties.md +46 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/mutation-testing.md +177 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/property-based-testing.md +42 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/python.md +188 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/rust.md +204 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/test-data-builders.md +125 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/test-types.md +335 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/typescript.md +304 -0
- pulse_orchestrator-0.3.0/.claude/skills/testing-best-practices/references/vcr-cassettes.md +107 -0
- pulse_orchestrator-0.3.0/.claude/skills/the-judge/.skill-meta.json +4 -0
- pulse_orchestrator-0.3.0/.claude/skills/the-judge/SKILL.md +240 -0
- pulse_orchestrator-0.3.0/.claude/skills/the-judge/references/comment-voice.md +69 -0
- pulse_orchestrator-0.3.0/.claude/skills/the-judge/references/review-standards.md +122 -0
- pulse_orchestrator-0.3.0/.claude/skills/the-judge/scripts/post_review.py +89 -0
- pulse_orchestrator-0.3.0/.claude/skills/the-judge/scripts/review_gate.py +216 -0
- pulse_orchestrator-0.3.0/.claude/skills/the-judge/scripts/scan_bypasses.py +68 -0
- pulse_orchestrator-0.3.0/.github/ISSUE_TEMPLATE/bug_report.yml +71 -0
- pulse_orchestrator-0.3.0/.github/ISSUE_TEMPLATE/config.yml +11 -0
- pulse_orchestrator-0.3.0/.github/ISSUE_TEMPLATE/feature_request.yml +35 -0
- pulse_orchestrator-0.3.0/.github/dependabot.yml +16 -0
- pulse_orchestrator-0.3.0/.github/pull_request_template.md +29 -0
- pulse_orchestrator-0.3.0/.github/workflows/ci.yml +210 -0
- pulse_orchestrator-0.3.0/.github/workflows/release-pr.yml +109 -0
- pulse_orchestrator-0.3.0/.github/workflows/release.yml +89 -0
- pulse_orchestrator-0.3.0/.gitignore +18 -0
- pulse_orchestrator-0.3.0/.gitleaks.toml +8 -0
- pulse_orchestrator-0.3.0/.pre-commit-config.yaml +36 -0
- pulse_orchestrator-0.3.0/.vscode/settings.json +3 -0
- pulse_orchestrator-0.3.0/AGENTS.md +414 -0
- pulse_orchestrator-0.3.0/ARCHITECTURE.md +926 -0
- pulse_orchestrator-0.3.0/CHANGELOG.md +97 -0
- pulse_orchestrator-0.3.0/CODE_OF_CONDUCT.md +85 -0
- pulse_orchestrator-0.3.0/CONTRIBUTING.md +94 -0
- pulse_orchestrator-0.3.0/LICENSE +21 -0
- pulse_orchestrator-0.3.0/PKG-INFO +444 -0
- pulse_orchestrator-0.3.0/README.en.md +55 -0
- pulse_orchestrator-0.3.0/README.md +423 -0
- pulse_orchestrator-0.3.0/SECURITY.md +42 -0
- pulse_orchestrator-0.3.0/SUPPORT.md +15 -0
- pulse_orchestrator-0.3.0/contracts/openapi.yaml +634 -0
- pulse_orchestrator-0.3.0/docs/adr/0001-camada-de-dominio.md +127 -0
- pulse_orchestrator-0.3.0/docs/adr/0002-engine-depends-on-ports.md +149 -0
- pulse_orchestrator-0.3.0/docs/adr/0003-listeners-locais-recusam-navegador.md +98 -0
- pulse_orchestrator-0.3.0/docs/adr/0004-texto-de-tela-mora-com-quem-o-compoe.md +101 -0
- pulse_orchestrator-0.3.0/docs/adr/0005-tcp-exige-token-do-daemon.md +94 -0
- pulse_orchestrator-0.3.0/docs/agentes.md +725 -0
- pulse_orchestrator-0.3.0/docs/armazenamento.md +139 -0
- pulse_orchestrator-0.3.0/docs/demo/demo.gif +0 -0
- pulse_orchestrator-0.3.0/docs/demo/demo.tape +59 -0
- pulse_orchestrator-0.3.0/docs/demo/fake_agent.py +282 -0
- pulse_orchestrator-0.3.0/docs/demo/prepare.sh +59 -0
- pulse_orchestrator-0.3.0/docs/logs.md +88 -0
- pulse_orchestrator-0.3.0/docs/quality-scorecard.md +147 -0
- pulse_orchestrator-0.3.0/docs/questions.md +203 -0
- pulse_orchestrator-0.3.0/docs/workflows.md +449 -0
- pulse_orchestrator-0.3.0/pulse/__init__.py +3 -0
- pulse_orchestrator-0.3.0/pulse/__main__.py +3 -0
- pulse_orchestrator-0.3.0/pulse/acp/__init__.py +3 -0
- pulse_orchestrator-0.3.0/pulse/acp/capabilities.py +27 -0
- pulse_orchestrator-0.3.0/pulse/acp/client.py +234 -0
- pulse_orchestrator-0.3.0/pulse/acp/reply_clock.py +44 -0
- pulse_orchestrator-0.3.0/pulse/acp/session_runner.py +543 -0
- pulse_orchestrator-0.3.0/pulse/acp/step_turns.py +206 -0
- pulse_orchestrator-0.3.0/pulse/acp/watched_prompts.py +62 -0
- pulse_orchestrator-0.3.0/pulse/api/__init__.py +3 -0
- pulse_orchestrator-0.3.0/pulse/api/app.py +39 -0
- pulse_orchestrator-0.3.0/pulse/api/browser_guard.py +44 -0
- pulse_orchestrator-0.3.0/pulse/api/config_routes.py +97 -0
- pulse_orchestrator-0.3.0/pulse/api/deps.py +28 -0
- pulse_orchestrator-0.3.0/pulse/api/history_routes.py +104 -0
- pulse_orchestrator-0.3.0/pulse/api/run_routes.py +143 -0
- pulse_orchestrator-0.3.0/pulse/api/settings_routes.py +239 -0
- pulse_orchestrator-0.3.0/pulse/api/system_routes.py +67 -0
- pulse_orchestrator-0.3.0/pulse/api/token_guard.py +52 -0
- pulse_orchestrator-0.3.0/pulse/cli/__init__.py +0 -0
- pulse_orchestrator-0.3.0/pulse/cli/daemon_command.py +71 -0
- pulse_orchestrator-0.3.0/pulse/cli/main.py +205 -0
- pulse_orchestrator-0.3.0/pulse/client/__init__.py +3 -0
- pulse_orchestrator-0.3.0/pulse/client/active_runs.py +39 -0
- pulse_orchestrator-0.3.0/pulse/client/daemon_process.py +74 -0
- pulse_orchestrator-0.3.0/pulse/client/engine_client.py +229 -0
- pulse_orchestrator-0.3.0/pulse/client/protocol.py +42 -0
- pulse_orchestrator-0.3.0/pulse/client/run_session.py +344 -0
- pulse_orchestrator-0.3.0/pulse/client/runtime_login.py +25 -0
- pulse_orchestrator-0.3.0/pulse/config/__init__.py +56 -0
- pulse_orchestrator-0.3.0/pulse/config/agent_profiles.py +34 -0
- pulse_orchestrator-0.3.0/pulse/config/agents.py +106 -0
- pulse_orchestrator-0.3.0/pulse/config/commands.py +50 -0
- pulse_orchestrator-0.3.0/pulse/config/global_config.py +264 -0
- pulse_orchestrator-0.3.0/pulse/config/model_catalog.py +68 -0
- pulse_orchestrator-0.3.0/pulse/config/onboarding.py +63 -0
- pulse_orchestrator-0.3.0/pulse/config/project_config.py +358 -0
- pulse_orchestrator-0.3.0/pulse/config/project_settings.py +202 -0
- pulse_orchestrator-0.3.0/pulse/config/ready.py +14 -0
- pulse_orchestrator-0.3.0/pulse/config/resolved.py +309 -0
- pulse_orchestrator-0.3.0/pulse/daemon/__init__.py +1 -0
- pulse_orchestrator-0.3.0/pulse/daemon/__main__.py +4 -0
- pulse_orchestrator-0.3.0/pulse/daemon/adapters.py +217 -0
- pulse_orchestrator-0.3.0/pulse/daemon/events.py +150 -0
- pulse_orchestrator-0.3.0/pulse/daemon/logs.py +32 -0
- pulse_orchestrator-0.3.0/pulse/daemon/runs.py +448 -0
- pulse_orchestrator-0.3.0/pulse/daemon/server.py +220 -0
- pulse_orchestrator-0.3.0/pulse/doctor/__init__.py +13 -0
- pulse_orchestrator-0.3.0/pulse/doctor/checks.py +126 -0
- pulse_orchestrator-0.3.0/pulse/doctor/report.py +124 -0
- pulse_orchestrator-0.3.0/pulse/domain/__init__.py +0 -0
- pulse_orchestrator-0.3.0/pulse/domain/branch_name.py +29 -0
- pulse_orchestrator-0.3.0/pulse/domain/control.py +56 -0
- pulse_orchestrator-0.3.0/pulse/domain/git_options.py +67 -0
- pulse_orchestrator-0.3.0/pulse/domain/outcome.py +201 -0
- pulse_orchestrator-0.3.0/pulse/domain/ports.py +574 -0
- pulse_orchestrator-0.3.0/pulse/domain/run.py +519 -0
- pulse_orchestrator-0.3.0/pulse/domain/task_brief.py +34 -0
- pulse_orchestrator-0.3.0/pulse/domain/workflow.py +154 -0
- pulse_orchestrator-0.3.0/pulse/history/__init__.py +10 -0
- pulse_orchestrator-0.3.0/pulse/history/catalog.py +130 -0
- pulse_orchestrator-0.3.0/pulse/history/events.py +191 -0
- pulse_orchestrator-0.3.0/pulse/history/log_wording.py +19 -0
- pulse_orchestrator-0.3.0/pulse/history/models.py +130 -0
- pulse_orchestrator-0.3.0/pulse/history/prompt_detail.py +224 -0
- pulse_orchestrator-0.3.0/pulse/history/run_lines.py +59 -0
- pulse_orchestrator-0.3.0/pulse/history/run_log.py +161 -0
- pulse_orchestrator-0.3.0/pulse/history/session_log.py +267 -0
- pulse_orchestrator-0.3.0/pulse/history/status_labels.py +78 -0
- pulse_orchestrator-0.3.0/pulse/history/tool_classify.py +48 -0
- pulse_orchestrator-0.3.0/pulse/history/tool_detail.py +537 -0
- pulse_orchestrator-0.3.0/pulse/mcp/__init__.py +1 -0
- pulse_orchestrator-0.3.0/pulse/mcp/ask_bridge.py +109 -0
- pulse_orchestrator-0.3.0/pulse/mcp/ask_protocol.py +126 -0
- pulse_orchestrator-0.3.0/pulse/mcp/ask_stdio.py +128 -0
- pulse_orchestrator-0.3.0/pulse/mcp/channel.py +30 -0
- pulse_orchestrator-0.3.0/pulse/mcp/config.py +14 -0
- pulse_orchestrator-0.3.0/pulse/mcp/http_bridge.py +166 -0
- pulse_orchestrator-0.3.0/pulse/orchestrator/__init__.py +4 -0
- pulse_orchestrator-0.3.0/pulse/orchestrator/agent_text.py +197 -0
- pulse_orchestrator-0.3.0/pulse/orchestrator/delivery.py +115 -0
- pulse_orchestrator-0.3.0/pulse/orchestrator/engine.py +620 -0
- pulse_orchestrator-0.3.0/pulse/orchestrator/fanout.py +84 -0
- pulse_orchestrator-0.3.0/pulse/orchestrator/loops.py +47 -0
- pulse_orchestrator-0.3.0/pulse/orchestrator/menus.py +119 -0
- pulse_orchestrator-0.3.0/pulse/orchestrator/render.py +46 -0
- pulse_orchestrator-0.3.0/pulse/orchestrator/turn.py +67 -0
- pulse_orchestrator-0.3.0/pulse/orchestrator/waits.py +33 -0
- pulse_orchestrator-0.3.0/pulse/orchestrator/wiring.py +67 -0
- pulse_orchestrator-0.3.0/pulse/orchestrator/wording.py +136 -0
- pulse_orchestrator-0.3.0/pulse/orchestrator/worktree.py +76 -0
- pulse_orchestrator-0.3.0/pulse/replies/__init__.py +63 -0
- pulse_orchestrator-0.3.0/pulse/replies/acp_payloads.py +208 -0
- pulse_orchestrator-0.3.0/pulse/replies/approval.py +106 -0
- pulse_orchestrator-0.3.0/pulse/replies/ask_question.py +173 -0
- pulse_orchestrator-0.3.0/pulse/replies/permission.py +127 -0
- pulse_orchestrator-0.3.0/pulse/replies/session_models.py +140 -0
- pulse_orchestrator-0.3.0/pulse/replies/text_questionnaire.py +265 -0
- pulse_orchestrator-0.3.0/pulse/replies/wording.py +25 -0
- pulse_orchestrator-0.3.0/pulse/runtimes/__init__.py +83 -0
- pulse_orchestrator-0.3.0/pulse/runtimes/base.py +228 -0
- pulse_orchestrator-0.3.0/pulse/runtimes/claude.py +93 -0
- pulse_orchestrator-0.3.0/pulse/runtimes/codex.py +81 -0
- pulse_orchestrator-0.3.0/pulse/runtimes/cursor.py +51 -0
- pulse_orchestrator-0.3.0/pulse/store/__init__.py +3 -0
- pulse_orchestrator-0.3.0/pulse/store/agent_settings.py +109 -0
- pulse_orchestrator-0.3.0/pulse/store/codec.py +16 -0
- pulse_orchestrator-0.3.0/pulse/store/db.py +418 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/__init__.py +522 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/codebase-docs/AGENT.md +980 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/codebase-docs/PHASE.md +27 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/codebase-explore/AGENT.md +980 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/codebase-explore/PHASE.md +56 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/implement/AGENT.md +447 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/implement/FIX.md +76 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/implement/PHASE.md +37 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/prd/AGENT.md +763 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/prd/PHASE.md +31 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/quick-implement/AGENT.md +654 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/quick-implement/PHASE.md +32 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/quick-plan/AGENT.md +594 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/quick-plan/PHASE.md +78 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/review/AGENT.md +1088 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/review/PHASE.md +93 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/review/STANDALONE.md +117 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/review-fix/AGENT.md +625 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/review-fix/PHASE.md +106 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/review-fix/STANDALONE.md +124 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/setup-artifacts/AGENT.md +525 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/setup-artifacts/PHASE.md +19 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/setup-interview/AGENT.md +525 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/setup-interview/PHASE.md +56 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/tasks/AGENT.md +846 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/tasks/PHASE.md +47 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/techspec/AGENT.md +577 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/techspec/PHASE.md +28 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/verify/AGENT.md +368 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/agents/verify/PHASE.md +118 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/pull_request.md +20 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/shared/approval-skip.md +27 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/shared/approval.md +18 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/shared/clarify.md +74 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/shared/handoff.md +16 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/shared/isolation-reuse.md +4 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/shared/isolation.md +7 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/shared/output-language.md +20 -0
- pulse_orchestrator-0.3.0/pulse/store/factory/shared/review-close.md +25 -0
- pulse_orchestrator-0.3.0/pulse/store/paths.py +119 -0
- pulse_orchestrator-0.3.0/pulse/store/runs.py +558 -0
- pulse_orchestrator-0.3.0/pulse/store/sessions.py +98 -0
- pulse_orchestrator-0.3.0/pulse/store/workflow_defs.py +198 -0
- pulse_orchestrator-0.3.0/pulse/tui/__init__.py +11 -0
- pulse_orchestrator-0.3.0/pulse/tui/adapters/__init__.py +6 -0
- pulse_orchestrator-0.3.0/pulse/tui/adapters/cockpit_sink.py +505 -0
- pulse_orchestrator-0.3.0/pulse/tui/adapters/prompt_bridge.py +431 -0
- pulse_orchestrator-0.3.0/pulse/tui/app.py +79 -0
- pulse_orchestrator-0.3.0/pulse/tui/artifact_tab.py +159 -0
- pulse_orchestrator-0.3.0/pulse/tui/artifacts.py +106 -0
- pulse_orchestrator-0.3.0/pulse/tui/brand.py +10 -0
- pulse_orchestrator-0.3.0/pulse/tui/cursor_store.py +199 -0
- pulse_orchestrator-0.3.0/pulse/tui/engine.py +454 -0
- pulse_orchestrator-0.3.0/pulse/tui/history_rows.py +89 -0
- pulse_orchestrator-0.3.0/pulse/tui/history_theme.py +81 -0
- pulse_orchestrator-0.3.0/pulse/tui/home_theme.py +340 -0
- pulse_orchestrator-0.3.0/pulse/tui/hydrate.py +236 -0
- pulse_orchestrator-0.3.0/pulse/tui/key_hints.py +16 -0
- pulse_orchestrator-0.3.0/pulse/tui/menu_rows.py +65 -0
- pulse_orchestrator-0.3.0/pulse/tui/palette.py +12 -0
- pulse_orchestrator-0.3.0/pulse/tui/screens/__init__.py +8 -0
- pulse_orchestrator-0.3.0/pulse/tui/screens/branch_name.py +80 -0
- pulse_orchestrator-0.3.0/pulse/tui/screens/cockpit.py +483 -0
- pulse_orchestrator-0.3.0/pulse/tui/screens/confirm.py +62 -0
- pulse_orchestrator-0.3.0/pulse/tui/screens/history.py +311 -0
- pulse_orchestrator-0.3.0/pulse/tui/screens/history_detail.py +273 -0
- pulse_orchestrator-0.3.0/pulse/tui/screens/home.py +479 -0
- pulse_orchestrator-0.3.0/pulse/tui/screens/navigation.py +17 -0
- pulse_orchestrator-0.3.0/pulse/tui/screens/onboarding.py +311 -0
- pulse_orchestrator-0.3.0/pulse/tui/screens/resume_choice.py +60 -0
- pulse_orchestrator-0.3.0/pulse/tui/screens/settings.py +488 -0
- pulse_orchestrator-0.3.0/pulse/tui/settings_rows.py +65 -0
- pulse_orchestrator-0.3.0/pulse/tui/settings_theme.py +72 -0
- pulse_orchestrator-0.3.0/pulse/tui/state.py +635 -0
- pulse_orchestrator-0.3.0/pulse/tui/strings.py +345 -0
- pulse_orchestrator-0.3.0/pulse/tui/theme.py +501 -0
- pulse_orchestrator-0.3.0/pulse/tui/widgets/__init__.py +9 -0
- pulse_orchestrator-0.3.0/pulse/tui/widgets/app_footer.py +58 -0
- pulse_orchestrator-0.3.0/pulse/tui/widgets/app_header.py +48 -0
- pulse_orchestrator-0.3.0/pulse/tui/widgets/artifact_pane.py +241 -0
- pulse_orchestrator-0.3.0/pulse/tui/widgets/file_mention.py +100 -0
- pulse_orchestrator-0.3.0/pulse/tui/widgets/log_stream.py +347 -0
- pulse_orchestrator-0.3.0/pulse/tui/widgets/menu_list.py +73 -0
- pulse_orchestrator-0.3.0/pulse/tui/widgets/options.py +13 -0
- pulse_orchestrator-0.3.0/pulse/tui/widgets/options_toggle.py +63 -0
- pulse_orchestrator-0.3.0/pulse/tui/widgets/phase_sidebar.py +211 -0
- pulse_orchestrator-0.3.0/pulse/tui/widgets/prompt_dock.py +179 -0
- pulse_orchestrator-0.3.0/pulse/tui/widgets/task_composer.py +131 -0
- pulse_orchestrator-0.3.0/pulse/tui/widgets/task_form.py +238 -0
- pulse_orchestrator-0.3.0/pulse/vcs/__init__.py +258 -0
- pulse_orchestrator-0.3.0/pulse/vcs/changes.py +110 -0
- pulse_orchestrator-0.3.0/pulse/vcs/publish.py +109 -0
- pulse_orchestrator-0.3.0/pulse/vcs/workspace.py +102 -0
- pulse_orchestrator-0.3.0/pulse_orchestrator.egg-info/PKG-INFO +444 -0
- pulse_orchestrator-0.3.0/pulse_orchestrator.egg-info/SOURCES.txt +491 -0
- pulse_orchestrator-0.3.0/pulse_orchestrator.egg-info/dependency_links.txt +1 -0
- pulse_orchestrator-0.3.0/pulse_orchestrator.egg-info/entry_points.txt +4 -0
- pulse_orchestrator-0.3.0/pulse_orchestrator.egg-info/requires.txt +7 -0
- pulse_orchestrator-0.3.0/pulse_orchestrator.egg-info/scm_file_list.json +487 -0
- pulse_orchestrator-0.3.0/pulse_orchestrator.egg-info/scm_version.json +8 -0
- pulse_orchestrator-0.3.0/pulse_orchestrator.egg-info/top_level.txt +1 -0
- pulse_orchestrator-0.3.0/pyproject.toml +331 -0
- pulse_orchestrator-0.3.0/scripts/mutation_gate.py +36 -0
- pulse_orchestrator-0.3.0/setup.cfg +4 -0
- pulse_orchestrator-0.3.0/skills-lock.json +11 -0
- pulse_orchestrator-0.3.0/tests/api/test_api_browser_guard.py +71 -0
- pulse_orchestrator-0.3.0/tests/api/test_api_engine.py +479 -0
- pulse_orchestrator-0.3.0/tests/api/test_api_routes.py +317 -0
- pulse_orchestrator-0.3.0/tests/api/test_api_token_guard.py +103 -0
- pulse_orchestrator-0.3.0/tests/api/test_daemon_adapters.py +98 -0
- pulse_orchestrator-0.3.0/tests/api/test_daemon_adapters_edges.py +231 -0
- pulse_orchestrator-0.3.0/tests/api/test_daemon_arguments.py +77 -0
- pulse_orchestrator-0.3.0/tests/api/test_daemon_logs.py +147 -0
- pulse_orchestrator-0.3.0/tests/api/test_daemon_loopback.py +46 -0
- pulse_orchestrator-0.3.0/tests/api/test_daemon_shutdown.py +196 -0
- pulse_orchestrator-0.3.0/tests/api/test_daemon_socket.py +98 -0
- pulse_orchestrator-0.3.0/tests/api/test_run_engine.py +151 -0
- pulse_orchestrator-0.3.0/tests/api/test_run_manager_race.py +51 -0
- pulse_orchestrator-0.3.0/tests/api/test_run_thread_failure.py +52 -0
- pulse_orchestrator-0.3.0/tests/api/test_settings_routes.py +267 -0
- pulse_orchestrator-0.3.0/tests/api/test_start_run_brief.py +125 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_docs.py +136 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_domain_imports.py +115 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_domain_typing.py +87 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_factory_seed.py +68 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_file_size.py +55 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_import_contracts.py +136 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_lint_baseline.py +52 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_mutation_gate.py +38 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_no_skip_on_required_dependencies.py +56 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_no_sleep_in_tests.py +83 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_openapi_contract.py +35 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_prompt_injection.py +202 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_release_version.py +15 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_suppressions_carry_a_reason.py +51 -0
- pulse_orchestrator-0.3.0/tests/architecture/test_tests_layout.py +71 -0
- pulse_orchestrator-0.3.0/tests/cli/test_cli.py +79 -0
- pulse_orchestrator-0.3.0/tests/cli/test_cli_commands.py +340 -0
- pulse_orchestrator-0.3.0/tests/cli/test_cli_daemon.py +57 -0
- pulse_orchestrator-0.3.0/tests/cli/test_cli_doctor_json.py +191 -0
- pulse_orchestrator-0.3.0/tests/cli/test_cli_engine_down.py +130 -0
- pulse_orchestrator-0.3.0/tests/client/test_daemon_process_lifecycle.py +216 -0
- pulse_orchestrator-0.3.0/tests/client/test_engine_client_transport.py +557 -0
- pulse_orchestrator-0.3.0/tests/client/test_engine_run_session.py +428 -0
- pulse_orchestrator-0.3.0/tests/client/test_engine_unreachable.py +188 -0
- pulse_orchestrator-0.3.0/tests/client/test_runtime_login.py +19 -0
- pulse_orchestrator-0.3.0/tests/config/test_agent_profiles.py +72 -0
- pulse_orchestrator-0.3.0/tests/config/test_agents_config.py +123 -0
- pulse_orchestrator-0.3.0/tests/config/test_config_commands.py +100 -0
- pulse_orchestrator-0.3.0/tests/config/test_config_updates.py +131 -0
- pulse_orchestrator-0.3.0/tests/config/test_global_config.py +161 -0
- pulse_orchestrator-0.3.0/tests/config/test_global_settings.py +94 -0
- pulse_orchestrator-0.3.0/tests/config/test_model_catalog.py +55 -0
- pulse_orchestrator-0.3.0/tests/config/test_project_config.py +168 -0
- pulse_orchestrator-0.3.0/tests/config/test_project_settings.py +156 -0
- pulse_orchestrator-0.3.0/tests/config/test_resolved_config.py +385 -0
- pulse_orchestrator-0.3.0/tests/config/test_unreadable_cwd.py +88 -0
- pulse_orchestrator-0.3.0/tests/config/test_workflow_config.py +51 -0
- pulse_orchestrator-0.3.0/tests/conftest.py +167 -0
- pulse_orchestrator-0.3.0/tests/doctor/test_doctor_checks.py +125 -0
- pulse_orchestrator-0.3.0/tests/doctor/test_doctor_report.py +97 -0
- pulse_orchestrator-0.3.0/tests/domain/test_branch_name.py +35 -0
- pulse_orchestrator-0.3.0/tests/domain/test_git_option_chain.py +76 -0
- pulse_orchestrator-0.3.0/tests/domain/test_outcome_block.py +184 -0
- pulse_orchestrator-0.3.0/tests/domain/test_ports.py +50 -0
- pulse_orchestrator-0.3.0/tests/domain/test_run_control.py +44 -0
- pulse_orchestrator-0.3.0/tests/domain/test_run_model.py +654 -0
- pulse_orchestrator-0.3.0/tests/domain/test_run_properties.py +362 -0
- pulse_orchestrator-0.3.0/tests/domain/test_task_brief.py +24 -0
- pulse_orchestrator-0.3.0/tests/domain/test_workflow.py +164 -0
- pulse_orchestrator-0.3.0/tests/fakes.py +454 -0
- pulse_orchestrator-0.3.0/tests/history/test_attach_after_resume.py +71 -0
- pulse_orchestrator-0.3.0/tests/history/test_catalog_title.py +47 -0
- pulse_orchestrator-0.3.0/tests/history/test_context_tokens_history.py +172 -0
- pulse_orchestrator-0.3.0/tests/history/test_context_usage.py +65 -0
- pulse_orchestrator-0.3.0/tests/history/test_history_item_codec.py +39 -0
- pulse_orchestrator-0.3.0/tests/history/test_history_log_fidelity.py +457 -0
- pulse_orchestrator-0.3.0/tests/history/test_phase_item.py +84 -0
- pulse_orchestrator-0.3.0/tests/history/test_prompt_detail_records.py +298 -0
- pulse_orchestrator-0.3.0/tests/history/test_run_log.py +105 -0
- pulse_orchestrator-0.3.0/tests/history/test_tool_classify.py +18 -0
- pulse_orchestrator-0.3.0/tests/history/test_tool_detail.py +407 -0
- pulse_orchestrator-0.3.0/tests/infra/test_acp_client.py +104 -0
- pulse_orchestrator-0.3.0/tests/infra/test_acp_client_errors.py +280 -0
- pulse_orchestrator-0.3.0/tests/infra/test_acp_client_process.py +39 -0
- pulse_orchestrator-0.3.0/tests/infra/test_artifact_tracking.py +135 -0
- pulse_orchestrator-0.3.0/tests/infra/test_ask_bridge.py +68 -0
- pulse_orchestrator-0.3.0/tests/infra/test_clarify_loop_factory.py +109 -0
- pulse_orchestrator-0.3.0/tests/infra/test_daemon_meta.py +110 -0
- pulse_orchestrator-0.3.0/tests/infra/test_git_delivery.py +180 -0
- pulse_orchestrator-0.3.0/tests/infra/test_http_bridge.py +167 -0
- pulse_orchestrator-0.3.0/tests/infra/test_list_files.py +61 -0
- pulse_orchestrator-0.3.0/tests/infra/test_mcp_ask_stdio.py +237 -0
- pulse_orchestrator-0.3.0/tests/infra/test_mcp_bridges.py +350 -0
- pulse_orchestrator-0.3.0/tests/infra/test_paths.py +25 -0
- pulse_orchestrator-0.3.0/tests/infra/test_pull_request_command.py +125 -0
- pulse_orchestrator-0.3.0/tests/infra/test_run_events.py +210 -0
- pulse_orchestrator-0.3.0/tests/infra/test_run_events_recorder.py +333 -0
- pulse_orchestrator-0.3.0/tests/infra/test_run_repository.py +239 -0
- pulse_orchestrator-0.3.0/tests/infra/test_run_stop.py +120 -0
- pulse_orchestrator-0.3.0/tests/infra/test_run_store.py +266 -0
- pulse_orchestrator-0.3.0/tests/infra/test_runtimes.py +261 -0
- pulse_orchestrator-0.3.0/tests/infra/test_schema_migrations.py +288 -0
- pulse_orchestrator-0.3.0/tests/infra/test_session_runner.py +238 -0
- pulse_orchestrator-0.3.0/tests/infra/test_session_runner_requests.py +695 -0
- pulse_orchestrator-0.3.0/tests/infra/test_session_timeout.py +193 -0
- pulse_orchestrator-0.3.0/tests/infra/test_sessions.py +52 -0
- pulse_orchestrator-0.3.0/tests/infra/test_step_turns.py +622 -0
- pulse_orchestrator-0.3.0/tests/infra/test_store.py +19 -0
- pulse_orchestrator-0.3.0/tests/infra/test_workflow_defs.py +681 -0
- pulse_orchestrator-0.3.0/tests/infra/test_workspace.py +132 -0
- pulse_orchestrator-0.3.0/tests/infra/test_worktree.py +436 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/conftest.py +13 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/harness.py +96 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_fanout.py +356 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_fanout_expand.py +74 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_git_options.py +322 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_render.py +32 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_resume_and_stop.py +272 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_retry_context.py +264 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_run_context.py +127 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_run_gates.py +101 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_step_failures.py +205 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_step_loops.py +423 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_step_outcome.py +264 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_step_sequence.py +99 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_stop_flow.py +86 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_turn_result.py +66 -0
- pulse_orchestrator-0.3.0/tests/orchestrator/test_user_wait.py +512 -0
- pulse_orchestrator-0.3.0/tests/replies/test_acp_payload_properties.py +337 -0
- pulse_orchestrator-0.3.0/tests/replies/test_acp_payloads_contract.py +461 -0
- pulse_orchestrator-0.3.0/tests/replies/test_approval_classification.py +96 -0
- pulse_orchestrator-0.3.0/tests/replies/test_ask_question_answers.py +349 -0
- pulse_orchestrator-0.3.0/tests/replies/test_permission_decisions.py +103 -0
- pulse_orchestrator-0.3.0/tests/replies/test_permission_policy.py +82 -0
- pulse_orchestrator-0.3.0/tests/replies/test_prompt_choices.py +341 -0
- pulse_orchestrator-0.3.0/tests/replies/test_session_models.py +213 -0
- pulse_orchestrator-0.3.0/tests/replies/test_text_questionnaire.py +79 -0
- pulse_orchestrator-0.3.0/tests/replies/test_text_questionnaire_parsing.py +453 -0
- pulse_orchestrator-0.3.0/tests/tui/conftest.py +48 -0
- pulse_orchestrator-0.3.0/tests/tui/test_artifact_confinement.py +98 -0
- pulse_orchestrator-0.3.0/tests/tui/test_artifact_pane.py +270 -0
- pulse_orchestrator-0.3.0/tests/tui/test_artifact_pane_widget.py +265 -0
- pulse_orchestrator-0.3.0/tests/tui/test_artifacts.py +92 -0
- pulse_orchestrator-0.3.0/tests/tui/test_branch_name_screen.py +76 -0
- pulse_orchestrator-0.3.0/tests/tui/test_cockpit_screen_actions.py +482 -0
- pulse_orchestrator-0.3.0/tests/tui/test_cockpit_sink.py +627 -0
- pulse_orchestrator-0.3.0/tests/tui/test_cockpit_sink_backfill.py +386 -0
- pulse_orchestrator-0.3.0/tests/tui/test_cockpit_state.py +608 -0
- pulse_orchestrator-0.3.0/tests/tui/test_context_usage_display.py +161 -0
- pulse_orchestrator-0.3.0/tests/tui/test_cursor_store.py +191 -0
- pulse_orchestrator-0.3.0/tests/tui/test_engine_gateway.py +166 -0
- pulse_orchestrator-0.3.0/tests/tui/test_file_mention.py +302 -0
- pulse_orchestrator-0.3.0/tests/tui/test_history_detail_screen.py +366 -0
- pulse_orchestrator-0.3.0/tests/tui/test_history_picker.py +301 -0
- pulse_orchestrator-0.3.0/tests/tui/test_history_rows.py +99 -0
- pulse_orchestrator-0.3.0/tests/tui/test_history_tui.py +382 -0
- pulse_orchestrator-0.3.0/tests/tui/test_home_task_form.py +598 -0
- pulse_orchestrator-0.3.0/tests/tui/test_hydrate.py +94 -0
- pulse_orchestrator-0.3.0/tests/tui/test_log_stream.py +85 -0
- pulse_orchestrator-0.3.0/tests/tui/test_menu_list.py +109 -0
- pulse_orchestrator-0.3.0/tests/tui/test_menu_rows.py +71 -0
- pulse_orchestrator-0.3.0/tests/tui/test_onboarding_flow.py +432 -0
- pulse_orchestrator-0.3.0/tests/tui/test_onboarding_screen.py +113 -0
- pulse_orchestrator-0.3.0/tests/tui/test_prompt_bridge.py +160 -0
- pulse_orchestrator-0.3.0/tests/tui/test_prompt_dock.py +333 -0
- pulse_orchestrator-0.3.0/tests/tui/test_prompt_dock_widget.py +183 -0
- pulse_orchestrator-0.3.0/tests/tui/test_prompt_handler_flows.py +543 -0
- pulse_orchestrator-0.3.0/tests/tui/test_resume_restore.py +173 -0
- pulse_orchestrator-0.3.0/tests/tui/test_run_attach.py +287 -0
- pulse_orchestrator-0.3.0/tests/tui/test_screens_without_daemon.py +174 -0
- pulse_orchestrator-0.3.0/tests/tui/test_settings_rows.py +55 -0
- pulse_orchestrator-0.3.0/tests/tui/test_settings_screen.py +482 -0
- pulse_orchestrator-0.3.0/tests/tui/test_stream_workflows.py +511 -0
- pulse_orchestrator-0.3.0/tests/tui/test_strings.py +66 -0
- pulse_orchestrator-0.3.0/tests/tui/test_task_composer.py +105 -0
- pulse_orchestrator-0.3.0/tests/tui/test_tui_navigation.py +626 -0
- pulse_orchestrator-0.3.0/tests/tui/test_tui_smoke.py +361 -0
- pulse_orchestrator-0.3.0/tests/tui/test_worktree_ui.py +430 -0
- pulse_orchestrator-0.3.0/uv.lock +2097 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"skills": {
|
|
4
|
+
"the-judge": {
|
|
5
|
+
"name": "the-judge",
|
|
6
|
+
"source": "local",
|
|
7
|
+
"contentHash": "05526209052f6592ad98476e8f59e9ffa2a24e803e10a90ceac659476b509403",
|
|
8
|
+
"installedAt": "2026-10-06T18:39:26.855Z",
|
|
9
|
+
"updatedAt": "2026-10-06T18:39:26.906Z",
|
|
10
|
+
"agents": [
|
|
11
|
+
"cursor",
|
|
12
|
+
"claude-code",
|
|
13
|
+
"windsurf"
|
|
14
|
+
],
|
|
15
|
+
"method": "copy",
|
|
16
|
+
"global": false
|
|
17
|
+
},
|
|
18
|
+
"tactical-ddd": {
|
|
19
|
+
"name": "tactical-ddd",
|
|
20
|
+
"source": "local",
|
|
21
|
+
"contentHash": "c3dfaf45e8cb784f18d9c460c7f005c4ee9dbb430f21ee8af6913bbfea66a75b",
|
|
22
|
+
"installedAt": "2026-10-07T13:26:12.397Z",
|
|
23
|
+
"updatedAt": "2026-10-07T13:26:12.423Z",
|
|
24
|
+
"agents": [
|
|
25
|
+
"cursor",
|
|
26
|
+
"claude-code",
|
|
27
|
+
"windsurf"
|
|
28
|
+
],
|
|
29
|
+
"method": "copy",
|
|
30
|
+
"global": false
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
description: Run comprehensive Python code quality checks (lint, format, type, test, security, deps)
|
|
2
|
+
argument-hint: "<target-path> --fix"
|
|
3
|
+
allowed-tools: Bash, Read, Grep, Glob
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Run a comprehensive Python code quality pipeline. Parse `$ARGUMENTS`:
|
|
7
|
+
- If `--fix` is present anywhere, enable **autofix mode** (tools auto-correct where possible).
|
|
8
|
+
- The remaining argument is the target path. Defaults to `.` if not provided.
|
|
9
|
+
- **Sanitize the target path:** reject any path containing shell metacharacters (`;`, `|`, `&`, `$`, backticks). Always wrap the target path in double quotes in all shell commands.
|
|
10
|
+
|
|
11
|
+
Execute all phases sequentially, producing a final structured report.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Authoritative Python References
|
|
16
|
+
|
|
17
|
+
Use these as source of truth when judging patterns and as tie-breakers for recommendations.
|
|
18
|
+
|
|
19
|
+
| Domain | Reference |
|
|
20
|
+
|---|---|
|
|
21
|
+
| **Logging** | [Logging HOWTO](https://docs.python.org/3/howto/logging.html) — prefer `logger = logging.getLogger(__name__)`, module-level loggers, lazy formatting |
|
|
22
|
+
| **Exceptions** | [Errors & Exceptions](https://docs.python.org/3/tutorial/errors.html) — specific except clauses, proper re-raise with `raise ... from`, avoid bare `except:` |
|
|
23
|
+
| **Stdlib Security** | [Security Considerations](https://docs.python.org/3/library/security_warnings.html) — `random` vs `secrets`, `pickle` with untrusted data, `subprocess` shell=True, `tempfile.mktemp` |
|
|
24
|
+
|
|
25
|
+
**Tool references** (use to explain tool output):
|
|
26
|
+
Ruff: https://docs.astral.sh/ruff/ · Black: https://black.readthedocs.io/ · mypy: https://mypy.readthedocs.io/ · pytest: https://docs.pytest.org/ · pre-commit: https://pre-commit.com/ · Bandit: https://bandit.readthedocs.io/ · pip-audit: https://github.com/pypa/pip-audit · pycodestyle: https://pycodestyle.pycqa.org/ · pydocstyle: https://pep257.readthedocs.io/
|
|
27
|
+
|
|
28
|
+
### Reporting rule (required)
|
|
29
|
+
|
|
30
|
+
For **any** finding related to Logging, Exceptions, or Stdlib-Security, include a `Ref:` line in the Fix Suggestions section pointing to the relevant Python doc above. Examples:
|
|
31
|
+
```
|
|
32
|
+
3. [S311] use of random for cryptographic purposes at crypto.py:18 (severity: HIGH)
|
|
33
|
+
FIX: Replace random.randint() with secrets.randbelow()
|
|
34
|
+
Ref: https://docs.python.org/3/library/security_warnings.html
|
|
35
|
+
|
|
36
|
+
4. [LOG001] bare logging.warning() call at handler.py:55 (severity: MED)
|
|
37
|
+
FIX: Use module logger: logger = logging.getLogger(__name__); logger.warning(...)
|
|
38
|
+
Ref: https://docs.python.org/3/howto/logging.html
|
|
39
|
+
|
|
40
|
+
5. [B001] bare except clause at service.py:30 (severity: MED)
|
|
41
|
+
FIX: Catch specific exceptions: except ValueError as e:
|
|
42
|
+
Ref: https://docs.python.org/3/tutorial/errors.html
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Output Management (IMPORTANT — follow throughout all phases)
|
|
48
|
+
|
|
49
|
+
Tool output on real codebases can be enormous. To avoid overwhelming context:
|
|
50
|
+
|
|
51
|
+
- **General rule:** if any command produces more than 80 lines of output, show only the first 40 lines and the final summary line, then note `"... and N more (truncated)"`.
|
|
52
|
+
- **Ruff lint:** use `--output-format=concise` for compact one-line-per-violation output. If output exceeds 40 lines, show the first 40 and the final summary line (e.g., `Found N errors [M fixable]`).
|
|
53
|
+
- **Ruff format:** in normal mode, use `--check` **without** `--diff` to get just the list of files needing formatting. Only add `--diff` if 5 or fewer files need changes.
|
|
54
|
+
- **mypy/pyright/ty:** capture the summary line at the end (e.g., `Found 42 errors in 15 files`). Only show individual errors if count < 30.
|
|
55
|
+
- **pytest:** the `-q` flag keeps it concise. If output exceeds 80 lines, focus on the summary line.
|
|
56
|
+
- **vulture:** if > 40 items, report only the count.
|
|
57
|
+
- **JSON output (bandit, pip-audit, pip list):** read the JSON output and extract only the relevant summary (issue count, package names, severity levels). Never include raw JSON in the final report.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Phase 1: Discovery
|
|
62
|
+
|
|
63
|
+
### 1a. Configuration files
|
|
64
|
+
|
|
65
|
+
Check for and read these files (if they exist) at the project root:
|
|
66
|
+
- `pyproject.toml` — note sections: `[tool.ruff]`, `[tool.ruff.lint]`, `[tool.mypy]`, `[tool.pytest.ini_options]`, `[tool.coverage.run]`
|
|
67
|
+
- `setup.cfg`
|
|
68
|
+
- `.pre-commit-config.yaml`
|
|
69
|
+
- `ruff.toml` or `.ruff.toml`
|
|
70
|
+
- `.flake8`
|
|
71
|
+
- `mypy.ini` or `.mypy.ini`
|
|
72
|
+
- `tox.ini`
|
|
73
|
+
- `uv.lock`, `poetry.lock`, `Pipfile.lock`
|
|
74
|
+
- `.python-version`
|
|
75
|
+
|
|
76
|
+
### 1b. Pre-commit hook detection
|
|
77
|
+
|
|
78
|
+
From `.pre-commit-config.yaml`, extract hooks. Inspect both the `repo` URL and hook `id`:
|
|
79
|
+
- `ruff` / `ruff-pre-commit` (repo contains `astral-sh/ruff`) → covers Ruff check
|
|
80
|
+
- `ruff-format` → covers Ruff format
|
|
81
|
+
- `black` / `black-jupyter` → covers formatting
|
|
82
|
+
- `mypy` / `mirrors-mypy` → covers mypy
|
|
83
|
+
- `pyright` → covers pyright
|
|
84
|
+
- `pycodestyle` / `flake8` → covers pycodestyle
|
|
85
|
+
- `pydocstyle` → covers pydocstyle
|
|
86
|
+
- `bandit` → covers Bandit
|
|
87
|
+
- `isort` → covers import sorting
|
|
88
|
+
|
|
89
|
+
### 1c. Virtual environment detection (CRITICAL)
|
|
90
|
+
|
|
91
|
+
Many projects install tools only inside a virtualenv. Detect and configure the command prefix.
|
|
92
|
+
|
|
93
|
+
**Check in this order** (manager-based prefixes first — they handle env resolution automatically):
|
|
94
|
+
|
|
95
|
+
1. Check if `$VIRTUAL_ENV` is already set (venv is active) — tools are on PATH, no prefix needed.
|
|
96
|
+
2. If `uv.lock` exists → use `uv run` as prefix. However, `uv run` only works for tools in the project's dependencies. When checking tool availability, if `uv run {tool} --version` fails, also try bare `{tool} --version` (system PATH fallback) before declaring the tool missing.
|
|
97
|
+
3. If `poetry.lock` exists → use `poetry run` as prefix. Same fallback logic: if `poetry run {tool} --version` fails, try bare `{tool} --version`.
|
|
98
|
+
4. If none of the above matched, check for venv directories: `.venv/bin/python`, `venv/bin/python`, `.env/bin/python`. If found, resolve the venv bin directory to an **absolute path** (e.g., `/Users/me/project/.venv/bin/`) and prefix commands with it. This prevents breakage if commands run from a subdirectory. Same fallback: if the prefixed command fails, try bare command.
|
|
99
|
+
5. If nothing matched, use bare commands (system-level tools).
|
|
100
|
+
|
|
101
|
+
Store the resolved primary prefix and apply it to tool commands. Remember the fallback-to-system-PATH rule for every tool availability check.
|
|
102
|
+
|
|
103
|
+
### 1d. Ruff config detection
|
|
104
|
+
|
|
105
|
+
Determine whether the project has **lint-level** Ruff configuration:
|
|
106
|
+
- `has_ruff_lint_config = true` if ANY of these exist:
|
|
107
|
+
- `ruff.toml` or `.ruff.toml` file exists
|
|
108
|
+
- `pyproject.toml` contains `[tool.ruff.lint]` with `select` or `extend-select` keys
|
|
109
|
+
- `pyproject.toml` contains `[tool.ruff]` with `select` or `extend-select` keys
|
|
110
|
+
- If `has_ruff_lint_config` is false, the skill will provide its own `--select` rules.
|
|
111
|
+
|
|
112
|
+
### 1e. Detect source layout
|
|
113
|
+
|
|
114
|
+
Identify the project's source directory for accurate type checking and coverage:
|
|
115
|
+
- If `pyproject.toml` has `[tool.coverage.run]` with `source`, record that as `SOURCE_DIR`.
|
|
116
|
+
- Else if a `src/` layout exists (directory `src/` with a Python package inside), set `SOURCE_DIR` to `src`.
|
|
117
|
+
- Else if there is exactly one top-level directory containing `__init__.py`, use that as `SOURCE_DIR`.
|
|
118
|
+
- Otherwise, **leave `SOURCE_DIR` unset**. (Do NOT default to `.` — that causes `--cov=.` which inflates coverage by including test files.)
|
|
119
|
+
|
|
120
|
+
### 1f. Verify Python files exist
|
|
121
|
+
|
|
122
|
+
Quick check: run `find "{TARGET_PATH}" -name "*.py" -type f -print -quit` (prints first match and stops). If no `.py` files are found, skip all subsequent phases and report: "No Python files found at target path. Nothing to analyze."
|
|
123
|
+
|
|
124
|
+
### 1g. Package manager and Python version
|
|
125
|
+
|
|
126
|
+
- Detect package manager: `uv.lock` → uv, `poetry.lock` → poetry, `Pipfile.lock` → pipenv, else pip.
|
|
127
|
+
- Record Python version: run `{CMD_PREFIX}python --version`.
|
|
128
|
+
|
|
129
|
+
### State to track
|
|
130
|
+
|
|
131
|
+
As you complete each phase, keep mental note of:
|
|
132
|
+
- `CMD_PREFIX`: command prefix from 1c (always an absolute path if venv-based)
|
|
133
|
+
- `TARGET_PATH`: sanitized target path (always quoted in commands)
|
|
134
|
+
- `SOURCE_DIR`: source directory from 1e, or unset
|
|
135
|
+
- `has_ruff_lint_config`: boolean from 1d
|
|
136
|
+
- `pre_commit_hooks`: list of hook IDs that **completed successfully** in Phase 2
|
|
137
|
+
- `missing_tools`: tools not installed (with pip install commands)
|
|
138
|
+
- Phase results and issues found (compiled into the report in Phase 8)
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Phase 2: Pre-commit
|
|
143
|
+
|
|
144
|
+
**Condition:** Only run if `.pre-commit-config.yaml` exists in the project root.
|
|
145
|
+
|
|
146
|
+
1. Check if pre-commit is installed:
|
|
147
|
+
```bash
|
|
148
|
+
{CMD_PREFIX}pre-commit --version 2>/dev/null
|
|
149
|
+
```
|
|
150
|
+
If not installed, record as missing (`pip install pre-commit`) and skip.
|
|
151
|
+
|
|
152
|
+
2. Run pre-commit. Use the Bash tool's timeout parameter set to 120000ms (2 minutes) to avoid hanging on first-run hook installation:
|
|
153
|
+
```bash
|
|
154
|
+
{CMD_PREFIX}pre-commit run --all-files --show-diff-on-failure 2>&1 || true
|
|
155
|
+
```
|
|
156
|
+
If the command times out, record: "Pre-commit timed out after 120s (may need hook installation) — skipping."
|
|
157
|
+
|
|
158
|
+
3. Parse the output. Note which **specific hooks** passed or auto-fixed files. If any hooks auto-fixed files, note: "Pre-commit auto-fixed files — subsequent phases will check the post-fix state."
|
|
159
|
+
|
|
160
|
+
4. Only mark a tool as "covered by pre-commit" if its corresponding hook **completed successfully** (passed or auto-fixed). A hook that failed or was skipped does NOT count as coverage.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Phase 3: Lint, Format, Security, Imports & Complexity
|
|
165
|
+
|
|
166
|
+
**Strategy:** Use Ruff as the unified tool when available. Fall back to individual tools only when Ruff is not installed.
|
|
167
|
+
|
|
168
|
+
### 3a. Check for Ruff
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
{CMD_PREFIX}ruff --version 2>/dev/null
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### If Ruff IS available (preferred path):
|
|
175
|
+
|
|
176
|
+
**Skip all of:** Black, pycodestyle, pydocstyle, Bandit, isort. Ruff covers them.
|
|
177
|
+
|
|
178
|
+
**Always run Ruff in Phase 3**, even if pre-commit also ran Ruff. Ruff is fast (~100ms on most projects), and re-running ensures consistent rule coverage — pre-commit hooks may use different `args` or rule sets. If pre-commit auto-fixed files, this run checks the post-fix state, which is useful.
|
|
179
|
+
|
|
180
|
+
**Linting:**
|
|
181
|
+
|
|
182
|
+
If `has_ruff_lint_config` is true (project has its own Ruff lint rules):
|
|
183
|
+
```bash
|
|
184
|
+
# Respect project config — do not pass --select
|
|
185
|
+
# In --fix mode:
|
|
186
|
+
{CMD_PREFIX}ruff check --output-format=concise --fix "{TARGET_PATH}" 2>&1 || true
|
|
187
|
+
# In normal mode:
|
|
188
|
+
{CMD_PREFIX}ruff check --output-format=concise "{TARGET_PATH}" 2>&1 || true
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
If `has_ruff_lint_config` is false (no project-level lint config):
|
|
192
|
+
```bash
|
|
193
|
+
# Provide sensible defaults
|
|
194
|
+
# In --fix mode:
|
|
195
|
+
{CMD_PREFIX}ruff check --select E,W,F,I,S,C90,UP,B,A,SIM --output-format=concise --fix "{TARGET_PATH}" 2>&1 || true
|
|
196
|
+
# In normal mode:
|
|
197
|
+
{CMD_PREFIX}ruff check --select E,W,F,I,S,C90,UP,B,A,SIM --output-format=concise "{TARGET_PATH}" 2>&1 || true
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
What the default rules cover:
|
|
201
|
+
- `E,W` — pycodestyle (PEP 8)
|
|
202
|
+
- `F` — pyflakes (undefined names, unused imports)
|
|
203
|
+
- `I` — isort (import sorting)
|
|
204
|
+
- `S` — flake8-bandit (security — replaces standalone Bandit)
|
|
205
|
+
- `C90` — mccabe (cyclomatic complexity, threshold 10)
|
|
206
|
+
- `UP` — pyupgrade (modernize Python syntax)
|
|
207
|
+
- `B` — flake8-bugbear (common bugs and design problems)
|
|
208
|
+
- `A` — flake8-builtins (shadowing builtins)
|
|
209
|
+
- `SIM` — flake8-simplify (simplification opportunities)
|
|
210
|
+
|
|
211
|
+
**Why `D` (pydocstyle) and `N` (pep8-naming) are excluded from defaults:**
|
|
212
|
+
- `D` rules produce hundreds of warnings on any project without a configured docstring convention (`google`, `numpy`, `pep257`). If the project's Ruff config includes `[tool.ruff.lint.pydocstyle]` with a `convention`, they will be included via the project-config path.
|
|
213
|
+
- `N` rules produce false positives with common patterns (unittest methods, library conventions).
|
|
214
|
+
|
|
215
|
+
**Formatting:**
|
|
216
|
+
```bash
|
|
217
|
+
# In --fix mode:
|
|
218
|
+
{CMD_PREFIX}ruff format "{TARGET_PATH}" 2>&1 || true
|
|
219
|
+
# In normal mode (no --diff to avoid enormous output; just list files):
|
|
220
|
+
{CMD_PREFIX}ruff format --check "{TARGET_PATH}" 2>&1 || true
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Add to fix commands (with issue counts if applicable):
|
|
224
|
+
- `ruff check --fix .`
|
|
225
|
+
- `ruff format .`
|
|
226
|
+
|
|
227
|
+
### If Ruff is NOT available (fallback path):
|
|
228
|
+
|
|
229
|
+
Run individual tools. Each tool: check availability with `{CMD_PREFIX}tool --version 2>/dev/null` (with system PATH fallback per 1c), skip if not installed (record in `missing_tools`). Skip any tool whose pre-commit hook completed successfully.
|
|
230
|
+
|
|
231
|
+
**3b. Black:**
|
|
232
|
+
```bash
|
|
233
|
+
{CMD_PREFIX}black --check --diff "{TARGET_PATH}" 2>&1 || true
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**3c. pycodestyle** (skip if flake8 ran via pre-commit):
|
|
237
|
+
```bash
|
|
238
|
+
{CMD_PREFIX}pycodestyle "{TARGET_PATH}" 2>&1 || true
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**3d. Bandit** (security):
|
|
242
|
+
```bash
|
|
243
|
+
{CMD_PREFIX}bandit -r "{TARGET_PATH}" -f json 2>&1 || true
|
|
244
|
+
```
|
|
245
|
+
Read the output. Bandit writes JSON to stdout and logging to stderr — both may appear in the output. Look for the JSON object with a `results` key. An empty `results` array means no issues (PASS). If the output contains no valid JSON, Bandit likely crashed — record as "Bandit error" and note the error message.
|
|
246
|
+
|
|
247
|
+
For security findings, reference:
|
|
248
|
+
- B101 (assert): stripped in optimized bytecode, never use for access control
|
|
249
|
+
- B301/B302 (pickle): arbitrary code execution risk
|
|
250
|
+
- B608 (SQL injection): use parameterized queries
|
|
251
|
+
- B403 (subprocess): shell injection risk
|
|
252
|
+
|
|
253
|
+
**3e. isort:**
|
|
254
|
+
```bash
|
|
255
|
+
{CMD_PREFIX}isort --check-only --diff "{TARGET_PATH}" 2>&1 || true
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Phase 4: Type Check
|
|
261
|
+
|
|
262
|
+
**Skip if pre-commit already ran the type checker successfully.**
|
|
263
|
+
|
|
264
|
+
Detect and use the best available type checker. Priority order (most reliable first):
|
|
265
|
+
|
|
266
|
+
1. **mypy** (most established, best ecosystem support):
|
|
267
|
+
```bash
|
|
268
|
+
{CMD_PREFIX}mypy --version 2>/dev/null
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
2. **pyright** (faster, checks unannotated code by default):
|
|
272
|
+
```bash
|
|
273
|
+
{CMD_PREFIX}pyright --version 2>/dev/null
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
3. **ty** (fastest, but still in beta — results may be incomplete):
|
|
277
|
+
```bash
|
|
278
|
+
{CMD_PREFIX}ty --version 2>/dev/null
|
|
279
|
+
```
|
|
280
|
+
If ty is the only checker available, note in the report: "ty is beta — results may have gaps."
|
|
281
|
+
|
|
282
|
+
If none are installed, record as missing (`pip install mypy`).
|
|
283
|
+
|
|
284
|
+
### mypy-specific hardening (IMPORTANT):
|
|
285
|
+
|
|
286
|
+
If mypy is the selected checker:
|
|
287
|
+
- If **no mypy config exists** (no `[tool.mypy]` in pyproject.toml, no `mypy.ini`, no `.mypy.ini`, no mypy section in `setup.cfg`), add these flags:
|
|
288
|
+
- `--ignore-missing-imports` — suppresses noise from untyped third-party libraries
|
|
289
|
+
- `--exclude '(\.venv|venv|\.env|\.git|node_modules|build|dist|__pycache__)'` — prevents scanning non-source directories
|
|
290
|
+
- If a mypy config exists, trust it and run without extra flags.
|
|
291
|
+
- **Never** run `--install-types` — it modifies the environment without user consent.
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
# With config:
|
|
295
|
+
{CMD_PREFIX}mypy "{TARGET_PATH}" 2>&1 || true
|
|
296
|
+
# Without config:
|
|
297
|
+
{CMD_PREFIX}mypy --ignore-missing-imports --exclude '(\.venv|venv|\.env|\.git|node_modules|build|dist|__pycache__)' "{TARGET_PATH}" 2>&1 || true
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Phase 5: Tests + Coverage
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
{CMD_PREFIX}pytest --version 2>/dev/null
|
|
306
|
+
```
|
|
307
|
+
If not installed, record as missing (`pip install pytest`) and skip.
|
|
308
|
+
|
|
309
|
+
### Determine test path
|
|
310
|
+
|
|
311
|
+
Do NOT blindly pass `$TARGET_PATH` to pytest — tests often live in a different directory:
|
|
312
|
+
- If `[tool.pytest.ini_options]` in `pyproject.toml` has `testpaths`, use those paths.
|
|
313
|
+
- Else if `$TARGET_PATH` is `.`, let pytest use its default discovery (pass no path argument).
|
|
314
|
+
- Else if `$TARGET_PATH` points to a source directory (not `tests/`), check if `tests/` or `test/` exists at the project root and use that instead.
|
|
315
|
+
- Otherwise, pass `$TARGET_PATH` as-is.
|
|
316
|
+
|
|
317
|
+
### Determine coverage source
|
|
318
|
+
|
|
319
|
+
Check if pytest-cov is available:
|
|
320
|
+
```bash
|
|
321
|
+
{CMD_PREFIX}python -c "import pytest_cov" 2>/dev/null
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Coverage is only included if `SOURCE_DIR` is set (from Phase 1e). If `SOURCE_DIR` is unset, skip coverage — running `--cov=.` inflates numbers by including test files.
|
|
325
|
+
|
|
326
|
+
### Run tests
|
|
327
|
+
|
|
328
|
+
If pytest-cov is available AND `SOURCE_DIR` is set:
|
|
329
|
+
```bash
|
|
330
|
+
{CMD_PREFIX}pytest {TEST_PATH} --tb=short -q --cov="{SOURCE_DIR}" --cov-report=term:skip-covered --cov-branch --cov-fail-under=0 2>&1 || true
|
|
331
|
+
```
|
|
332
|
+
Notes:
|
|
333
|
+
- `term:skip-covered` omits files with 100% coverage from the report, keeping output compact. The overall percentage is still shown.
|
|
334
|
+
- `--cov-fail-under=0` overrides any project-level `fail_under` threshold so low coverage doesn't mask actual test pass/fail results in this pipeline.
|
|
335
|
+
|
|
336
|
+
If pytest-cov is unavailable or `SOURCE_DIR` is unset:
|
|
337
|
+
```bash
|
|
338
|
+
{CMD_PREFIX}pytest {TEST_PATH} --tb=short -q 2>&1 || true
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Record: tests passed, failed, skipped, errors, and coverage percentage (if available). If pytest-cov is missing, add to missing tools: `pip install pytest-cov` (informational).
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## Phase 6: Dependency Audit
|
|
346
|
+
|
|
347
|
+
### 6a. Vulnerability scan
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
{CMD_PREFIX}pip-audit --version 2>/dev/null
|
|
351
|
+
```
|
|
352
|
+
If not installed, record as missing (`pip install pip-audit`) and skip.
|
|
353
|
+
|
|
354
|
+
If installed:
|
|
355
|
+
```bash
|
|
356
|
+
{CMD_PREFIX}pip-audit --format=json 2>&1 || true
|
|
357
|
+
```
|
|
358
|
+
Read the output. Look for valid JSON with a `dependencies` key. If the output contains no valid JSON, pip-audit likely failed — record the error message. For successful runs, extract vulnerability count and affected packages. Add upgrade commands to fix commands.
|
|
359
|
+
|
|
360
|
+
### 6b. Outdated dependencies (informational)
|
|
361
|
+
|
|
362
|
+
For uv-managed projects, use the built-in `uv pip` subcommand (no `run` prefix needed):
|
|
363
|
+
```bash
|
|
364
|
+
uv pip list --outdated --format=json 2>/dev/null || true
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
For all other projects:
|
|
368
|
+
```bash
|
|
369
|
+
{CMD_PREFIX}pip list --outdated --format=json 2>/dev/null || true
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Read the JSON. If more than 20 outdated packages, report only the count and the 5 with the largest version gap. This is **informational only** — never mark as failure.
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Phase 7: Dead Code Detection (Optional/Informational)
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
{CMD_PREFIX}vulture --version 2>/dev/null
|
|
380
|
+
```
|
|
381
|
+
If not installed, note in missing tools (`pip install vulture`) and skip. This phase is optional.
|
|
382
|
+
|
|
383
|
+
If installed:
|
|
384
|
+
```bash
|
|
385
|
+
{CMD_PREFIX}vulture "{TARGET_PATH}" --min-confidence 80 2>&1 || true
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
Mark all results as **informational** (severity: LOW). Dead code detection has inherent false positives from dynamic imports, plugin systems, framework magic (Django models, Flask routes, pytest fixtures, etc.).
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## Phase 8: Report
|
|
393
|
+
|
|
394
|
+
Run `{CMD_PREFIX}python --version 2>&1` if not already captured.
|
|
395
|
+
|
|
396
|
+
Produce this structured summary:
|
|
397
|
+
|
|
398
|
+
```
|
|
399
|
+
=== PYTHON QUALITY REPORT ===
|
|
400
|
+
Target: <target path>
|
|
401
|
+
Mode: <normal | autofix>
|
|
402
|
+
Python: <version>
|
|
403
|
+
Env: <venv (.venv) | uv | poetry | system>
|
|
404
|
+
|
|
405
|
+
--- Phase Results ---
|
|
406
|
+
1. Discovery: OK — <config files found, env detected>
|
|
407
|
+
2. Pre-commit: <PASS | FAIL | SKIP | TIMEOUT> — <N hooks passed, M failed>
|
|
408
|
+
3. Lint/Format/Security: <PASS | FAIL | SKIP> — <tool(s) used>: <issue counts by category>
|
|
409
|
+
4. Type Check: <PASS | FAIL | SKIP> — <tool used>: <error count>
|
|
410
|
+
5. Tests + Coverage: <PASS | FAIL | SKIP> — <passed/failed/skipped> (coverage: <N%> | n/a)
|
|
411
|
+
6. Dep Audit: <PASS | FAIL | SKIP> — <vulnerability count>, <N outdated>
|
|
412
|
+
7. Dead Code: <INFO | SKIP> — <N unused items found>
|
|
413
|
+
|
|
414
|
+
--- Missing Tools ---
|
|
415
|
+
<list each missing tool with its pip install command, or "None — all tools available">
|
|
416
|
+
Install all: pip install <space-separated list>
|
|
417
|
+
|
|
418
|
+
--- Top 5 Issues ---
|
|
419
|
+
<Prioritized by severity:
|
|
420
|
+
1. Security vulnerabilities / dependency CVEs (HIGH)
|
|
421
|
+
2. Test failures (HIGH)
|
|
422
|
+
3. Type errors (MED)
|
|
423
|
+
4. Lint errors — bugs/bugbear (MED)
|
|
424
|
+
5. Style/format issues (LOW)
|
|
425
|
+
Format:
|
|
426
|
+
N. [RULE_CODE] description at FILE:LINE (severity: HIGH|MED|LOW)
|
|
427
|
+
If fewer than 5 issues, list all. If no issues: "No issues found.">
|
|
428
|
+
|
|
429
|
+
--- Fix Suggestions ---
|
|
430
|
+
<For each top issue, a concrete fix:
|
|
431
|
+
1. [S105] hardcoded-password-string at auth.py:42
|
|
432
|
+
FIX: password = os.environ["DB_PASSWORD"]
|
|
433
|
+
2. [D100] Missing docstring at utils.py:1
|
|
434
|
+
FIX: Add module docstring
|
|
435
|
+
If no issues: omit this section entirely.>
|
|
436
|
+
|
|
437
|
+
--- Quick Fix Commands ---
|
|
438
|
+
<Copy-pasteable commands with {CMD_PREFIX} resolved to actual prefix:>
|
|
439
|
+
ruff check --fix . # Auto-fix N linting issues
|
|
440
|
+
ruff format . # Auto-format N files
|
|
441
|
+
pip install --upgrade PKG>=X.Y # Fix CVE-YYYY-NNNNN
|
|
442
|
+
<If in autofix mode: "Auto-fix already applied. N issues remain requiring manual fixes.">
|
|
443
|
+
<If no fixes needed: "No auto-fixable issues found.">
|
|
444
|
+
|
|
445
|
+
--- Verdict ---
|
|
446
|
+
<PASS | WARN | FAIL>
|
|
447
|
+
FAIL if: any HIGH severity security issue, any test failure, any dependency vulnerability with known exploit
|
|
448
|
+
WARN if: medium-severity lint issues, coverage < 60%, outdated deps, missing tools
|
|
449
|
+
PASS if: all clean or only LOW informational items
|
|
450
|
+
=== END REPORT ===
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
**Important notes:**
|
|
454
|
+
- All paths in shell commands MUST be wrapped in double quotes.
|
|
455
|
+
- All `|| true` suffixes prevent a failing tool from halting the pipeline.
|
|
456
|
+
- Group issues by tool and sort by severity.
|
|
457
|
+
- When Ruff has project-level lint config, respect it — do not pass `--select`.
|
|
458
|
+
- In autofix mode, report what was auto-fixed and what remains as manual work.
|
|
459
|
+
|
|
460
|
+
**Single-file target:** If `$TARGET_PATH` is a specific `.py` file (not a directory):
|
|
461
|
+
- Ruff check, Ruff format, mypy, pyright, ty, vulture, bandit: pass the file path directly — all support single-file arguments.
|
|
462
|
+
- pytest: only pass the file to pytest if it matches `test_*.py` or `*_test.py`. Otherwise, use default test discovery (no path argument) and skip coverage.
|
|
463
|
+
- pip-audit, outdated deps: run as normal (they audit the environment, not individual files).
|
|
464
|
+
- pre-commit: run as normal (`--all-files` is independent of the target argument).
|
|
465
|
+
- Coverage: skip `--cov` for single-file targets (coverage of one file requires knowing its importable module name).
|