@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.
Files changed (446) hide show
  1. package/.agent-src/README.md +64 -0
  2. package/.agent-src/commands/agent-handoff.md +64 -0
  3. package/.agent-src/commands/agent-status.md +83 -0
  4. package/.agent-src/commands/agents-audit.md +243 -0
  5. package/.agent-src/commands/agents-cleanup.md +169 -0
  6. package/.agent-src/commands/agents-prepare.md +137 -0
  7. package/.agent-src/commands/analyze-reference-repo.md +191 -0
  8. package/.agent-src/commands/bug-fix.md +181 -0
  9. package/.agent-src/commands/bug-investigate.md +175 -0
  10. package/.agent-src/commands/commit.md +121 -0
  11. package/.agent-src/commands/compress.md +177 -0
  12. package/.agent-src/commands/config-agent-settings.md +126 -0
  13. package/.agent-src/commands/context-create.md +167 -0
  14. package/.agent-src/commands/context-refactor.md +170 -0
  15. package/.agent-src/commands/copilot-agents-init.md +150 -0
  16. package/.agent-src/commands/copilot-agents-optimize.md +251 -0
  17. package/.agent-src/commands/create-pr-description.md +112 -0
  18. package/.agent-src/commands/create-pr.md +76 -0
  19. package/.agent-src/commands/do-and-judge.md +114 -0
  20. package/.agent-src/commands/do-in-steps.md +84 -0
  21. package/.agent-src/commands/e2e-heal.md +98 -0
  22. package/.agent-src/commands/e2e-plan.md +85 -0
  23. package/.agent-src/commands/estimate-ticket.md +80 -0
  24. package/.agent-src/commands/feature-dev.md +111 -0
  25. package/.agent-src/commands/feature-explore.md +180 -0
  26. package/.agent-src/commands/feature-plan.md +288 -0
  27. package/.agent-src/commands/feature-refactor.md +181 -0
  28. package/.agent-src/commands/feature-roadmap.md +184 -0
  29. package/.agent-src/commands/fix-ci.md +48 -0
  30. package/.agent-src/commands/fix-portability.md +97 -0
  31. package/.agent-src/commands/fix-pr-bot-comments.md +146 -0
  32. package/.agent-src/commands/fix-pr-comments.md +58 -0
  33. package/.agent-src/commands/fix-pr-developer-comments.md +152 -0
  34. package/.agent-src/commands/fix-references.md +94 -0
  35. package/.agent-src/commands/fix-seeder.md +146 -0
  36. package/.agent-src/commands/implement-ticket.md +133 -0
  37. package/.agent-src/commands/jira-ticket.md +71 -0
  38. package/.agent-src/commands/judge.md +86 -0
  39. package/.agent-src/commands/memory-add.md +130 -0
  40. package/.agent-src/commands/memory-full.md +97 -0
  41. package/.agent-src/commands/memory-promote.md +144 -0
  42. package/.agent-src/commands/mode.md +121 -0
  43. package/.agent-src/commands/module-create.md +132 -0
  44. package/.agent-src/commands/module-explore.md +157 -0
  45. package/.agent-src/commands/optimize-agents.md +139 -0
  46. package/.agent-src/commands/optimize-augmentignore.md +262 -0
  47. package/.agent-src/commands/optimize-rtk-filters.md +120 -0
  48. package/.agent-src/commands/optimize-skills.md +121 -0
  49. package/.agent-src/commands/override-create.md +97 -0
  50. package/.agent-src/commands/override-manage.md +96 -0
  51. package/.agent-src/commands/package-reset.md +154 -0
  52. package/.agent-src/commands/package-test.md +154 -0
  53. package/.agent-src/commands/prepare-for-review.md +91 -0
  54. package/.agent-src/commands/project-analyze.md +300 -0
  55. package/.agent-src/commands/project-health.md +95 -0
  56. package/.agent-src/commands/propose-memory.md +108 -0
  57. package/.agent-src/commands/quality-fix.md +106 -0
  58. package/.agent-src/commands/refine-ticket.md +81 -0
  59. package/.agent-src/commands/review-changes.md +130 -0
  60. package/.agent-src/commands/review-routing.md +111 -0
  61. package/.agent-src/commands/roadmap-create.md +110 -0
  62. package/.agent-src/commands/roadmap-execute.md +68 -0
  63. package/.agent-src/commands/rule-compliance-audit.md +139 -0
  64. package/.agent-src/commands/tests-create.md +73 -0
  65. package/.agent-src/commands/tests-execute.md +58 -0
  66. package/.agent-src/commands/threat-model.md +115 -0
  67. package/.agent-src/commands/update-form-request-messages.md +189 -0
  68. package/.agent-src/commands/upstream-contribute.md +171 -0
  69. package/.agent-src/contexts/augment-infrastructure.md +181 -0
  70. package/.agent-src/contexts/documentation-hierarchy.md +142 -0
  71. package/.agent-src/contexts/model-recommendations.md +142 -0
  72. package/.agent-src/contexts/override-system.md +187 -0
  73. package/.agent-src/contexts/skills-and-commands.md +154 -0
  74. package/.agent-src/contexts/subagent-configuration.md +62 -0
  75. package/.agent-src/guidelines/agent-infra/agent-interaction-and-decision-quality.md +110 -0
  76. package/.agent-src/guidelines/agent-infra/break-glass-usage.md +113 -0
  77. package/.agent-src/guidelines/agent-infra/developer-judgment.md +82 -0
  78. package/.agent-src/guidelines/agent-infra/engineering-memory-data-format.md +117 -0
  79. package/.agent-src/guidelines/agent-infra/layered-settings.md +158 -0
  80. package/.agent-src/guidelines/agent-infra/memory-access.md +121 -0
  81. package/.agent-src/guidelines/agent-infra/naming.md +69 -0
  82. package/.agent-src/guidelines/agent-infra/output-patterns.md +117 -0
  83. package/.agent-src/guidelines/agent-infra/review-routing-data-format.md +144 -0
  84. package/.agent-src/guidelines/agent-infra/role-contracts.md +211 -0
  85. package/.agent-src/guidelines/agent-infra/role-mode-router.md +89 -0
  86. package/.agent-src/guidelines/agent-infra/runtime-layer.md +89 -0
  87. package/.agent-src/guidelines/agent-infra/self-improvement-pipeline.md +135 -0
  88. package/.agent-src/guidelines/agent-infra/size-and-scope.md +189 -0
  89. package/.agent-src/guidelines/agent-infra/tool-integration.md +73 -0
  90. package/.agent-src/guidelines/docs/readme-size-and-splitting.md +153 -0
  91. package/.agent-src/guidelines/e2e/playwright.md +363 -0
  92. package/.agent-src/guidelines/php/api-design.md +115 -0
  93. package/.agent-src/guidelines/php/artisan-commands.md +81 -0
  94. package/.agent-src/guidelines/php/blade-ui.md +78 -0
  95. package/.agent-src/guidelines/php/controllers.md +90 -0
  96. package/.agent-src/guidelines/php/database.md +111 -0
  97. package/.agent-src/guidelines/php/eloquent.md +208 -0
  98. package/.agent-src/guidelines/php/flux.md +80 -0
  99. package/.agent-src/guidelines/php/general.md +191 -0
  100. package/.agent-src/guidelines/php/git.md +96 -0
  101. package/.agent-src/guidelines/php/jobs.md +111 -0
  102. package/.agent-src/guidelines/php/livewire.md +71 -0
  103. package/.agent-src/guidelines/php/logging.md +79 -0
  104. package/.agent-src/guidelines/php/naming.md +89 -0
  105. package/.agent-src/guidelines/php/patterns/dependency-injection.md +57 -0
  106. package/.agent-src/guidelines/php/patterns/dtos.md +199 -0
  107. package/.agent-src/guidelines/php/patterns/events.md +67 -0
  108. package/.agent-src/guidelines/php/patterns/factory.md +53 -0
  109. package/.agent-src/guidelines/php/patterns/pipelines.md +66 -0
  110. package/.agent-src/guidelines/php/patterns/policies.md +66 -0
  111. package/.agent-src/guidelines/php/patterns/repositories.md +122 -0
  112. package/.agent-src/guidelines/php/patterns/service-layer.md +64 -0
  113. package/.agent-src/guidelines/php/patterns/strategy.md +69 -0
  114. package/.agent-src/guidelines/php/patterns.md +28 -0
  115. package/.agent-src/guidelines/php/performance.md +92 -0
  116. package/.agent-src/guidelines/php/resources.md +100 -0
  117. package/.agent-src/guidelines/php/security.md +110 -0
  118. package/.agent-src/guidelines/php/sql.md +97 -0
  119. package/.agent-src/guidelines/php/validations.md +119 -0
  120. package/.agent-src/guidelines/php/websocket.md +100 -0
  121. package/.agent-src/personas/README.md +104 -0
  122. package/.agent-src/personas/ai-agent.md +77 -0
  123. package/.agent-src/personas/critical-challenger.md +73 -0
  124. package/.agent-src/personas/developer.md +73 -0
  125. package/.agent-src/personas/product-owner.md +78 -0
  126. package/.agent-src/personas/qa.md +67 -0
  127. package/.agent-src/personas/senior-engineer.md +77 -0
  128. package/.agent-src/personas/stakeholder.md +78 -0
  129. package/.agent-src/rules/agent-docs.md +61 -0
  130. package/.agent-src/rules/analysis-skill-routing.md +48 -0
  131. package/.agent-src/rules/architecture.md +62 -0
  132. package/.agent-src/rules/artifact-drafting-protocol.md +73 -0
  133. package/.agent-src/rules/ask-when-uncertain.md +52 -0
  134. package/.agent-src/rules/augment-portability.md +38 -0
  135. package/.agent-src/rules/augment-source-of-truth.md +128 -0
  136. package/.agent-src/rules/capture-learnings.md +89 -0
  137. package/.agent-src/rules/cli-output-handling.md +94 -0
  138. package/.agent-src/rules/commit-conventions.md +64 -0
  139. package/.agent-src/rules/context-hygiene.md +90 -0
  140. package/.agent-src/rules/docker-commands.md +55 -0
  141. package/.agent-src/rules/docs-sync.md +79 -0
  142. package/.agent-src/rules/downstream-changes.md +70 -0
  143. package/.agent-src/rules/e2e-testing.md +53 -0
  144. package/.agent-src/rules/guidelines.md +90 -0
  145. package/.agent-src/rules/improve-before-implement.md +94 -0
  146. package/.agent-src/rules/language-and-tone.md +104 -0
  147. package/.agent-src/rules/laravel-translations.md +48 -0
  148. package/.agent-src/rules/markdown-safe-codeblocks.md +18 -0
  149. package/.agent-src/rules/minimal-safe-diff.md +87 -0
  150. package/.agent-src/rules/missing-tool-handling.md +62 -0
  151. package/.agent-src/rules/model-recommendation.md +70 -0
  152. package/.agent-src/rules/package-ci-checks.md +80 -0
  153. package/.agent-src/rules/php-coding.md +63 -0
  154. package/.agent-src/rules/preservation-guard.md +29 -0
  155. package/.agent-src/rules/review-routing-awareness.md +125 -0
  156. package/.agent-src/rules/reviewer-awareness.md +92 -0
  157. package/.agent-src/rules/roadmap-progress-sync.md +56 -0
  158. package/.agent-src/rules/role-mode-adherence.md +54 -0
  159. package/.agent-src/rules/rule-type-governance.md +46 -0
  160. package/.agent-src/rules/runtime-safety.md +42 -0
  161. package/.agent-src/rules/scope-control.md +40 -0
  162. package/.agent-src/rules/security-sensitive-stop.md +77 -0
  163. package/.agent-src/rules/size-enforcement.md +29 -0
  164. package/.agent-src/rules/skill-improvement-trigger.md +58 -0
  165. package/.agent-src/rules/skill-quality.md +110 -0
  166. package/.agent-src/rules/slash-commands.md +30 -0
  167. package/.agent-src/rules/think-before-action.md +91 -0
  168. package/.agent-src/rules/token-efficiency.md +99 -0
  169. package/.agent-src/rules/tool-safety.md +36 -0
  170. package/.agent-src/rules/upstream-proposal.md +76 -0
  171. package/.agent-src/rules/user-interaction.md +79 -0
  172. package/.agent-src/rules/verify-before-complete.md +120 -0
  173. package/.agent-src/scripts/scan-seeder-violations.php +145 -0
  174. package/.agent-src/scripts/update_roadmap_progress.py +244 -0
  175. package/.agent-src/skills/adversarial-review/SKILL.md +149 -0
  176. package/.agent-src/skills/agent-docs-writing/SKILL.md +234 -0
  177. package/.agent-src/skills/analysis-autonomous-mode/SKILL.md +197 -0
  178. package/.agent-src/skills/analysis-skill-router/SKILL.md +134 -0
  179. package/.agent-src/skills/api-design/SKILL.md +104 -0
  180. package/.agent-src/skills/api-endpoint/SKILL.md +185 -0
  181. package/.agent-src/skills/api-testing/SKILL.md +206 -0
  182. package/.agent-src/skills/artisan-commands/SKILL.md +78 -0
  183. package/.agent-src/skills/authz-review/SKILL.md +171 -0
  184. package/.agent-src/skills/aws-infrastructure/SKILL.md +152 -0
  185. package/.agent-src/skills/blade-ui/SKILL.md +75 -0
  186. package/.agent-src/skills/blast-radius-analyzer/SKILL.md +185 -0
  187. package/.agent-src/skills/bug-analyzer/SKILL.md +256 -0
  188. package/.agent-src/skills/check-refs/SKILL.md +72 -0
  189. package/.agent-src/skills/code-refactoring/SKILL.md +200 -0
  190. package/.agent-src/skills/code-review/SKILL.md +214 -0
  191. package/.agent-src/skills/command-routing/SKILL.md +96 -0
  192. package/.agent-src/skills/command-writing/SKILL.md +143 -0
  193. package/.agent-src/skills/composer-packages/SKILL.md +172 -0
  194. package/.agent-src/skills/context-authoring/SKILL.md +157 -0
  195. package/.agent-src/skills/context-document/SKILL.md +153 -0
  196. package/.agent-src/skills/conventional-commits-writing/SKILL.md +70 -0
  197. package/.agent-src/skills/copilot-agents-optimization/SKILL.md +220 -0
  198. package/.agent-src/skills/copilot-config/SKILL.md +203 -0
  199. package/.agent-src/skills/dashboard-design/SKILL.md +116 -0
  200. package/.agent-src/skills/data-flow-mapper/SKILL.md +160 -0
  201. package/.agent-src/skills/database/SKILL.md +91 -0
  202. package/.agent-src/skills/dependency-upgrade/SKILL.md +204 -0
  203. package/.agent-src/skills/description-assist/SKILL.md +169 -0
  204. package/.agent-src/skills/design-review/SKILL.md +228 -0
  205. package/.agent-src/skills/devcontainer/SKILL.md +121 -0
  206. package/.agent-src/skills/developer-like-execution/SKILL.md +276 -0
  207. package/.agent-src/skills/docker/SKILL.md +245 -0
  208. package/.agent-src/skills/dto-creator/SKILL.md +117 -0
  209. package/.agent-src/skills/eloquent/SKILL.md +92 -0
  210. package/.agent-src/skills/eloquent/evals/last-run.json +99 -0
  211. package/.agent-src/skills/eloquent/evals/triggers.json +16 -0
  212. package/.agent-src/skills/estimate-ticket/SKILL.md +186 -0
  213. package/.agent-src/skills/estimate-ticket/evals/output-schema.yml +20 -0
  214. package/.agent-src/skills/estimate-ticket/evals/triggers.json +18 -0
  215. package/.agent-src/skills/fe-design/SKILL.md +223 -0
  216. package/.agent-src/skills/feature-planning/SKILL.md +226 -0
  217. package/.agent-src/skills/file-editor/SKILL.md +129 -0
  218. package/.agent-src/skills/finishing-a-development-branch/SKILL.md +200 -0
  219. package/.agent-src/skills/flux/SKILL.md +64 -0
  220. package/.agent-src/skills/git-workflow/SKILL.md +102 -0
  221. package/.agent-src/skills/github-ci/SKILL.md +122 -0
  222. package/.agent-src/skills/grafana/SKILL.md +168 -0
  223. package/.agent-src/skills/guideline-writing/SKILL.md +147 -0
  224. package/.agent-src/skills/jira-integration/SKILL.md +182 -0
  225. package/.agent-src/skills/jobs-events/SKILL.md +87 -0
  226. package/.agent-src/skills/judge-bug-hunter/SKILL.md +157 -0
  227. package/.agent-src/skills/judge-code-quality/SKILL.md +158 -0
  228. package/.agent-src/skills/judge-security-auditor/SKILL.md +167 -0
  229. package/.agent-src/skills/judge-test-coverage/SKILL.md +154 -0
  230. package/.agent-src/skills/laravel/SKILL.md +195 -0
  231. package/.agent-src/skills/laravel-horizon/SKILL.md +169 -0
  232. package/.agent-src/skills/laravel-mail/SKILL.md +193 -0
  233. package/.agent-src/skills/laravel-middleware/SKILL.md +185 -0
  234. package/.agent-src/skills/laravel-notifications/SKILL.md +168 -0
  235. package/.agent-src/skills/laravel-pennant/SKILL.md +188 -0
  236. package/.agent-src/skills/laravel-pulse/SKILL.md +160 -0
  237. package/.agent-src/skills/laravel-reverb/SKILL.md +205 -0
  238. package/.agent-src/skills/laravel-scheduling/SKILL.md +167 -0
  239. package/.agent-src/skills/laravel-validation/SKILL.md +71 -0
  240. package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +249 -0
  241. package/.agent-src/skills/lint-skills/SKILL.md +72 -0
  242. package/.agent-src/skills/livewire/SKILL.md +79 -0
  243. package/.agent-src/skills/logging-monitoring/SKILL.md +100 -0
  244. package/.agent-src/skills/mcp/SKILL.md +193 -0
  245. package/.agent-src/skills/merge-conflicts/SKILL.md +158 -0
  246. package/.agent-src/skills/migration-creator/SKILL.md +160 -0
  247. package/.agent-src/skills/module-management/SKILL.md +154 -0
  248. package/.agent-src/skills/multi-tenancy/SKILL.md +129 -0
  249. package/.agent-src/skills/openapi/SKILL.md +154 -0
  250. package/.agent-src/skills/override-management/SKILL.md +186 -0
  251. package/.agent-src/skills/performance/SKILL.md +69 -0
  252. package/.agent-src/skills/performance-analysis/SKILL.md +118 -0
  253. package/.agent-src/skills/pest-testing/SKILL.md +321 -0
  254. package/.agent-src/skills/php-coder/SKILL.md +78 -0
  255. package/.agent-src/skills/php-coder/evals/triggers.json +16 -0
  256. package/.agent-src/skills/php-debugging/SKILL.md +184 -0
  257. package/.agent-src/skills/php-service/SKILL.md +96 -0
  258. package/.agent-src/skills/playwright-testing/SKILL.md +244 -0
  259. package/.agent-src/skills/project-analysis-core/SKILL.md +138 -0
  260. package/.agent-src/skills/project-analysis-hypothesis-driven/SKILL.md +130 -0
  261. package/.agent-src/skills/project-analysis-laravel/SKILL.md +119 -0
  262. package/.agent-src/skills/project-analysis-nextjs/SKILL.md +123 -0
  263. package/.agent-src/skills/project-analysis-node-express/SKILL.md +111 -0
  264. package/.agent-src/skills/project-analysis-react/SKILL.md +119 -0
  265. package/.agent-src/skills/project-analysis-symfony/SKILL.md +111 -0
  266. package/.agent-src/skills/project-analysis-zend-laminas/SKILL.md +108 -0
  267. package/.agent-src/skills/project-analyzer/SKILL.md +341 -0
  268. package/.agent-src/skills/project-docs/SKILL.md +137 -0
  269. package/.agent-src/skills/quality-tools/SKILL.md +411 -0
  270. package/.agent-src/skills/readme-reviewer/SKILL.md +187 -0
  271. package/.agent-src/skills/readme-writing/SKILL.md +142 -0
  272. package/.agent-src/skills/readme-writing-package/SKILL.md +185 -0
  273. package/.agent-src/skills/receiving-code-review/SKILL.md +190 -0
  274. package/.agent-src/skills/refine-ticket/SKILL.md +310 -0
  275. package/.agent-src/skills/refine-ticket/detection-map.yml +124 -0
  276. package/.agent-src/skills/refine-ticket/evals/output-schema.yml +16 -0
  277. package/.agent-src/skills/refine-ticket/evals/triggers.json +16 -0
  278. package/.agent-src/skills/requesting-code-review/SKILL.md +199 -0
  279. package/.agent-src/skills/review-routing/SKILL.md +195 -0
  280. package/.agent-src/skills/roadmap-management/SKILL.md +303 -0
  281. package/.agent-src/skills/rtk-output-filtering/SKILL.md +184 -0
  282. package/.agent-src/skills/rule-writing/SKILL.md +148 -0
  283. package/.agent-src/skills/security/SKILL.md +79 -0
  284. package/.agent-src/skills/security-audit/SKILL.md +123 -0
  285. package/.agent-src/skills/sentry-integration/SKILL.md +170 -0
  286. package/.agent-src/skills/sequential-thinking/SKILL.md +158 -0
  287. package/.agent-src/skills/skill-improvement-pipeline/SKILL.md +155 -0
  288. package/.agent-src/skills/skill-management/SKILL.md +121 -0
  289. package/.agent-src/skills/skill-reviewer/SKILL.md +218 -0
  290. package/.agent-src/skills/skill-writing/SKILL.md +291 -0
  291. package/.agent-src/skills/skill-writing/evals/triggers.json +16 -0
  292. package/.agent-src/skills/sql-writing/SKILL.md +74 -0
  293. package/.agent-src/skills/subagent-orchestration/SKILL.md +190 -0
  294. package/.agent-src/skills/systematic-debugging/SKILL.md +244 -0
  295. package/.agent-src/skills/technical-specification/SKILL.md +185 -0
  296. package/.agent-src/skills/terraform/SKILL.md +137 -0
  297. package/.agent-src/skills/terragrunt/SKILL.md +217 -0
  298. package/.agent-src/skills/test-driven-development/SKILL.md +252 -0
  299. package/.agent-src/skills/test-performance/SKILL.md +172 -0
  300. package/.agent-src/skills/threat-modeling/SKILL.md +189 -0
  301. package/.agent-src/skills/traefik/SKILL.md +319 -0
  302. package/.agent-src/skills/universal-project-analysis/SKILL.md +179 -0
  303. package/.agent-src/skills/upstream-contribute/SKILL.md +255 -0
  304. package/.agent-src/skills/using-git-worktrees/SKILL.md +148 -0
  305. package/.agent-src/skills/validate-feature-fit/SKILL.md +113 -0
  306. package/.agent-src/skills/verify-before-complete/SKILL.md +188 -0
  307. package/.agent-src/skills/websocket/SKILL.md +75 -0
  308. package/.agent-src/templates/AGENTS.md +146 -0
  309. package/.agent-src/templates/agent-settings.md +256 -0
  310. package/.agent-src/templates/agents/.gitattributes.fragment +16 -0
  311. package/.agent-src/templates/agents/agent-project-settings.example.yml +138 -0
  312. package/.agent-src/templates/agents/memory/architecture-decisions.example.yml +95 -0
  313. package/.agent-src/templates/agents/memory/domain-invariants.example.yml +80 -0
  314. package/.agent-src/templates/agents/memory/historical-patterns.example.yml +82 -0
  315. package/.agent-src/templates/agents/memory/incident-learnings.example.yml +113 -0
  316. package/.agent-src/templates/agents/memory/ownership.example.yml +75 -0
  317. package/.agent-src/templates/agents/memory/product-rules.example.yml +87 -0
  318. package/.agent-src/templates/agents/proposal.example.md +143 -0
  319. package/.agent-src/templates/command.md +84 -0
  320. package/.agent-src/templates/contexts/auth-model.md +59 -0
  321. package/.agent-src/templates/contexts/data-sensitivity.md +60 -0
  322. package/.agent-src/templates/contexts/deployment-order.md +72 -0
  323. package/.agent-src/templates/contexts/observability.md +64 -0
  324. package/.agent-src/templates/contexts/tenant-boundaries.md +68 -0
  325. package/.agent-src/templates/contexts.md +116 -0
  326. package/.agent-src/templates/copilot-instructions.md +115 -0
  327. package/.agent-src/templates/features.md +125 -0
  328. package/.agent-src/templates/github-workflows/memory-hygiene.yml +133 -0
  329. package/.agent-src/templates/github-workflows/pr-risk-review.yml +123 -0
  330. package/.agent-src/templates/github-workflows/proposal-drift.yml +118 -0
  331. package/.agent-src/templates/overrides/command.md +24 -0
  332. package/.agent-src/templates/overrides/guideline.md +21 -0
  333. package/.agent-src/templates/overrides/rule.md +19 -0
  334. package/.agent-src/templates/overrides/skill.md +24 -0
  335. package/.agent-src/templates/overrides/template.md +21 -0
  336. package/.agent-src/templates/persona.md +99 -0
  337. package/.agent-src/templates/roadmaps.md +109 -0
  338. package/.agent-src/templates/scripts/README.md +195 -0
  339. package/.agent-src/templates/scripts/check_memory.py +283 -0
  340. package/.agent-src/templates/scripts/check_memory_proposal.py +180 -0
  341. package/.agent-src/templates/scripts/historical-bug-patterns.example.yml +84 -0
  342. package/.agent-src/templates/scripts/implement_ticket/__init__.py +57 -0
  343. package/.agent-src/templates/scripts/implement_ticket/__main__.py +9 -0
  344. package/.agent-src/templates/scripts/implement_ticket/cli.py +171 -0
  345. package/.agent-src/templates/scripts/implement_ticket/delivery_state.py +130 -0
  346. package/.agent-src/templates/scripts/implement_ticket/dispatcher.py +134 -0
  347. package/.agent-src/templates/scripts/implement_ticket/persona_policy.py +85 -0
  348. package/.agent-src/templates/scripts/implement_ticket/steps/__init__.py +49 -0
  349. package/.agent-src/templates/scripts/implement_ticket/steps/analyze.py +98 -0
  350. package/.agent-src/templates/scripts/implement_ticket/steps/implement.py +145 -0
  351. package/.agent-src/templates/scripts/implement_ticket/steps/memory.py +136 -0
  352. package/.agent-src/templates/scripts/implement_ticket/steps/plan.py +175 -0
  353. package/.agent-src/templates/scripts/implement_ticket/steps/refine.py +140 -0
  354. package/.agent-src/templates/scripts/implement_ticket/steps/report.py +195 -0
  355. package/.agent-src/templates/scripts/implement_ticket/steps/test.py +180 -0
  356. package/.agent-src/templates/scripts/implement_ticket/steps/verify.py +170 -0
  357. package/.agent-src/templates/scripts/memory_hash.py +75 -0
  358. package/.agent-src/templates/scripts/memory_lookup.py +216 -0
  359. package/.agent-src/templates/scripts/memory_report.py +184 -0
  360. package/.agent-src/templates/scripts/memory_signal.py +167 -0
  361. package/.agent-src/templates/scripts/memory_status.py +156 -0
  362. package/.agent-src/templates/scripts/ownership-map.example.yml +87 -0
  363. package/.agent-src/templates/scripts/pr-risk-config.example.yml +76 -0
  364. package/.agent-src/templates/scripts/pr_review_routing.py +340 -0
  365. package/.agent-src/templates/scripts/pr_risk_review.py +211 -0
  366. package/.agent-src/templates/skill.md +136 -0
  367. package/.augment-plugin/marketplace.json +32 -0
  368. package/.augment-plugin/plugin.json +21 -0
  369. package/.claude-plugin/marketplace.json +119 -0
  370. package/AGENTS.md +121 -0
  371. package/CHANGELOG.md +279 -0
  372. package/CONTRIBUTING.md +176 -0
  373. package/LICENSE +21 -0
  374. package/README.md +357 -0
  375. package/bin/install.php +38 -0
  376. package/composer.json +29 -0
  377. package/config/agent-settings.template.yml +96 -0
  378. package/config/profiles/balanced.ini +10 -0
  379. package/config/profiles/full.ini +10 -0
  380. package/config/profiles/minimal.ini +10 -0
  381. package/docs/architecture.md +144 -0
  382. package/docs/customization.md +88 -0
  383. package/docs/development.md +171 -0
  384. package/docs/getting-started.md +130 -0
  385. package/docs/github-topics.md +84 -0
  386. package/docs/installation.md +376 -0
  387. package/docs/mcp.md +133 -0
  388. package/docs/quality.md +98 -0
  389. package/docs/skills-catalog.md +136 -0
  390. package/docs/troubleshooting.md +167 -0
  391. package/llms.txt +130 -0
  392. package/package.json +31 -0
  393. package/scripts/audit_skill_descriptions.py +168 -0
  394. package/scripts/check_compression.py +221 -0
  395. package/scripts/check_memory.py +341 -0
  396. package/scripts/check_memory_proposal.py +180 -0
  397. package/scripts/check_portability.py +320 -0
  398. package/scripts/check_proposal.py +269 -0
  399. package/scripts/check_references.py +400 -0
  400. package/scripts/ci_summary.py +131 -0
  401. package/scripts/compress.py +671 -0
  402. package/scripts/compress.sh +18 -0
  403. package/scripts/first-run.sh +109 -0
  404. package/scripts/generate_catalog.py +116 -0
  405. package/scripts/install +151 -0
  406. package/scripts/install-hooks.sh +29 -0
  407. package/scripts/install.py +487 -0
  408. package/scripts/install.sh +637 -0
  409. package/scripts/install_anthropic_key.sh +101 -0
  410. package/scripts/inventory_frontmatter.py +164 -0
  411. package/scripts/lint_marketplace.py +142 -0
  412. package/scripts/lint_regression.py +232 -0
  413. package/scripts/mcp_render.py +159 -0
  414. package/scripts/measure_patterns.py +376 -0
  415. package/scripts/memory_hash.py +75 -0
  416. package/scripts/memory_lookup.py +441 -0
  417. package/scripts/memory_report.py +336 -0
  418. package/scripts/memory_signal.py +210 -0
  419. package/scripts/memory_status.py +195 -0
  420. package/scripts/postinstall.sh +60 -0
  421. package/scripts/readme_linter.py +580 -0
  422. package/scripts/refine_ticket_detect.py +623 -0
  423. package/scripts/requirements-evals.txt +7 -0
  424. package/scripts/runtime_dispatcher.py +265 -0
  425. package/scripts/runtime_handler.py +148 -0
  426. package/scripts/runtime_registry.py +166 -0
  427. package/scripts/schemas/command.schema.json +32 -0
  428. package/scripts/schemas/persona.schema.json +42 -0
  429. package/scripts/schemas/rule.schema.json +28 -0
  430. package/scripts/schemas/skill.schema.json +73 -0
  431. package/scripts/setup.sh +230 -0
  432. package/scripts/setup_eval_venv.sh +58 -0
  433. package/scripts/skill_linter.py +2175 -0
  434. package/scripts/skill_trigger_eval.py +651 -0
  435. package/scripts/tool_registry.py +146 -0
  436. package/scripts/tools/__init__.py +1 -0
  437. package/scripts/tools/adapter_errors.py +63 -0
  438. package/scripts/tools/base_adapter.py +91 -0
  439. package/scripts/tools/github_adapter.py +128 -0
  440. package/scripts/tools/jira_adapter.py +115 -0
  441. package/scripts/update_counts.py +147 -0
  442. package/scripts/validate_frontmatter.py +424 -0
  443. package/templates/consumer-settings/README.md +46 -0
  444. package/templates/consumer-settings/augment-settings.json +12 -0
  445. package/templates/consumer-settings/claude-settings.json +9 -0
  446. 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"]