@event4u/agent-config 1.9.1
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.
- package/.agent-src/README.md +64 -0
- package/.agent-src/commands/agent-handoff.md +64 -0
- package/.agent-src/commands/agent-status.md +83 -0
- package/.agent-src/commands/agents-audit.md +243 -0
- package/.agent-src/commands/agents-cleanup.md +169 -0
- package/.agent-src/commands/agents-prepare.md +137 -0
- package/.agent-src/commands/analyze-reference-repo.md +191 -0
- package/.agent-src/commands/bug-fix.md +181 -0
- package/.agent-src/commands/bug-investigate.md +175 -0
- package/.agent-src/commands/commit.md +121 -0
- package/.agent-src/commands/compress.md +177 -0
- package/.agent-src/commands/config-agent-settings.md +126 -0
- package/.agent-src/commands/context-create.md +167 -0
- package/.agent-src/commands/context-refactor.md +170 -0
- package/.agent-src/commands/copilot-agents-init.md +150 -0
- package/.agent-src/commands/copilot-agents-optimize.md +251 -0
- package/.agent-src/commands/create-pr-description.md +112 -0
- package/.agent-src/commands/create-pr.md +76 -0
- package/.agent-src/commands/do-and-judge.md +114 -0
- package/.agent-src/commands/do-in-steps.md +84 -0
- package/.agent-src/commands/e2e-heal.md +98 -0
- package/.agent-src/commands/e2e-plan.md +85 -0
- package/.agent-src/commands/estimate-ticket.md +80 -0
- package/.agent-src/commands/feature-dev.md +111 -0
- package/.agent-src/commands/feature-explore.md +180 -0
- package/.agent-src/commands/feature-plan.md +288 -0
- package/.agent-src/commands/feature-refactor.md +181 -0
- package/.agent-src/commands/feature-roadmap.md +184 -0
- package/.agent-src/commands/fix-ci.md +48 -0
- package/.agent-src/commands/fix-portability.md +97 -0
- package/.agent-src/commands/fix-pr-bot-comments.md +146 -0
- package/.agent-src/commands/fix-pr-comments.md +58 -0
- package/.agent-src/commands/fix-pr-developer-comments.md +152 -0
- package/.agent-src/commands/fix-references.md +94 -0
- package/.agent-src/commands/fix-seeder.md +146 -0
- package/.agent-src/commands/implement-ticket.md +133 -0
- package/.agent-src/commands/jira-ticket.md +71 -0
- package/.agent-src/commands/judge.md +86 -0
- package/.agent-src/commands/memory-add.md +130 -0
- package/.agent-src/commands/memory-full.md +97 -0
- package/.agent-src/commands/memory-promote.md +144 -0
- package/.agent-src/commands/mode.md +121 -0
- package/.agent-src/commands/module-create.md +132 -0
- package/.agent-src/commands/module-explore.md +157 -0
- package/.agent-src/commands/optimize-agents.md +139 -0
- package/.agent-src/commands/optimize-augmentignore.md +262 -0
- package/.agent-src/commands/optimize-rtk-filters.md +120 -0
- package/.agent-src/commands/optimize-skills.md +121 -0
- package/.agent-src/commands/override-create.md +97 -0
- package/.agent-src/commands/override-manage.md +96 -0
- package/.agent-src/commands/package-reset.md +154 -0
- package/.agent-src/commands/package-test.md +154 -0
- package/.agent-src/commands/prepare-for-review.md +91 -0
- package/.agent-src/commands/project-analyze.md +300 -0
- package/.agent-src/commands/project-health.md +95 -0
- package/.agent-src/commands/propose-memory.md +108 -0
- package/.agent-src/commands/quality-fix.md +106 -0
- package/.agent-src/commands/refine-ticket.md +81 -0
- package/.agent-src/commands/review-changes.md +130 -0
- package/.agent-src/commands/review-routing.md +111 -0
- package/.agent-src/commands/roadmap-create.md +110 -0
- package/.agent-src/commands/roadmap-execute.md +68 -0
- package/.agent-src/commands/rule-compliance-audit.md +139 -0
- package/.agent-src/commands/tests-create.md +73 -0
- package/.agent-src/commands/tests-execute.md +58 -0
- package/.agent-src/commands/threat-model.md +115 -0
- package/.agent-src/commands/update-form-request-messages.md +189 -0
- package/.agent-src/commands/upstream-contribute.md +171 -0
- package/.agent-src/contexts/augment-infrastructure.md +181 -0
- package/.agent-src/contexts/documentation-hierarchy.md +142 -0
- package/.agent-src/contexts/model-recommendations.md +142 -0
- package/.agent-src/contexts/override-system.md +187 -0
- package/.agent-src/contexts/skills-and-commands.md +154 -0
- package/.agent-src/contexts/subagent-configuration.md +62 -0
- package/.agent-src/guidelines/agent-infra/agent-interaction-and-decision-quality.md +110 -0
- package/.agent-src/guidelines/agent-infra/break-glass-usage.md +113 -0
- package/.agent-src/guidelines/agent-infra/developer-judgment.md +82 -0
- package/.agent-src/guidelines/agent-infra/engineering-memory-data-format.md +117 -0
- package/.agent-src/guidelines/agent-infra/layered-settings.md +158 -0
- package/.agent-src/guidelines/agent-infra/memory-access.md +121 -0
- package/.agent-src/guidelines/agent-infra/naming.md +69 -0
- package/.agent-src/guidelines/agent-infra/output-patterns.md +117 -0
- package/.agent-src/guidelines/agent-infra/review-routing-data-format.md +144 -0
- package/.agent-src/guidelines/agent-infra/role-contracts.md +211 -0
- package/.agent-src/guidelines/agent-infra/role-mode-router.md +89 -0
- package/.agent-src/guidelines/agent-infra/runtime-layer.md +89 -0
- package/.agent-src/guidelines/agent-infra/self-improvement-pipeline.md +135 -0
- package/.agent-src/guidelines/agent-infra/size-and-scope.md +189 -0
- package/.agent-src/guidelines/agent-infra/tool-integration.md +73 -0
- package/.agent-src/guidelines/docs/readme-size-and-splitting.md +153 -0
- package/.agent-src/guidelines/e2e/playwright.md +363 -0
- package/.agent-src/guidelines/php/api-design.md +115 -0
- package/.agent-src/guidelines/php/artisan-commands.md +81 -0
- package/.agent-src/guidelines/php/blade-ui.md +78 -0
- package/.agent-src/guidelines/php/controllers.md +90 -0
- package/.agent-src/guidelines/php/database.md +111 -0
- package/.agent-src/guidelines/php/eloquent.md +208 -0
- package/.agent-src/guidelines/php/flux.md +80 -0
- package/.agent-src/guidelines/php/general.md +191 -0
- package/.agent-src/guidelines/php/git.md +96 -0
- package/.agent-src/guidelines/php/jobs.md +111 -0
- package/.agent-src/guidelines/php/livewire.md +71 -0
- package/.agent-src/guidelines/php/logging.md +79 -0
- package/.agent-src/guidelines/php/naming.md +89 -0
- package/.agent-src/guidelines/php/patterns/dependency-injection.md +57 -0
- package/.agent-src/guidelines/php/patterns/dtos.md +199 -0
- package/.agent-src/guidelines/php/patterns/events.md +67 -0
- package/.agent-src/guidelines/php/patterns/factory.md +53 -0
- package/.agent-src/guidelines/php/patterns/pipelines.md +66 -0
- package/.agent-src/guidelines/php/patterns/policies.md +66 -0
- package/.agent-src/guidelines/php/patterns/repositories.md +122 -0
- package/.agent-src/guidelines/php/patterns/service-layer.md +64 -0
- package/.agent-src/guidelines/php/patterns/strategy.md +69 -0
- package/.agent-src/guidelines/php/patterns.md +28 -0
- package/.agent-src/guidelines/php/performance.md +92 -0
- package/.agent-src/guidelines/php/resources.md +100 -0
- package/.agent-src/guidelines/php/security.md +110 -0
- package/.agent-src/guidelines/php/sql.md +97 -0
- package/.agent-src/guidelines/php/validations.md +119 -0
- package/.agent-src/guidelines/php/websocket.md +100 -0
- package/.agent-src/personas/README.md +104 -0
- package/.agent-src/personas/ai-agent.md +77 -0
- package/.agent-src/personas/critical-challenger.md +73 -0
- package/.agent-src/personas/developer.md +73 -0
- package/.agent-src/personas/product-owner.md +78 -0
- package/.agent-src/personas/qa.md +67 -0
- package/.agent-src/personas/senior-engineer.md +77 -0
- package/.agent-src/personas/stakeholder.md +78 -0
- package/.agent-src/rules/agent-docs.md +61 -0
- package/.agent-src/rules/analysis-skill-routing.md +48 -0
- package/.agent-src/rules/architecture.md +62 -0
- package/.agent-src/rules/artifact-drafting-protocol.md +73 -0
- package/.agent-src/rules/ask-when-uncertain.md +52 -0
- package/.agent-src/rules/augment-portability.md +38 -0
- package/.agent-src/rules/augment-source-of-truth.md +128 -0
- package/.agent-src/rules/capture-learnings.md +89 -0
- package/.agent-src/rules/cli-output-handling.md +94 -0
- package/.agent-src/rules/commit-conventions.md +64 -0
- package/.agent-src/rules/context-hygiene.md +90 -0
- package/.agent-src/rules/docker-commands.md +55 -0
- package/.agent-src/rules/docs-sync.md +79 -0
- package/.agent-src/rules/downstream-changes.md +70 -0
- package/.agent-src/rules/e2e-testing.md +53 -0
- package/.agent-src/rules/guidelines.md +90 -0
- package/.agent-src/rules/improve-before-implement.md +94 -0
- package/.agent-src/rules/language-and-tone.md +104 -0
- package/.agent-src/rules/laravel-translations.md +48 -0
- package/.agent-src/rules/markdown-safe-codeblocks.md +18 -0
- package/.agent-src/rules/minimal-safe-diff.md +87 -0
- package/.agent-src/rules/missing-tool-handling.md +62 -0
- package/.agent-src/rules/model-recommendation.md +70 -0
- package/.agent-src/rules/package-ci-checks.md +80 -0
- package/.agent-src/rules/php-coding.md +63 -0
- package/.agent-src/rules/preservation-guard.md +29 -0
- package/.agent-src/rules/review-routing-awareness.md +125 -0
- package/.agent-src/rules/reviewer-awareness.md +92 -0
- package/.agent-src/rules/roadmap-progress-sync.md +56 -0
- package/.agent-src/rules/role-mode-adherence.md +54 -0
- package/.agent-src/rules/rule-type-governance.md +46 -0
- package/.agent-src/rules/runtime-safety.md +42 -0
- package/.agent-src/rules/scope-control.md +40 -0
- package/.agent-src/rules/security-sensitive-stop.md +77 -0
- package/.agent-src/rules/size-enforcement.md +29 -0
- package/.agent-src/rules/skill-improvement-trigger.md +58 -0
- package/.agent-src/rules/skill-quality.md +110 -0
- package/.agent-src/rules/slash-commands.md +30 -0
- package/.agent-src/rules/think-before-action.md +91 -0
- package/.agent-src/rules/token-efficiency.md +99 -0
- package/.agent-src/rules/tool-safety.md +36 -0
- package/.agent-src/rules/upstream-proposal.md +76 -0
- package/.agent-src/rules/user-interaction.md +79 -0
- package/.agent-src/rules/verify-before-complete.md +120 -0
- package/.agent-src/scripts/scan-seeder-violations.php +145 -0
- package/.agent-src/scripts/update_roadmap_progress.py +244 -0
- package/.agent-src/skills/adversarial-review/SKILL.md +149 -0
- package/.agent-src/skills/agent-docs-writing/SKILL.md +234 -0
- package/.agent-src/skills/analysis-autonomous-mode/SKILL.md +197 -0
- package/.agent-src/skills/analysis-skill-router/SKILL.md +134 -0
- package/.agent-src/skills/api-design/SKILL.md +104 -0
- package/.agent-src/skills/api-endpoint/SKILL.md +185 -0
- package/.agent-src/skills/api-testing/SKILL.md +206 -0
- package/.agent-src/skills/artisan-commands/SKILL.md +78 -0
- package/.agent-src/skills/authz-review/SKILL.md +171 -0
- package/.agent-src/skills/aws-infrastructure/SKILL.md +152 -0
- package/.agent-src/skills/blade-ui/SKILL.md +75 -0
- package/.agent-src/skills/blast-radius-analyzer/SKILL.md +185 -0
- package/.agent-src/skills/bug-analyzer/SKILL.md +256 -0
- package/.agent-src/skills/check-refs/SKILL.md +72 -0
- package/.agent-src/skills/code-refactoring/SKILL.md +200 -0
- package/.agent-src/skills/code-review/SKILL.md +214 -0
- package/.agent-src/skills/command-routing/SKILL.md +96 -0
- package/.agent-src/skills/command-writing/SKILL.md +143 -0
- package/.agent-src/skills/composer-packages/SKILL.md +172 -0
- package/.agent-src/skills/context-authoring/SKILL.md +157 -0
- package/.agent-src/skills/context-document/SKILL.md +153 -0
- package/.agent-src/skills/conventional-commits-writing/SKILL.md +70 -0
- package/.agent-src/skills/copilot-agents-optimization/SKILL.md +220 -0
- package/.agent-src/skills/copilot-config/SKILL.md +203 -0
- package/.agent-src/skills/dashboard-design/SKILL.md +116 -0
- package/.agent-src/skills/data-flow-mapper/SKILL.md +160 -0
- package/.agent-src/skills/database/SKILL.md +91 -0
- package/.agent-src/skills/dependency-upgrade/SKILL.md +204 -0
- package/.agent-src/skills/description-assist/SKILL.md +169 -0
- package/.agent-src/skills/design-review/SKILL.md +228 -0
- package/.agent-src/skills/devcontainer/SKILL.md +121 -0
- package/.agent-src/skills/developer-like-execution/SKILL.md +276 -0
- package/.agent-src/skills/docker/SKILL.md +245 -0
- package/.agent-src/skills/dto-creator/SKILL.md +117 -0
- package/.agent-src/skills/eloquent/SKILL.md +92 -0
- package/.agent-src/skills/eloquent/evals/last-run.json +99 -0
- package/.agent-src/skills/eloquent/evals/triggers.json +16 -0
- package/.agent-src/skills/estimate-ticket/SKILL.md +186 -0
- package/.agent-src/skills/estimate-ticket/evals/output-schema.yml +20 -0
- package/.agent-src/skills/estimate-ticket/evals/triggers.json +18 -0
- package/.agent-src/skills/fe-design/SKILL.md +223 -0
- package/.agent-src/skills/feature-planning/SKILL.md +226 -0
- package/.agent-src/skills/file-editor/SKILL.md +129 -0
- package/.agent-src/skills/finishing-a-development-branch/SKILL.md +200 -0
- package/.agent-src/skills/flux/SKILL.md +64 -0
- package/.agent-src/skills/git-workflow/SKILL.md +102 -0
- package/.agent-src/skills/github-ci/SKILL.md +122 -0
- package/.agent-src/skills/grafana/SKILL.md +168 -0
- package/.agent-src/skills/guideline-writing/SKILL.md +147 -0
- package/.agent-src/skills/jira-integration/SKILL.md +182 -0
- package/.agent-src/skills/jobs-events/SKILL.md +87 -0
- package/.agent-src/skills/judge-bug-hunter/SKILL.md +157 -0
- package/.agent-src/skills/judge-code-quality/SKILL.md +158 -0
- package/.agent-src/skills/judge-security-auditor/SKILL.md +167 -0
- package/.agent-src/skills/judge-test-coverage/SKILL.md +154 -0
- package/.agent-src/skills/laravel/SKILL.md +195 -0
- package/.agent-src/skills/laravel-horizon/SKILL.md +169 -0
- package/.agent-src/skills/laravel-mail/SKILL.md +193 -0
- package/.agent-src/skills/laravel-middleware/SKILL.md +185 -0
- package/.agent-src/skills/laravel-notifications/SKILL.md +168 -0
- package/.agent-src/skills/laravel-pennant/SKILL.md +188 -0
- package/.agent-src/skills/laravel-pulse/SKILL.md +160 -0
- package/.agent-src/skills/laravel-reverb/SKILL.md +205 -0
- package/.agent-src/skills/laravel-scheduling/SKILL.md +167 -0
- package/.agent-src/skills/laravel-validation/SKILL.md +71 -0
- package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +249 -0
- package/.agent-src/skills/lint-skills/SKILL.md +72 -0
- package/.agent-src/skills/livewire/SKILL.md +79 -0
- package/.agent-src/skills/logging-monitoring/SKILL.md +100 -0
- package/.agent-src/skills/mcp/SKILL.md +193 -0
- package/.agent-src/skills/merge-conflicts/SKILL.md +158 -0
- package/.agent-src/skills/migration-creator/SKILL.md +160 -0
- package/.agent-src/skills/module-management/SKILL.md +154 -0
- package/.agent-src/skills/multi-tenancy/SKILL.md +129 -0
- package/.agent-src/skills/openapi/SKILL.md +154 -0
- package/.agent-src/skills/override-management/SKILL.md +186 -0
- package/.agent-src/skills/performance/SKILL.md +69 -0
- package/.agent-src/skills/performance-analysis/SKILL.md +118 -0
- package/.agent-src/skills/pest-testing/SKILL.md +321 -0
- package/.agent-src/skills/php-coder/SKILL.md +78 -0
- package/.agent-src/skills/php-coder/evals/triggers.json +16 -0
- package/.agent-src/skills/php-debugging/SKILL.md +184 -0
- package/.agent-src/skills/php-service/SKILL.md +96 -0
- package/.agent-src/skills/playwright-testing/SKILL.md +244 -0
- package/.agent-src/skills/project-analysis-core/SKILL.md +138 -0
- package/.agent-src/skills/project-analysis-hypothesis-driven/SKILL.md +130 -0
- package/.agent-src/skills/project-analysis-laravel/SKILL.md +119 -0
- package/.agent-src/skills/project-analysis-nextjs/SKILL.md +123 -0
- package/.agent-src/skills/project-analysis-node-express/SKILL.md +111 -0
- package/.agent-src/skills/project-analysis-react/SKILL.md +119 -0
- package/.agent-src/skills/project-analysis-symfony/SKILL.md +111 -0
- package/.agent-src/skills/project-analysis-zend-laminas/SKILL.md +108 -0
- package/.agent-src/skills/project-analyzer/SKILL.md +341 -0
- package/.agent-src/skills/project-docs/SKILL.md +137 -0
- package/.agent-src/skills/quality-tools/SKILL.md +411 -0
- package/.agent-src/skills/readme-reviewer/SKILL.md +187 -0
- package/.agent-src/skills/readme-writing/SKILL.md +142 -0
- package/.agent-src/skills/readme-writing-package/SKILL.md +185 -0
- package/.agent-src/skills/receiving-code-review/SKILL.md +190 -0
- package/.agent-src/skills/refine-ticket/SKILL.md +310 -0
- package/.agent-src/skills/refine-ticket/detection-map.yml +124 -0
- package/.agent-src/skills/refine-ticket/evals/output-schema.yml +16 -0
- package/.agent-src/skills/refine-ticket/evals/triggers.json +16 -0
- package/.agent-src/skills/requesting-code-review/SKILL.md +199 -0
- package/.agent-src/skills/review-routing/SKILL.md +195 -0
- package/.agent-src/skills/roadmap-management/SKILL.md +303 -0
- package/.agent-src/skills/rtk-output-filtering/SKILL.md +184 -0
- package/.agent-src/skills/rule-writing/SKILL.md +148 -0
- package/.agent-src/skills/security/SKILL.md +79 -0
- package/.agent-src/skills/security-audit/SKILL.md +123 -0
- package/.agent-src/skills/sentry-integration/SKILL.md +170 -0
- package/.agent-src/skills/sequential-thinking/SKILL.md +158 -0
- package/.agent-src/skills/skill-improvement-pipeline/SKILL.md +155 -0
- package/.agent-src/skills/skill-management/SKILL.md +121 -0
- package/.agent-src/skills/skill-reviewer/SKILL.md +218 -0
- package/.agent-src/skills/skill-writing/SKILL.md +291 -0
- package/.agent-src/skills/skill-writing/evals/triggers.json +16 -0
- package/.agent-src/skills/sql-writing/SKILL.md +74 -0
- package/.agent-src/skills/subagent-orchestration/SKILL.md +190 -0
- package/.agent-src/skills/systematic-debugging/SKILL.md +244 -0
- package/.agent-src/skills/technical-specification/SKILL.md +185 -0
- package/.agent-src/skills/terraform/SKILL.md +137 -0
- package/.agent-src/skills/terragrunt/SKILL.md +217 -0
- package/.agent-src/skills/test-driven-development/SKILL.md +252 -0
- package/.agent-src/skills/test-performance/SKILL.md +172 -0
- package/.agent-src/skills/threat-modeling/SKILL.md +189 -0
- package/.agent-src/skills/traefik/SKILL.md +319 -0
- package/.agent-src/skills/universal-project-analysis/SKILL.md +179 -0
- package/.agent-src/skills/upstream-contribute/SKILL.md +255 -0
- package/.agent-src/skills/using-git-worktrees/SKILL.md +148 -0
- package/.agent-src/skills/validate-feature-fit/SKILL.md +113 -0
- package/.agent-src/skills/verify-before-complete/SKILL.md +188 -0
- package/.agent-src/skills/websocket/SKILL.md +75 -0
- package/.agent-src/templates/AGENTS.md +146 -0
- package/.agent-src/templates/agent-settings.md +256 -0
- package/.agent-src/templates/agents/.gitattributes.fragment +16 -0
- package/.agent-src/templates/agents/agent-project-settings.example.yml +138 -0
- package/.agent-src/templates/agents/memory/architecture-decisions.example.yml +95 -0
- package/.agent-src/templates/agents/memory/domain-invariants.example.yml +80 -0
- package/.agent-src/templates/agents/memory/historical-patterns.example.yml +82 -0
- package/.agent-src/templates/agents/memory/incident-learnings.example.yml +113 -0
- package/.agent-src/templates/agents/memory/ownership.example.yml +75 -0
- package/.agent-src/templates/agents/memory/product-rules.example.yml +87 -0
- package/.agent-src/templates/agents/proposal.example.md +143 -0
- package/.agent-src/templates/command.md +84 -0
- package/.agent-src/templates/contexts/auth-model.md +59 -0
- package/.agent-src/templates/contexts/data-sensitivity.md +60 -0
- package/.agent-src/templates/contexts/deployment-order.md +72 -0
- package/.agent-src/templates/contexts/observability.md +64 -0
- package/.agent-src/templates/contexts/tenant-boundaries.md +68 -0
- package/.agent-src/templates/contexts.md +116 -0
- package/.agent-src/templates/copilot-instructions.md +115 -0
- package/.agent-src/templates/features.md +125 -0
- package/.agent-src/templates/github-workflows/memory-hygiene.yml +133 -0
- package/.agent-src/templates/github-workflows/pr-risk-review.yml +123 -0
- package/.agent-src/templates/github-workflows/proposal-drift.yml +118 -0
- package/.agent-src/templates/overrides/command.md +24 -0
- package/.agent-src/templates/overrides/guideline.md +21 -0
- package/.agent-src/templates/overrides/rule.md +19 -0
- package/.agent-src/templates/overrides/skill.md +24 -0
- package/.agent-src/templates/overrides/template.md +21 -0
- package/.agent-src/templates/persona.md +99 -0
- package/.agent-src/templates/roadmaps.md +109 -0
- package/.agent-src/templates/scripts/README.md +195 -0
- package/.agent-src/templates/scripts/check_memory.py +283 -0
- package/.agent-src/templates/scripts/check_memory_proposal.py +180 -0
- package/.agent-src/templates/scripts/historical-bug-patterns.example.yml +84 -0
- package/.agent-src/templates/scripts/implement_ticket/__init__.py +57 -0
- package/.agent-src/templates/scripts/implement_ticket/__main__.py +9 -0
- package/.agent-src/templates/scripts/implement_ticket/cli.py +171 -0
- package/.agent-src/templates/scripts/implement_ticket/delivery_state.py +130 -0
- package/.agent-src/templates/scripts/implement_ticket/dispatcher.py +134 -0
- package/.agent-src/templates/scripts/implement_ticket/persona_policy.py +85 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/__init__.py +49 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/analyze.py +98 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/implement.py +145 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/memory.py +136 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/plan.py +175 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/refine.py +140 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/report.py +195 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/test.py +180 -0
- package/.agent-src/templates/scripts/implement_ticket/steps/verify.py +170 -0
- package/.agent-src/templates/scripts/memory_hash.py +75 -0
- package/.agent-src/templates/scripts/memory_lookup.py +216 -0
- package/.agent-src/templates/scripts/memory_report.py +184 -0
- package/.agent-src/templates/scripts/memory_signal.py +167 -0
- package/.agent-src/templates/scripts/memory_status.py +156 -0
- package/.agent-src/templates/scripts/ownership-map.example.yml +87 -0
- package/.agent-src/templates/scripts/pr-risk-config.example.yml +76 -0
- package/.agent-src/templates/scripts/pr_review_routing.py +340 -0
- package/.agent-src/templates/scripts/pr_risk_review.py +211 -0
- package/.agent-src/templates/skill.md +136 -0
- package/.augment-plugin/marketplace.json +32 -0
- package/.augment-plugin/plugin.json +21 -0
- package/.claude-plugin/marketplace.json +119 -0
- package/AGENTS.md +121 -0
- package/CHANGELOG.md +279 -0
- package/CONTRIBUTING.md +176 -0
- package/LICENSE +21 -0
- package/README.md +357 -0
- package/bin/install.php +38 -0
- package/composer.json +29 -0
- package/config/agent-settings.template.yml +96 -0
- package/config/profiles/balanced.ini +10 -0
- package/config/profiles/full.ini +10 -0
- package/config/profiles/minimal.ini +10 -0
- package/docs/architecture.md +144 -0
- package/docs/customization.md +88 -0
- package/docs/development.md +171 -0
- package/docs/getting-started.md +130 -0
- package/docs/github-topics.md +84 -0
- package/docs/installation.md +376 -0
- package/docs/mcp.md +133 -0
- package/docs/quality.md +98 -0
- package/docs/skills-catalog.md +136 -0
- package/docs/troubleshooting.md +167 -0
- package/llms.txt +130 -0
- package/package.json +31 -0
- package/scripts/audit_skill_descriptions.py +168 -0
- package/scripts/check_compression.py +221 -0
- package/scripts/check_memory.py +341 -0
- package/scripts/check_memory_proposal.py +180 -0
- package/scripts/check_portability.py +320 -0
- package/scripts/check_proposal.py +269 -0
- package/scripts/check_references.py +400 -0
- package/scripts/ci_summary.py +131 -0
- package/scripts/compress.py +671 -0
- package/scripts/compress.sh +18 -0
- package/scripts/first-run.sh +109 -0
- package/scripts/generate_catalog.py +116 -0
- package/scripts/install +151 -0
- package/scripts/install-hooks.sh +29 -0
- package/scripts/install.py +487 -0
- package/scripts/install.sh +637 -0
- package/scripts/install_anthropic_key.sh +101 -0
- package/scripts/inventory_frontmatter.py +164 -0
- package/scripts/lint_marketplace.py +142 -0
- package/scripts/lint_regression.py +232 -0
- package/scripts/mcp_render.py +159 -0
- package/scripts/measure_patterns.py +376 -0
- package/scripts/memory_hash.py +75 -0
- package/scripts/memory_lookup.py +441 -0
- package/scripts/memory_report.py +336 -0
- package/scripts/memory_signal.py +210 -0
- package/scripts/memory_status.py +195 -0
- package/scripts/postinstall.sh +60 -0
- package/scripts/readme_linter.py +580 -0
- package/scripts/refine_ticket_detect.py +623 -0
- package/scripts/requirements-evals.txt +7 -0
- package/scripts/runtime_dispatcher.py +265 -0
- package/scripts/runtime_handler.py +148 -0
- package/scripts/runtime_registry.py +166 -0
- package/scripts/schemas/command.schema.json +32 -0
- package/scripts/schemas/persona.schema.json +42 -0
- package/scripts/schemas/rule.schema.json +28 -0
- package/scripts/schemas/skill.schema.json +73 -0
- package/scripts/setup.sh +230 -0
- package/scripts/setup_eval_venv.sh +58 -0
- package/scripts/skill_linter.py +2175 -0
- package/scripts/skill_trigger_eval.py +651 -0
- package/scripts/tool_registry.py +146 -0
- package/scripts/tools/__init__.py +1 -0
- package/scripts/tools/adapter_errors.py +63 -0
- package/scripts/tools/base_adapter.py +91 -0
- package/scripts/tools/github_adapter.py +128 -0
- package/scripts/tools/jira_adapter.py +115 -0
- package/scripts/update_counts.py +147 -0
- package/scripts/validate_frontmatter.py +424 -0
- package/templates/consumer-settings/README.md +46 -0
- package/templates/consumer-settings/augment-settings.json +12 -0
- package/templates/consumer-settings/claude-settings.json +9 -0
- package/templates/consumer-settings/copilot-settings.json +14 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""``implement`` step — gate + Option-A delegation for applying the plan.
|
|
2
|
+
|
|
3
|
+
The step never edits files. Editing is delegated to the agent via
|
|
4
|
+
``@agent-directive: apply-plan``; the agent runs the `minimal-safe-
|
|
5
|
+
diff` and `scope-control` rules while it applies the plan, then
|
|
6
|
+
writes the resulting file-level changes onto ``state.changes`` and
|
|
7
|
+
marks ``outcomes['implement'] = 'success'`` before re-invoking the
|
|
8
|
+
dispatcher.
|
|
9
|
+
|
|
10
|
+
Flow:
|
|
11
|
+
|
|
12
|
+
- ``plan`` outcome is not ``success`` → BLOCKED on precondition.
|
|
13
|
+
- ``state.changes`` empty → BLOCKED with ``@agent-directive:
|
|
14
|
+
apply-plan`` so the agent applies the plan.
|
|
15
|
+
- ``state.changes`` populated but malformed (entries missing
|
|
16
|
+
``path``, or non-dict entries) → BLOCKED with shape complaint.
|
|
17
|
+
- Otherwise → SUCCESS.
|
|
18
|
+
|
|
19
|
+
``changes`` entries use the loose shape described in
|
|
20
|
+
``agents/contexts/implement-ticket-flow.md#deliverystate-the-only-shared-object``
|
|
21
|
+
\u2014 each entry is a dict with at least a ``path``; optional
|
|
22
|
+
``lines`` / ``purpose`` feed the delivery report.
|
|
23
|
+
"""
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from typing import Any
|
|
27
|
+
|
|
28
|
+
from ..delivery_state import (
|
|
29
|
+
DeliveryState,
|
|
30
|
+
Outcome,
|
|
31
|
+
StepResult,
|
|
32
|
+
agent_directive,
|
|
33
|
+
)
|
|
34
|
+
from ..persona_policy import resolve_policy
|
|
35
|
+
|
|
36
|
+
AMBIGUITIES: tuple[dict[str, str], ...] = (
|
|
37
|
+
{
|
|
38
|
+
"code": "upstream_plan_failed",
|
|
39
|
+
"trigger": "`plan` outcome is not `success`",
|
|
40
|
+
"resolution": "re-run `/implement-ticket` from the start",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"code": "empty_changes_delegate",
|
|
44
|
+
"trigger": "`state.changes` empty — plan not applied yet",
|
|
45
|
+
"resolution": (
|
|
46
|
+
"agent directive `apply-plan` → edit under `minimal-safe-diff` "
|
|
47
|
+
"+ `scope-control`"
|
|
48
|
+
),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"code": "malformed_changes",
|
|
52
|
+
"trigger": "any change entry is not a dict or has no non-empty `path`",
|
|
53
|
+
"resolution": "re-run `apply-plan` and resume",
|
|
54
|
+
},
|
|
55
|
+
)
|
|
56
|
+
"""Declared ambiguity surfaces. Advisory personas skip this step entirely."""
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def run(state: DeliveryState) -> StepResult:
|
|
60
|
+
"""Gate on ``plan``, then either delegate or validate ``state.changes``."""
|
|
61
|
+
policy = resolve_policy(state.persona)
|
|
62
|
+
if not policy.allows_implement:
|
|
63
|
+
# Advisory personas produce a plan only; ``state.changes`` stays
|
|
64
|
+
# empty and the delivery report renders a "no file changes
|
|
65
|
+
# recorded" placeholder. See ``persona_policy`` for contract.
|
|
66
|
+
return StepResult(
|
|
67
|
+
outcome=Outcome.SUCCESS,
|
|
68
|
+
message=f"implement skipped: persona `{policy.name}` is plan-only.",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
if state.outcomes.get("plan") != Outcome.SUCCESS.value:
|
|
72
|
+
return _blocked_on_precondition(state)
|
|
73
|
+
|
|
74
|
+
if not state.changes:
|
|
75
|
+
return _delegate_to_apply_plan(state)
|
|
76
|
+
|
|
77
|
+
shape_issues = _diagnose_changes(state.changes)
|
|
78
|
+
if shape_issues:
|
|
79
|
+
return _blocked_on_shape(state, shape_issues)
|
|
80
|
+
|
|
81
|
+
return StepResult(outcome=Outcome.SUCCESS)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _diagnose_changes(changes: list[Any]) -> list[str]:
|
|
85
|
+
"""Every entry must be a dict carrying at least a non-empty ``path``."""
|
|
86
|
+
issues: list[str] = []
|
|
87
|
+
for idx, change in enumerate(changes, start=1):
|
|
88
|
+
if not isinstance(change, dict):
|
|
89
|
+
issues.append(f"change #{idx} is not a dict")
|
|
90
|
+
continue
|
|
91
|
+
path = change.get("path") or change.get("file")
|
|
92
|
+
if not isinstance(path, str) or not path.strip():
|
|
93
|
+
issues.append(f"change #{idx} has no path")
|
|
94
|
+
return issues
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _delegate_to_apply_plan(state: DeliveryState) -> StepResult:
|
|
98
|
+
ticket_id = (state.ticket or {}).get("id") or "(no id)"
|
|
99
|
+
return StepResult(
|
|
100
|
+
outcome=Outcome.BLOCKED,
|
|
101
|
+
questions=[
|
|
102
|
+
agent_directive("apply-plan", ticket=ticket_id),
|
|
103
|
+
f"> Ticket {ticket_id} \u2014 applying the recorded plan under "
|
|
104
|
+
"`minimal-safe-diff` + `scope-control`.",
|
|
105
|
+
"> 1. Continue \u2014 apply the plan as recorded",
|
|
106
|
+
"> 2. Abort \u2014 stop before any edits are made",
|
|
107
|
+
],
|
|
108
|
+
message=f"Ticket {ticket_id} needs its plan applied before testing.",
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _blocked_on_precondition(state: DeliveryState) -> StepResult:
|
|
113
|
+
ticket_id = (state.ticket or {}).get("id") or "(no id)"
|
|
114
|
+
return StepResult(
|
|
115
|
+
outcome=Outcome.BLOCKED,
|
|
116
|
+
questions=[
|
|
117
|
+
f"> Ticket {ticket_id} \u2014 implement gate refused: "
|
|
118
|
+
"`plan` step did not complete successfully.",
|
|
119
|
+
"> 1. Re-run `/implement-ticket` from the start",
|
|
120
|
+
"> 2. Abort",
|
|
121
|
+
],
|
|
122
|
+
message=(
|
|
123
|
+
f"Ticket {ticket_id} cannot implement: plan gate did not pass."
|
|
124
|
+
),
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _blocked_on_shape(state: DeliveryState, issues: list[str]) -> StepResult:
|
|
129
|
+
ticket_id = (state.ticket or {}).get("id") or "(no id)"
|
|
130
|
+
return StepResult(
|
|
131
|
+
outcome=Outcome.BLOCKED,
|
|
132
|
+
questions=[
|
|
133
|
+
f"> Ticket {ticket_id} \u2014 recorded changes are malformed: "
|
|
134
|
+
+ "; ".join(issues)
|
|
135
|
+
+ ".",
|
|
136
|
+
"> 1. Re-run `apply-plan` and resume",
|
|
137
|
+
"> 2. Abort \u2014 changes cannot be trusted",
|
|
138
|
+
],
|
|
139
|
+
message=(
|
|
140
|
+
f"Ticket {ticket_id} changes shape invalid: {'; '.join(issues)}."
|
|
141
|
+
),
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
__all__ = ["AMBIGUITIES", "run"]
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""``memory`` step — bounded retrieval over the four allowed types.
|
|
2
|
+
|
|
3
|
+
Contract (see
|
|
4
|
+
``agents/contexts/implement-ticket-flow.md#memory-retrieval-contract``):
|
|
5
|
+
|
|
6
|
+
- Four allowed types: ``domain-invariants``, ``architecture-decisions``,
|
|
7
|
+
``incident-learnings``, ``historical-patterns``.
|
|
8
|
+
- Hard cap of **12** hits total across the four types.
|
|
9
|
+
- Keys derive from the ticket — title tokens plus acceptance-criterion
|
|
10
|
+
tokens plus any already-known ``files`` hint. Tokenisation is
|
|
11
|
+
deliberately naive (whitespace split, lower-cased) so the retrieval
|
|
12
|
+
shape stays reproducible in tests.
|
|
13
|
+
- Step always returns ``SUCCESS``. Zero hits is a valid outcome
|
|
14
|
+
("nothing in memory touches this ticket") — the ``report`` step
|
|
15
|
+
drops the memory section when that happens rather than padding.
|
|
16
|
+
|
|
17
|
+
The step stores each hit as a plain ``dict`` on ``state.memory`` so
|
|
18
|
+
consumers outside Python (the delivery report, JSON log lines) can
|
|
19
|
+
round-trip the structure without pickling dataclasses.
|
|
20
|
+
"""
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import re
|
|
24
|
+
from typing import Any, Iterable
|
|
25
|
+
|
|
26
|
+
from ..delivery_state import DeliveryState, Outcome, StepResult
|
|
27
|
+
|
|
28
|
+
MEMORY_TYPES: tuple[str, ...] = (
|
|
29
|
+
"domain-invariants",
|
|
30
|
+
"architecture-decisions",
|
|
31
|
+
"incident-learnings",
|
|
32
|
+
"historical-patterns",
|
|
33
|
+
)
|
|
34
|
+
"""The four types allowed by the flow contract. No aliases, no extras."""
|
|
35
|
+
|
|
36
|
+
MAX_HITS: int = 12
|
|
37
|
+
"""Hard cap per the roadmap — never raise without amending the contract."""
|
|
38
|
+
|
|
39
|
+
AMBIGUITIES: tuple[dict[str, str], ...] = ()
|
|
40
|
+
"""Memory retrieval always succeeds — zero hits is a valid outcome.
|
|
41
|
+
|
|
42
|
+
Declared empty so the aggregate registry in ``steps/__init__.py``
|
|
43
|
+
can round-trip every step's surfaces without a special case.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
_WORD = re.compile(r"[A-Za-z][A-Za-z0-9_\-]{2,}")
|
|
47
|
+
_STOPWORDS = frozenset(
|
|
48
|
+
{
|
|
49
|
+
"the", "and", "for", "with", "from", "into", "that", "this",
|
|
50
|
+
"should", "must", "when", "then", "will", "have", "has",
|
|
51
|
+
"are", "was", "were", "can", "could", "would", "shall",
|
|
52
|
+
"also", "which", "where", "while", "make", "made", "use",
|
|
53
|
+
"used", "using", "user", "users", "test", "tests",
|
|
54
|
+
},
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def run(state: DeliveryState) -> StepResult:
|
|
59
|
+
"""Populate ``state.memory`` with up to :data:`MAX_HITS` hits."""
|
|
60
|
+
retrieve = _resolve_retrieve()
|
|
61
|
+
keys = _keys_from_ticket(state.ticket)
|
|
62
|
+
hits = retrieve(list(MEMORY_TYPES), keys, MAX_HITS)
|
|
63
|
+
|
|
64
|
+
# ``retrieve`` returns ``Hit`` dataclasses; coerce to dicts so the
|
|
65
|
+
# state is serialisation-ready for the report step and metrics log.
|
|
66
|
+
state.memory = [_as_dict(h) for h in hits[:MAX_HITS]]
|
|
67
|
+
return StepResult(outcome=Outcome.SUCCESS)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _resolve_retrieve():
|
|
71
|
+
"""Import ``memory_lookup.retrieve`` lazily so tests can monkeypatch it.
|
|
72
|
+
|
|
73
|
+
Importing at module load time would freeze the reference before
|
|
74
|
+
tests can swap in a fake, which is the standard gotcha with the
|
|
75
|
+
``from X import Y`` form. Deferring the import keeps the step
|
|
76
|
+
patchable from a single attribute (``memory_lookup.retrieve``).
|
|
77
|
+
"""
|
|
78
|
+
import memory_lookup # noqa: WPS433 — deliberately late import
|
|
79
|
+
|
|
80
|
+
return memory_lookup.retrieve
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _keys_from_ticket(ticket: dict[str, Any]) -> list[str]:
|
|
84
|
+
"""Derive retrieval keys from the ticket.
|
|
85
|
+
|
|
86
|
+
Three sources, in priority order so callers reading the log can
|
|
87
|
+
reconstruct why a hit scored: explicit ``files`` hints first,
|
|
88
|
+
then title tokens, then acceptance-criterion tokens. Duplicates
|
|
89
|
+
are removed while preserving first-seen order.
|
|
90
|
+
"""
|
|
91
|
+
keys: list[str] = []
|
|
92
|
+
_extend_unique(keys, _as_str_list(ticket.get("files")))
|
|
93
|
+
_extend_unique(keys, _tokenise(ticket.get("title")))
|
|
94
|
+
for ac in _as_str_list(ticket.get("acceptance_criteria")):
|
|
95
|
+
_extend_unique(keys, _tokenise(ac))
|
|
96
|
+
return keys
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _tokenise(value: Any) -> Iterable[str]:
|
|
100
|
+
"""Return lower-cased content words from ``value`` (empty when absent)."""
|
|
101
|
+
if not isinstance(value, str):
|
|
102
|
+
return []
|
|
103
|
+
return [
|
|
104
|
+
match.group(0).lower()
|
|
105
|
+
for match in _WORD.finditer(value)
|
|
106
|
+
if match.group(0).lower() not in _STOPWORDS
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _as_str_list(value: Any) -> list[str]:
|
|
111
|
+
"""Coerce ``value`` to a list of non-empty strings."""
|
|
112
|
+
if not isinstance(value, list):
|
|
113
|
+
return []
|
|
114
|
+
return [item for item in value if isinstance(item, str) and item.strip()]
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _extend_unique(target: list[str], source: Iterable[str]) -> None:
|
|
118
|
+
"""Append items from ``source`` to ``target`` skipping duplicates."""
|
|
119
|
+
seen = set(target)
|
|
120
|
+
for item in source:
|
|
121
|
+
if item in seen:
|
|
122
|
+
continue
|
|
123
|
+
target.append(item)
|
|
124
|
+
seen.add(item)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _as_dict(hit: Any) -> dict[str, Any]:
|
|
128
|
+
"""Coerce a ``Hit`` (or pre-dict test fake) into a plain dict."""
|
|
129
|
+
as_dict = getattr(hit, "as_dict", None)
|
|
130
|
+
if callable(as_dict):
|
|
131
|
+
return as_dict()
|
|
132
|
+
if isinstance(hit, dict):
|
|
133
|
+
return dict(hit)
|
|
134
|
+
# Fallback path — should not happen in production, but keeps the
|
|
135
|
+
# step from crashing if a fixture returns a raw namespace object.
|
|
136
|
+
return {"entry": repr(hit)}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""``plan`` step — gate + delegation to ``feature-plan``.
|
|
2
|
+
|
|
3
|
+
The dispatcher cannot synthesise a plan from pure Python: the real
|
|
4
|
+
work needs code reading and judgement that only the agent has. The
|
|
5
|
+
step therefore follows the Option-A delegation pattern described in
|
|
6
|
+
``agents/contexts/implement-ticket-flow.md#agent-directives``:
|
|
7
|
+
|
|
8
|
+
- ``state.plan`` empty → halt with ``BLOCKED`` and emit
|
|
9
|
+
``@agent-directive: create-plan``. The orchestrator runs the
|
|
10
|
+
``feature-plan`` skill, writes its output onto ``state.plan``,
|
|
11
|
+
marks ``outcomes['plan'] = 'success'``, and re-invokes the
|
|
12
|
+
dispatcher.
|
|
13
|
+
|
|
14
|
+
- ``state.plan`` populated with a minimally valid shape → ``SUCCESS``
|
|
15
|
+
with no mutation. Shape validation catches accidental scaffolding
|
|
16
|
+
(e.g. an empty list, a placeholder string) that would produce a
|
|
17
|
+
broken plan downstream.
|
|
18
|
+
|
|
19
|
+
- ``state.plan`` populated but malformed → ``BLOCKED`` with numbered
|
|
20
|
+
options so the user decides whether to re-plan, continue with the
|
|
21
|
+
malformed plan, or abort.
|
|
22
|
+
|
|
23
|
+
``analyze`` is a precondition: the step refuses to plan when the
|
|
24
|
+
upstream gate did not succeed, rather than silently re-running a
|
|
25
|
+
derailed flow.
|
|
26
|
+
"""
|
|
27
|
+
from __future__ import annotations
|
|
28
|
+
|
|
29
|
+
from typing import Any
|
|
30
|
+
|
|
31
|
+
from ..delivery_state import (
|
|
32
|
+
DeliveryState,
|
|
33
|
+
Outcome,
|
|
34
|
+
StepResult,
|
|
35
|
+
agent_directive,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
AMBIGUITIES: tuple[dict[str, str], ...] = (
|
|
39
|
+
{
|
|
40
|
+
"code": "upstream_analyze_failed",
|
|
41
|
+
"trigger": "`analyze` outcome is not `success`",
|
|
42
|
+
"resolution": "re-run `/implement-ticket` from the start",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"code": "empty_plan_delegate",
|
|
46
|
+
"trigger": "`state.plan` empty — no plan recorded yet",
|
|
47
|
+
"resolution": "agent directive `create-plan` → `/feature-plan`",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"code": "malformed_plan",
|
|
51
|
+
"trigger": (
|
|
52
|
+
"plan is not a non-empty string, list of strings/dicts, "
|
|
53
|
+
"or dict with a non-empty `steps` list"
|
|
54
|
+
),
|
|
55
|
+
"resolution": "re-run `/feature-plan` or correct the recorded plan",
|
|
56
|
+
},
|
|
57
|
+
)
|
|
58
|
+
"""Declared ambiguity surfaces. Every BLOCKED return maps to one code."""
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def run(state: DeliveryState) -> StepResult:
|
|
62
|
+
"""Gate on ``analyze``, then either delegate or validate the plan."""
|
|
63
|
+
if state.outcomes.get("analyze") != Outcome.SUCCESS.value:
|
|
64
|
+
return _blocked_on_precondition(state)
|
|
65
|
+
|
|
66
|
+
if _is_plan_empty(state.plan):
|
|
67
|
+
return _delegate_to_feature_plan(state)
|
|
68
|
+
|
|
69
|
+
shape_issues = _diagnose_shape(state.plan)
|
|
70
|
+
if shape_issues:
|
|
71
|
+
return _blocked_on_shape(state, shape_issues)
|
|
72
|
+
|
|
73
|
+
return StepResult(outcome=Outcome.SUCCESS)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _is_plan_empty(plan: Any) -> bool:
|
|
77
|
+
"""True when ``state.plan`` has nothing a downstream step could use.
|
|
78
|
+
|
|
79
|
+
Whitespace-only strings count as empty \u2014 the user experience of
|
|
80
|
+
"nothing planned" is identical to "blank placeholder", and both
|
|
81
|
+
should delegate to ``feature-plan`` rather than fall through to
|
|
82
|
+
the shape-validator.
|
|
83
|
+
"""
|
|
84
|
+
if plan is None:
|
|
85
|
+
return True
|
|
86
|
+
if isinstance(plan, str):
|
|
87
|
+
return not plan.strip()
|
|
88
|
+
if isinstance(plan, (list, dict, tuple, set)):
|
|
89
|
+
return len(plan) == 0
|
|
90
|
+
return False
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _diagnose_shape(plan: Any) -> list[str]:
|
|
94
|
+
"""Return the list of shape complaints against ``state.plan``.
|
|
95
|
+
|
|
96
|
+
Accepted shapes (matches ``report._format_plan``):
|
|
97
|
+
a non-empty string, a list of strings or ``{title, detail}`` dicts,
|
|
98
|
+
or a dict with a non-empty ``steps`` list. Everything else is
|
|
99
|
+
rejected so the report renderer never has to guess.
|
|
100
|
+
"""
|
|
101
|
+
issues: list[str] = []
|
|
102
|
+
|
|
103
|
+
if isinstance(plan, str):
|
|
104
|
+
if not plan.strip():
|
|
105
|
+
issues.append("plan is a blank string")
|
|
106
|
+
return issues
|
|
107
|
+
|
|
108
|
+
if isinstance(plan, list):
|
|
109
|
+
if not plan:
|
|
110
|
+
issues.append("plan list is empty")
|
|
111
|
+
return issues
|
|
112
|
+
for idx, item in enumerate(plan, start=1):
|
|
113
|
+
if isinstance(item, dict):
|
|
114
|
+
if not (item.get("title") or item.get("step")):
|
|
115
|
+
issues.append(f"plan step #{idx} has no title")
|
|
116
|
+
elif not isinstance(item, str) or not item.strip():
|
|
117
|
+
issues.append(f"plan step #{idx} is not a usable string")
|
|
118
|
+
return issues
|
|
119
|
+
|
|
120
|
+
if isinstance(plan, dict):
|
|
121
|
+
steps = plan.get("steps")
|
|
122
|
+
if not isinstance(steps, list) or not steps:
|
|
123
|
+
issues.append("plan dict must carry a non-empty 'steps' list")
|
|
124
|
+
return issues
|
|
125
|
+
|
|
126
|
+
issues.append(f"plan has unsupported type: {type(plan).__name__}")
|
|
127
|
+
return issues
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _delegate_to_feature_plan(state: DeliveryState) -> StepResult:
|
|
131
|
+
"""Halt with an agent directive so the orchestrator runs ``feature-plan``."""
|
|
132
|
+
ticket_id = (state.ticket or {}).get("id") or "(no id)"
|
|
133
|
+
return StepResult(
|
|
134
|
+
outcome=Outcome.BLOCKED,
|
|
135
|
+
questions=[
|
|
136
|
+
agent_directive("create-plan", ticket=ticket_id),
|
|
137
|
+
f"> Ticket {ticket_id} \u2014 no plan recorded yet; running "
|
|
138
|
+
"`feature-plan` and resuming.",
|
|
139
|
+
"> 1. Continue \u2014 use the plan produced by `feature-plan`",
|
|
140
|
+
"> 2. Abort \u2014 stop before any edits are proposed",
|
|
141
|
+
],
|
|
142
|
+
message=f"Ticket {ticket_id} needs a plan before implementation.",
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _blocked_on_precondition(state: DeliveryState) -> StepResult:
|
|
147
|
+
ticket_id = (state.ticket or {}).get("id") or "(no id)"
|
|
148
|
+
return StepResult(
|
|
149
|
+
outcome=Outcome.BLOCKED,
|
|
150
|
+
questions=[
|
|
151
|
+
f"> Ticket {ticket_id} \u2014 plan gate refused: "
|
|
152
|
+
"`analyze` step did not complete successfully.",
|
|
153
|
+
"> 1. Re-run `/implement-ticket` from the start",
|
|
154
|
+
"> 2. Abort",
|
|
155
|
+
],
|
|
156
|
+
message=f"Ticket {ticket_id} cannot plan: analyze gate did not pass.",
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _blocked_on_shape(state: DeliveryState, issues: list[str]) -> StepResult:
|
|
161
|
+
ticket_id = (state.ticket or {}).get("id") or "(no id)"
|
|
162
|
+
return StepResult(
|
|
163
|
+
outcome=Outcome.BLOCKED,
|
|
164
|
+
questions=[
|
|
165
|
+
f"> Ticket {ticket_id} \u2014 recorded plan is malformed: "
|
|
166
|
+
+ "; ".join(issues)
|
|
167
|
+
+ ".",
|
|
168
|
+
"> 1. Re-run `feature-plan` and resume",
|
|
169
|
+
"> 2. Abort \u2014 the plan cannot be trusted",
|
|
170
|
+
],
|
|
171
|
+
message=f"Ticket {ticket_id} plan shape invalid: {'; '.join(issues)}.",
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
__all__ = ["AMBIGUITIES", "run"]
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""``refine`` step — deterministic gate in front of the ``refine-ticket`` skill.
|
|
2
|
+
|
|
3
|
+
The step never calls an LLM. It inspects ``state.ticket`` for the
|
|
4
|
+
minimum viable shape (an identifier, a non-trivial title, and at
|
|
5
|
+
least one sufficiently concrete acceptance criterion) and either:
|
|
6
|
+
|
|
7
|
+
- returns ``SUCCESS`` — the ticket is already refined enough for the
|
|
8
|
+
downstream steps to plan against, or
|
|
9
|
+
- returns ``BLOCKED`` — the deficiencies are listed as numbered
|
|
10
|
+
options per the ``user-interaction`` rule, and the flow halts so
|
|
11
|
+
the user can run ``/refine-ticket`` (or provide the missing data)
|
|
12
|
+
and re-invoke ``/implement-ticket``.
|
|
13
|
+
|
|
14
|
+
The checks live here (rather than inside the ``refine-ticket`` skill)
|
|
15
|
+
because the dispatcher is synchronous Python: it cannot "delegate"
|
|
16
|
+
to an agent skill mid-loop. Making the gate deterministic keeps the
|
|
17
|
+
contract "block on ambiguity, never guess" enforceable from code,
|
|
18
|
+
and leaves the harder judgement calls (is an AC measurable? testable?)
|
|
19
|
+
to the human-run ``/refine-ticket`` flow on the rebound.
|
|
20
|
+
"""
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
from typing import Any
|
|
24
|
+
|
|
25
|
+
from ..delivery_state import DeliveryState, Outcome, StepResult
|
|
26
|
+
|
|
27
|
+
_MIN_TITLE_LEN = 3
|
|
28
|
+
_MIN_AC_LEN = 10
|
|
29
|
+
|
|
30
|
+
AMBIGUITIES: tuple[dict[str, str], ...] = (
|
|
31
|
+
{
|
|
32
|
+
"code": "missing_id",
|
|
33
|
+
"trigger": "ticket has no `id` field (or only whitespace)",
|
|
34
|
+
"resolution": "run `/refine-ticket` or paste the ticket id in chat",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"code": "trivial_title",
|
|
38
|
+
"trigger": f"title missing or shorter than {_MIN_TITLE_LEN} chars",
|
|
39
|
+
"resolution": "run `/refine-ticket` to rewrite the title",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"code": "missing_or_vague_ac",
|
|
43
|
+
"trigger": (
|
|
44
|
+
f"acceptance_criteria empty, non-list, or any item under "
|
|
45
|
+
f"{_MIN_AC_LEN} chars"
|
|
46
|
+
),
|
|
47
|
+
"resolution": "run `/refine-ticket` to add concrete acceptance criteria",
|
|
48
|
+
},
|
|
49
|
+
)
|
|
50
|
+
"""Declared ambiguity surfaces. Every BLOCKED return maps to one code."""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def run(state: DeliveryState) -> StepResult:
|
|
54
|
+
"""Return SUCCESS when the ticket is refined, BLOCKED otherwise."""
|
|
55
|
+
deficiencies = _diagnose(state.ticket)
|
|
56
|
+
if not deficiencies:
|
|
57
|
+
return StepResult(outcome=Outcome.SUCCESS)
|
|
58
|
+
|
|
59
|
+
ticket_id = state.ticket.get("id") or "(no id)"
|
|
60
|
+
questions = _format_questions(ticket_id, deficiencies)
|
|
61
|
+
return StepResult(
|
|
62
|
+
outcome=Outcome.BLOCKED,
|
|
63
|
+
questions=questions,
|
|
64
|
+
message=(
|
|
65
|
+
f"Ticket {ticket_id} is not refined enough to plan against: "
|
|
66
|
+
+ "; ".join(deficiencies)
|
|
67
|
+
),
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _diagnose(ticket: dict[str, Any]) -> list[str]:
|
|
72
|
+
"""Return a human-readable list of what's missing from the ticket.
|
|
73
|
+
|
|
74
|
+
Order matches what a reader needs first (identity → summary →
|
|
75
|
+
acceptance criteria) so the surfaced questions read naturally.
|
|
76
|
+
"""
|
|
77
|
+
issues: list[str] = []
|
|
78
|
+
|
|
79
|
+
ticket_id = ticket.get("id")
|
|
80
|
+
if not isinstance(ticket_id, str) or not ticket_id.strip():
|
|
81
|
+
issues.append("missing ticket id")
|
|
82
|
+
|
|
83
|
+
title = ticket.get("title")
|
|
84
|
+
if not isinstance(title, str) or len(title.strip()) < _MIN_TITLE_LEN:
|
|
85
|
+
issues.append("missing or trivial title")
|
|
86
|
+
|
|
87
|
+
ac = ticket.get("acceptance_criteria")
|
|
88
|
+
if not isinstance(ac, list) or not ac:
|
|
89
|
+
issues.append("no acceptance criteria")
|
|
90
|
+
else:
|
|
91
|
+
weak_indices = [
|
|
92
|
+
idx + 1
|
|
93
|
+
for idx, item in enumerate(ac)
|
|
94
|
+
if not _is_concrete_ac(item)
|
|
95
|
+
]
|
|
96
|
+
if weak_indices:
|
|
97
|
+
issues.append(
|
|
98
|
+
"vague acceptance criteria at position(s) "
|
|
99
|
+
+ ", ".join(str(i) for i in weak_indices),
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
return issues
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _is_concrete_ac(item: Any) -> bool:
|
|
106
|
+
"""An AC is concrete when it is a non-empty string above the length floor.
|
|
107
|
+
|
|
108
|
+
The floor is deliberately loose: refine is a gate, not a style
|
|
109
|
+
judge. The heavy lifting (measurability, testability, tone) is
|
|
110
|
+
owned by the ``refine-ticket`` skill on the rebound.
|
|
111
|
+
"""
|
|
112
|
+
if not isinstance(item, str):
|
|
113
|
+
return False
|
|
114
|
+
return len(item.strip()) >= _MIN_AC_LEN
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _format_questions(ticket_id: str, deficiencies: list[str]) -> list[str]:
|
|
118
|
+
"""Render the numbered options shown to the user when BLOCKED.
|
|
119
|
+
|
|
120
|
+
Three options, ordered by likely next action: run the existing
|
|
121
|
+
refinement skill, paste the missing data in chat, or abandon the
|
|
122
|
+
ticket entirely. ``user-interaction`` requires numbered, prose-
|
|
123
|
+
free options; the deficiency list is rendered as a headnote.
|
|
124
|
+
"""
|
|
125
|
+
headnote = (
|
|
126
|
+
"> Ticket "
|
|
127
|
+
+ ticket_id
|
|
128
|
+
+ " is missing: "
|
|
129
|
+
+ "; ".join(deficiencies)
|
|
130
|
+
+ "."
|
|
131
|
+
)
|
|
132
|
+
return [
|
|
133
|
+
headnote,
|
|
134
|
+
f"> 1. Run `/refine-ticket {ticket_id}` and re-invoke `/implement-ticket`",
|
|
135
|
+
"> 2. Provide the missing details in chat — I'll merge them into the ticket",
|
|
136
|
+
"> 3. Abandon this ticket — too vague to implement",
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
__all__ = ["AMBIGUITIES", "run"]
|