@danmoisan/drm-copilot-mcp 0.0.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 (380) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -0
  3. package/out/mcp-server.js +17323 -0
  4. package/package.json +36 -0
  5. package/resources/claude-customizations/.claude/agent-memory/orchestrator/MEMORY.md +3 -0
  6. package/resources/claude-customizations/.claude/agent-memory/orchestrator/feedback_repo_root_is_source_of_truth.md +11 -0
  7. package/resources/claude-customizations/.claude/agent-memory/orchestrator/feedback_vsce_verify_package_location.md +19 -0
  8. package/resources/claude-customizations/.claude/agent-memory/orchestrator/project_extension_location.md +11 -0
  9. package/resources/claude-customizations/.claude/agent-memory/prd-feature/MEMORY.md +1 -0
  10. package/resources/claude-customizations/.claude/agent-memory/prd-feature/project_push_down_pattern.md +13 -0
  11. package/resources/claude-customizations/.claude/agent-memory/task-researcher/MEMORY.md +3 -0
  12. package/resources/claude-customizations/.claude/agent-memory/task-researcher/project_push_down_claude_dir.md +11 -0
  13. package/resources/claude-customizations/.claude/agents/atomic-executor.md +135 -0
  14. package/resources/claude-customizations/.claude/agents/atomic-planner.md +71 -0
  15. package/resources/claude-customizations/.claude/agents/csharp-typed-engineer.md +69 -0
  16. package/resources/claude-customizations/.claude/agents/epic-review.md +40 -0
  17. package/resources/claude-customizations/.claude/agents/feature-review.md +136 -0
  18. package/resources/claude-customizations/.claude/agents/orchestrator.md +83 -0
  19. package/resources/claude-customizations/.claude/agents/powershell-typed-engineer.md +80 -0
  20. package/resources/claude-customizations/.claude/agents/prd-feature.md +42 -0
  21. package/resources/claude-customizations/.claude/agents/python-typed-engineer.md +72 -0
  22. package/resources/claude-customizations/.claude/agents/staged-review.md +41 -0
  23. package/resources/claude-customizations/.claude/agents/status-updater.md +41 -0
  24. package/resources/claude-customizations/.claude/agents/task-researcher.md +81 -0
  25. package/resources/claude-customizations/.claude/agents/typescript-engineer.md +24 -0
  26. package/resources/claude-customizations/.claude/hooks/check-powershell-test-purity.ps1 +111 -0
  27. package/resources/claude-customizations/.claude/hooks/check-python-test-purity.ps1 +146 -0
  28. package/resources/claude-customizations/.claude/hooks/enforce-evidence-locations.ps1 +150 -0
  29. package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +238 -0
  30. package/resources/claude-customizations/.claude/hooks/enforce-promotion-mcp-only.ps1 +147 -0
  31. package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +235 -0
  32. package/resources/claude-customizations/.claude/hooks/validate-bash.ps1 +69 -0
  33. package/resources/claude-customizations/.claude/hooks/validate-executor-output.ps1 +296 -0
  34. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage.ps1 +389 -0
  35. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +141 -0
  36. package/resources/claude-customizations/.claude/hooks/validate-planner-output.ps1 +288 -0
  37. package/resources/claude-customizations/.claude/hooks/validate-required-artifact-output.ps1 +171 -0
  38. package/resources/claude-customizations/.claude/hooks/validate-task-researcher-output.ps1 +142 -0
  39. package/resources/claude-customizations/.claude/rules/csharp.md +62 -0
  40. package/resources/claude-customizations/.claude/rules/general-code-change.md +71 -0
  41. package/resources/claude-customizations/.claude/rules/general-unit-test.md +60 -0
  42. package/resources/claude-customizations/.claude/rules/powershell.md +97 -0
  43. package/resources/claude-customizations/.claude/rules/python-suppressions.md +143 -0
  44. package/resources/claude-customizations/.claude/rules/python.md +99 -0
  45. package/resources/claude-customizations/.claude/rules/self-explanatory-code-commenting.md +97 -0
  46. package/resources/claude-customizations/.claude/rules/tonality.md +80 -0
  47. package/resources/claude-customizations/.claude/rules/typescript-suppressions.md +66 -0
  48. package/resources/claude-customizations/.claude/rules/typescript.md +45 -0
  49. package/resources/claude-customizations/.claude/settings.json +144 -0
  50. package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +102 -0
  51. package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +189 -0
  52. package/resources/claude-customizations/.claude/skills/commit-message/SKILL.md +65 -0
  53. package/resources/claude-customizations/.claude/skills/csharp-change-budget-router/SKILL.md +90 -0
  54. package/resources/claude-customizations/.claude/skills/csharp-orchestration-state-machine/SKILL.md +58 -0
  55. package/resources/claude-customizations/.claude/skills/csharp-qa-gate/SKILL.md +77 -0
  56. package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +164 -0
  57. package/resources/claude-customizations/.claude/skills/execute-hard-lock/SKILL.md +82 -0
  58. package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +115 -0
  59. package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +167 -0
  60. package/resources/claude-customizations/.claude/skills/fill-feature-docs/SKILL.md +22 -0
  61. package/resources/claude-customizations/.claude/skills/invoke-csharp-engineer/SKILL.md +64 -0
  62. package/resources/claude-customizations/.claude/skills/invoke-powershell-engineer/SKILL.md +65 -0
  63. package/resources/claude-customizations/.claude/skills/invoke-python-engineer/SKILL.md +64 -0
  64. package/resources/claude-customizations/.claude/skills/make-skill-template/SKILL.md +147 -0
  65. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +132 -0
  66. package/resources/claude-customizations/.claude/skills/policy-audit-template-usage/SKILL.md +49 -0
  67. package/resources/claude-customizations/.claude/skills/policy-compliance-order/SKILL.md +40 -0
  68. package/resources/claude-customizations/.claude/skills/powershell-change-budget-router/SKILL.md +49 -0
  69. package/resources/claude-customizations/.claude/skills/powershell-orchestration-state-machine/SKILL.md +58 -0
  70. package/resources/claude-customizations/.claude/skills/powershell-qa-gate/SKILL.md +77 -0
  71. package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +50 -0
  72. package/resources/claude-customizations/.claude/skills/pr-base-branch-merge-base/SKILL.md +56 -0
  73. package/resources/claude-customizations/.claude/skills/pr-context-artifacts/SKILL.md +30 -0
  74. package/resources/claude-customizations/.claude/skills/python-change-budget-router/SKILL.md +79 -0
  75. package/resources/claude-customizations/.claude/skills/python-qa-gate/SKILL.md +77 -0
  76. package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +40 -0
  77. package/resources/claude-customizations/.claude/skills/research-issue/SKILL.md +67 -0
  78. package/resources/claude-customizations/.claude/skills/review-epic/SKILL.md +21 -0
  79. package/resources/claude-customizations/.claude/skills/review-feature/SKILL.md +25 -0
  80. package/resources/claude-customizations/.claude/skills/review-staged/SKILL.md +21 -0
  81. package/resources/claude-customizations/.claude/skills/skill-canonical-location-audit/SKILL.md +49 -0
  82. package/resources/claude-customizations/.claude/skills/translate-copilot-to-claude/SKILL.md +295 -0
  83. package/resources/claude-customizations/.claude/skills/update-status/SKILL.md +21 -0
  84. package/resources/claude-dir-customizations/.mcp.json +8 -0
  85. package/resources/codex-and-agents-customizations/.agents/README.md +86 -0
  86. package/resources/codex-and-agents-customizations/.agents/skills/README.md +49 -0
  87. package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +107 -0
  88. package/resources/codex-and-agents-customizations/.agents/skills/atomic-executor/SKILL.md +73 -0
  89. package/resources/codex-and-agents-customizations/.agents/skills/atomic-plan-contract/SKILL.md +194 -0
  90. package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +87 -0
  91. package/resources/codex-and-agents-customizations/.agents/skills/commit-message/SKILL.md +70 -0
  92. package/resources/codex-and-agents-customizations/.agents/skills/commit-message-conventions/SKILL.md +95 -0
  93. package/resources/codex-and-agents-customizations/.agents/skills/csharp/SKILL.md +67 -0
  94. package/resources/codex-and-agents-customizations/.agents/skills/csharp-change-budget-router/SKILL.md +94 -0
  95. package/resources/codex-and-agents-customizations/.agents/skills/csharp-orchestration-state-machine/SKILL.md +64 -0
  96. package/resources/codex-and-agents-customizations/.agents/skills/csharp-qa-gate/SKILL.md +82 -0
  97. package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +168 -0
  98. package/resources/codex-and-agents-customizations/.agents/skills/execute-hard-lock/SKILL.md +88 -0
  99. package/resources/codex-and-agents-customizations/.agents/skills/feature-promotion-lifecycle/SKILL.md +129 -0
  100. package/resources/codex-and-agents-customizations/.agents/skills/feature-review/SKILL.md +106 -0
  101. package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +181 -0
  102. package/resources/codex-and-agents-customizations/.agents/skills/fill-feature-docs/SKILL.md +27 -0
  103. package/resources/codex-and-agents-customizations/.agents/skills/invoke-csharp-engineer/SKILL.md +73 -0
  104. package/resources/codex-and-agents-customizations/.agents/skills/invoke-powershell-engineer/SKILL.md +74 -0
  105. package/resources/codex-and-agents-customizations/.agents/skills/invoke-python-engineer/SKILL.md +73 -0
  106. package/resources/codex-and-agents-customizations/.agents/skills/make-skill-template/SKILL.md +152 -0
  107. package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +143 -0
  108. package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +317 -0
  109. package/resources/codex-and-agents-customizations/.agents/skills/policy-audit-template-usage/SKILL.md +53 -0
  110. package/resources/codex-and-agents-customizations/.agents/skills/policy-compliance-order/SKILL.md +49 -0
  111. package/resources/codex-and-agents-customizations/.agents/skills/powershell/SKILL.md +102 -0
  112. package/resources/codex-and-agents-customizations/.agents/skills/powershell-change-budget-router/SKILL.md +53 -0
  113. package/resources/codex-and-agents-customizations/.agents/skills/powershell-orchestration-state-machine/SKILL.md +64 -0
  114. package/resources/codex-and-agents-customizations/.agents/skills/powershell-qa-gate/SKILL.md +83 -0
  115. package/resources/codex-and-agents-customizations/.agents/skills/pr-author/SKILL.md +55 -0
  116. package/resources/codex-and-agents-customizations/.agents/skills/pr-authoring/SKILL.md +124 -0
  117. package/resources/codex-and-agents-customizations/.agents/skills/pr-base-branch-merge-base/SKILL.md +60 -0
  118. package/resources/codex-and-agents-customizations/.agents/skills/pr-context-artifacts/SKILL.md +34 -0
  119. package/resources/codex-and-agents-customizations/.agents/skills/python/SKILL.md +104 -0
  120. package/resources/codex-and-agents-customizations/.agents/skills/python-change-budget-router/SKILL.md +84 -0
  121. package/resources/codex-and-agents-customizations/.agents/skills/python-qa-gate/SKILL.md +82 -0
  122. package/resources/codex-and-agents-customizations/.agents/skills/python-suppressions/SKILL.md +148 -0
  123. package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +49 -0
  124. package/resources/codex-and-agents-customizations/.agents/skills/repo-automation-adapter/SKILL.md +142 -0
  125. package/resources/codex-and-agents-customizations/.agents/skills/repo-automation-adapter/agents/openai.yaml +5 -0
  126. package/resources/codex-and-agents-customizations/.agents/skills/research-issue/SKILL.md +72 -0
  127. package/resources/codex-and-agents-customizations/.agents/skills/review-epic/SKILL.md +26 -0
  128. package/resources/codex-and-agents-customizations/.agents/skills/review-feature/SKILL.md +30 -0
  129. package/resources/codex-and-agents-customizations/.agents/skills/review-staged/SKILL.md +26 -0
  130. package/resources/codex-and-agents-customizations/.agents/skills/self-explanatory-code-commenting/SKILL.md +102 -0
  131. package/resources/codex-and-agents-customizations/.agents/skills/skill-canonical-location-audit/SKILL.md +52 -0
  132. package/resources/codex-and-agents-customizations/.agents/skills/translate-copilot-to-claude/SKILL.md +317 -0
  133. package/resources/codex-and-agents-customizations/.agents/skills/typescript/SKILL.md +50 -0
  134. package/resources/codex-and-agents-customizations/.agents/skills/typescript-suppressions/SKILL.md +71 -0
  135. package/resources/codex-and-agents-customizations/.agents/skills/update-status/SKILL.md +26 -0
  136. package/resources/codex-and-agents-customizations/.codex/agents/5.1-beast-adjusted.toml +23 -0
  137. package/resources/codex-and-agents-customizations/.codex/agents/5.1-thinking-beast-mode-adjusted.toml +23 -0
  138. package/resources/codex-and-agents-customizations/.codex/agents/api-architect.toml +23 -0
  139. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +151 -0
  140. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +93 -0
  141. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planning.toml +24 -0
  142. package/resources/codex-and-agents-customizations/.codex/agents/commentary-remediation.toml +23 -0
  143. package/resources/codex-and-agents-customizations/.codex/agents/commit-steward.toml +20 -0
  144. package/resources/codex-and-agents-customizations/.codex/agents/csharp-atomic-executor.toml +24 -0
  145. package/resources/codex-and-agents-customizations/.codex/agents/csharp-atomic-planning.toml +25 -0
  146. package/resources/codex-and-agents-customizations/.codex/agents/csharp-orchestrator.toml +56 -0
  147. package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer.toml +97 -0
  148. package/resources/codex-and-agents-customizations/.codex/agents/epic-review.toml +52 -0
  149. package/resources/codex-and-agents-customizations/.codex/agents/expert-nextjs-developer.toml +23 -0
  150. package/resources/codex-and-agents-customizations/.codex/agents/expert-react-frontend-engineer.toml +23 -0
  151. package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +149 -0
  152. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer.toml +60 -0
  153. package/resources/codex-and-agents-customizations/.codex/agents/gpt-5-beast-mode.toml +23 -0
  154. package/resources/codex-and-agents-customizations/.codex/agents/hlbpa.toml +23 -0
  155. package/resources/codex-and-agents-customizations/.codex/agents/mentor.toml +23 -0
  156. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +121 -0
  157. package/resources/codex-and-agents-customizations/.codex/agents/powershell-atomic-executor.toml +24 -0
  158. package/resources/codex-and-agents-customizations/.codex/agents/powershell-atomic-planning.toml +25 -0
  159. package/resources/codex-and-agents-customizations/.codex/agents/powershell-di-unit-test-engineer.toml +24 -0
  160. package/resources/codex-and-agents-customizations/.codex/agents/powershell-orchestrator.toml +56 -0
  161. package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer.toml +108 -0
  162. package/resources/codex-and-agents-customizations/.codex/agents/pr-author.toml +26 -0
  163. package/resources/codex-and-agents-customizations/.codex/agents/prd-feature.toml +53 -0
  164. package/resources/codex-and-agents-customizations/.codex/agents/prd.toml +23 -0
  165. package/resources/codex-and-agents-customizations/.codex/agents/pytest-unit-test-coding.toml +24 -0
  166. package/resources/codex-and-agents-customizations/.codex/agents/python-atomic-executor.toml +24 -0
  167. package/resources/codex-and-agents-customizations/.codex/agents/python-atomic-planning.toml +25 -0
  168. package/resources/codex-and-agents-customizations/.codex/agents/python-execution-only-typed.toml +24 -0
  169. package/resources/codex-and-agents-customizations/.codex/agents/python-orchestrator.toml +54 -0
  170. package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer.toml +100 -0
  171. package/resources/codex-and-agents-customizations/.codex/agents/staged-review.toml +53 -0
  172. package/resources/codex-and-agents-customizations/.codex/agents/status-updater.toml +53 -0
  173. package/resources/codex-and-agents-customizations/.codex/agents/task-researcher.toml +103 -0
  174. package/resources/codex-and-agents-customizations/.codex/agents/tdd-green.toml +23 -0
  175. package/resources/codex-and-agents-customizations/.codex/agents/tdd-red.toml +23 -0
  176. package/resources/codex-and-agents-customizations/.codex/agents/tdd-refactor.toml +23 -0
  177. package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer.toml +48 -0
  178. package/resources/codex-and-agents-customizations/.codex/agents/voidbeast-gpt41enhanced.toml +23 -0
  179. package/resources/codex-and-agents-customizations/.codex/codex-web-setup.plan.md +26 -0
  180. package/resources/codex-and-agents-customizations/.codex/codex-web-setup.sh +384 -0
  181. package/resources/codex-and-agents-customizations/.codex/config.toml +137 -0
  182. package/resources/codex-and-agents-customizations/.codex/hooks/check-powershell-test-purity.ps1 +113 -0
  183. package/resources/codex-and-agents-customizations/.codex/hooks/check-python-test-purity.ps1 +149 -0
  184. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-evidence-locations.ps1 +153 -0
  185. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +241 -0
  186. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-promotion-mcp-only.ps1 +150 -0
  187. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +238 -0
  188. package/resources/codex-and-agents-customizations/.codex/hooks/validate-bash.ps1 +72 -0
  189. package/resources/codex-and-agents-customizations/.codex/hooks/validate-feature-review-coverage.ps1 +265 -0
  190. package/resources/codex-and-agents-customizations/.codex/prompts/feature-review-remediate.md +10 -0
  191. package/resources/codex-and-agents-customizations/.codex/prompts/generate-commit-message-repo.md +11 -0
  192. package/resources/codex-and-agents-customizations/.codex/prompts/generate-pr.md +15 -0
  193. package/resources/codex-and-agents-customizations/.codex/prompts/orchestrate-work.md +22 -0
  194. package/resources/codex-and-agents-customizations/AGENTS.md +317 -0
  195. package/resources/customizations/.github/agents/5.1-Beast-adjusted.agent.md +181 -0
  196. package/resources/customizations/.github/agents/5.1-Thinking-Beast-Mode-adjusted.agent.md +361 -0
  197. package/resources/customizations/.github/agents/Powershell DI Unit Test Engineer.agent.md +192 -0
  198. package/resources/customizations/.github/agents/api-architect.agent.md +40 -0
  199. package/resources/customizations/.github/agents/atomic_executor.agent.md +251 -0
  200. package/resources/customizations/.github/agents/atomic_planning.agent.md +658 -0
  201. package/resources/customizations/.github/agents/commentary-remediation.agent.md +35 -0
  202. package/resources/customizations/.github/agents/commit-steward.agent.md +200 -0
  203. package/resources/customizations/.github/agents/csharp-atomic-executor.agent.md +288 -0
  204. package/resources/customizations/.github/agents/csharp-atomic-planning.agent.md +354 -0
  205. package/resources/customizations/.github/agents/csharp-orchestrator.agent.md +375 -0
  206. package/resources/customizations/.github/agents/csharp-typed-engineer.agent.md +285 -0
  207. package/resources/customizations/.github/agents/epic-review.agent.md +374 -0
  208. package/resources/customizations/.github/agents/expert-nextjs-developer.agent.md +477 -0
  209. package/resources/customizations/.github/agents/expert-react-frontend-engineer.agent.md +739 -0
  210. package/resources/customizations/.github/agents/feature-review.agent.md +49 -0
  211. package/resources/customizations/.github/agents/gpt-5-beast-mode.agent.md +116 -0
  212. package/resources/customizations/.github/agents/hlbpa.agent.md +219 -0
  213. package/resources/customizations/.github/agents/mentor.agent.md +32 -0
  214. package/resources/customizations/.github/agents/orchestrator.agent.md +449 -0
  215. package/resources/customizations/.github/agents/powershell-atomic-executor.agent.md +287 -0
  216. package/resources/customizations/.github/agents/powershell-atomic-planning.agent.md +647 -0
  217. package/resources/customizations/.github/agents/powershell-orchestrator.agent.md +382 -0
  218. package/resources/customizations/.github/agents/powershell-typed-engineer.agent.md +293 -0
  219. package/resources/customizations/.github/agents/pr-author.agent.md +138 -0
  220. package/resources/customizations/.github/agents/prd-feature.agent.md +52 -0
  221. package/resources/customizations/.github/agents/prd.agent.md +202 -0
  222. package/resources/customizations/.github/agents/pytest-unit-test-coding.agent.md +202 -0
  223. package/resources/customizations/.github/agents/python-atomic-executor.agent.md +289 -0
  224. package/resources/customizations/.github/agents/python-atomic-planning.agent.md +429 -0
  225. package/resources/customizations/.github/agents/python-execution-only-typed.agent.md +217 -0
  226. package/resources/customizations/.github/agents/python-orchestrator.agent.md +380 -0
  227. package/resources/customizations/.github/agents/python-typed-engineer.agent.md +271 -0
  228. package/resources/customizations/.github/agents/staged-review.agent.md +246 -0
  229. package/resources/customizations/.github/agents/status_updater.agent.md +279 -0
  230. package/resources/customizations/.github/agents/task-researcher.agent.md +298 -0
  231. package/resources/customizations/.github/agents/tdd-green.agent.md +60 -0
  232. package/resources/customizations/.github/agents/tdd-red.agent.md +66 -0
  233. package/resources/customizations/.github/agents/tdd-refactor.agent.md +94 -0
  234. package/resources/customizations/.github/agents/typescript-engineer.agent.md +167 -0
  235. package/resources/customizations/.github/agents/voidbeast-gpt41enhanced.agent.md +230 -0
  236. package/resources/customizations/.github/codex/execute-hard-lock.prompt.md +105 -0
  237. package/resources/customizations/.github/codex/resume-hard-lock.prompt.md +92 -0
  238. package/resources/customizations/.github/copilot-instructions.md +7 -0
  239. package/resources/customizations/.github/instructions/csharp-code-change.instructions.md +184 -0
  240. package/resources/customizations/.github/instructions/csharp-unit-test.instructions.md +52 -0
  241. package/resources/customizations/.github/instructions/general-code-change.instructions.md +290 -0
  242. package/resources/customizations/.github/instructions/general-unit-test.instructions.md +106 -0
  243. package/resources/customizations/.github/instructions/github-actions-ci-cd-best-practices.instructions.md +607 -0
  244. package/resources/customizations/.github/instructions/github-actions.instructions.md +23 -0
  245. package/resources/customizations/.github/instructions/powershell-code-change.instructions.md +81 -0
  246. package/resources/customizations/.github/instructions/powershell-unit-test.instructions.md +69 -0
  247. package/resources/customizations/.github/instructions/python-code-change.instructions.md +232 -0
  248. package/resources/customizations/.github/instructions/python-suppressions.instructions.md +609 -0
  249. package/resources/customizations/.github/instructions/python-unit-test.instructions.md +71 -0
  250. package/resources/customizations/.github/instructions/self-explanatory-code-commenting.instructions.md +238 -0
  251. package/resources/customizations/.github/instructions/tonality.instructions.md +133 -0
  252. package/resources/customizations/.github/instructions/typescript-code-change.instructions.md +203 -0
  253. package/resources/customizations/.github/instructions/typescript-suppressions.instructions.md +157 -0
  254. package/resources/customizations/.github/instructions/typescript-unit-test.instructions.md +112 -0
  255. package/resources/customizations/.github/prompts/add-educational-comments.prompt.md +129 -0
  256. package/resources/customizations/.github/prompts/breakdown-bug-prd.prompt.md +29 -0
  257. package/resources/customizations/.github/prompts/breakdown-epic-arch.prompt.md +66 -0
  258. package/resources/customizations/.github/prompts/breakdown-epic-pm.prompt.md +58 -0
  259. package/resources/customizations/.github/prompts/breakdown-feature-implementation.prompt.md +128 -0
  260. package/resources/customizations/.github/prompts/breakdown-feature-prd.prompt.md +61 -0
  261. package/resources/customizations/.github/prompts/code-exemplars-blueprint-generator.prompt.md +126 -0
  262. package/resources/customizations/.github/prompts/drafts/create-github-issues-feature-from-implementation-plan.prompt.md +28 -0
  263. package/resources/customizations/.github/prompts/drafts/create-implementation-plan.prompt.md +158 -0
  264. package/resources/customizations/.github/prompts/drafts/create-technical-spike.prompt.md +231 -0
  265. package/resources/customizations/.github/prompts/drafts/potential-feature-prd.prompt.md +19 -0
  266. package/resources/customizations/.github/prompts/drafts/update-implementation-plan.prompt.md +158 -0
  267. package/resources/customizations/.github/prompts/execute-plan-template.md +21 -0
  268. package/resources/customizations/.github/prompts/export-chat.prompt.md +7 -0
  269. package/resources/customizations/.github/prompts/fillout-prd-feature.prompt.md +46 -0
  270. package/resources/customizations/.github/prompts/generate-atomic-plan.prompt.md +96 -0
  271. package/resources/customizations/.github/prompts/generate-commit-message-repo.prompt.md +108 -0
  272. package/resources/customizations/.github/prompts/generate-pr.prompt.md +151 -0
  273. package/resources/customizations/.github/prompts/javascript-typescript-jest.prompt.md +44 -0
  274. package/resources/customizations/.github/prompts/orchestrate-csharp-work.prompt.md +66 -0
  275. package/resources/customizations/.github/prompts/orchestrate-powershell-work.prompt.md +50 -0
  276. package/resources/customizations/.github/prompts/orchestrate-python-work.prompt.md +50 -0
  277. package/resources/customizations/.github/prompts/orchestrate-work.prompt.md +66 -0
  278. package/resources/customizations/.github/prompts/remediate-comments.prompt.md +53 -0
  279. package/resources/customizations/.github/prompts/research-issue.prompt.md +125 -0
  280. package/resources/customizations/.github/prompts/review-epic.prompt.md +94 -0
  281. package/resources/customizations/.github/prompts/review-feature.prompt.md +130 -0
  282. package/resources/customizations/.github/prompts/review-staged.prompt.md +43 -0
  283. package/resources/customizations/.github/prompts/update_status.prompt.md +68 -0
  284. package/resources/customizations/.github/skills/README.md +26 -0
  285. package/resources/customizations/.github/skills/acceptance-criteria-tracking/SKILL.md +102 -0
  286. package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +174 -0
  287. package/resources/customizations/.github/skills/csharp-change-budget-router/SKILL.md +48 -0
  288. package/resources/customizations/.github/skills/csharp-orchestration-state-machine/SKILL.md +57 -0
  289. package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +135 -0
  290. package/resources/customizations/.github/skills/feature-promotion-lifecycle/SKILL.md +121 -0
  291. package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +153 -0
  292. package/resources/customizations/.github/skills/make-skill-template/SKILL.md +147 -0
  293. package/resources/customizations/.github/skills/policy-audit-template-usage/SKILL.md +48 -0
  294. package/resources/customizations/.github/skills/policy-compliance-order/SKILL.md +37 -0
  295. package/resources/customizations/.github/skills/powershell-change-budget-router/SKILL.md +48 -0
  296. package/resources/customizations/.github/skills/powershell-orchestration-state-machine/SKILL.md +57 -0
  297. package/resources/customizations/.github/skills/pr-base-branch-merge-base/SKILL.md +55 -0
  298. package/resources/customizations/.github/skills/pr-context-artifacts/SKILL.md +29 -0
  299. package/resources/customizations/.github/skills/remediation-handoff-atomic-planner/SKILL.md +39 -0
  300. package/resources/customizations/.github/skills/skill-canonical-location-audit/SKILL.md +48 -0
  301. package/resources/feature-templates/bug/plan.yyyy-MM-ddTHH-mm.md +44 -0
  302. package/resources/feature-templates/bug/potential_bug.md +59 -0
  303. package/resources/feature-templates/bug/spec.md +99 -0
  304. package/resources/feature-templates/epic/initiative.md +43 -0
  305. package/resources/feature-templates/feature/plan.yyyy-MM-ddTHH-mm.md +53 -0
  306. package/resources/feature-templates/feature/spec.md +66 -0
  307. package/resources/feature-templates/feature/user-story.md +42 -0
  308. package/resources/feature-templates/potential/template.md +33 -0
  309. package/resources/feature-templates/refactor/plan.yyyy-MM-ddTHH-mm.md +52 -0
  310. package/resources/feature-templates/refactor/spec.md +69 -0
  311. package/resources/powershell/PoshQC/PoshQC.Analyzer.psm1 +254 -0
  312. package/resources/powershell/PoshQC/PoshQC.FileDiscovery.psm1 +138 -0
  313. package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +409 -0
  314. package/resources/powershell/PoshQC/PoshQC.psd1 +31 -0
  315. package/resources/powershell/PoshQC/PoshQC.psm1 +101 -0
  316. package/resources/powershell/PoshQC/README.md +80 -0
  317. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +59 -0
  318. package/resources/powershell/PoshQC/settings/pssa.settings.psd1 +55 -0
  319. package/resources/scripts/dev_tools/__init__.py +0 -0
  320. package/resources/scripts/dev_tools/agentic_sync.py +819 -0
  321. package/resources/scripts/dev_tools/codex_native_converter/__init__.py +11 -0
  322. package/resources/scripts/dev_tools/codex_native_converter/__main__.py +6 -0
  323. package/resources/scripts/dev_tools/codex_native_converter/cli.py +11 -0
  324. package/resources/scripts/dev_tools/new_active_feature_folder.py +79 -0
  325. package/resources/scripts/dev_tools/new_active_feature_folder_docs.py +268 -0
  326. package/resources/scripts/dev_tools/new_active_feature_folder_flow.py +366 -0
  327. package/resources/scripts/dev_tools/new_active_feature_folder_io.py +306 -0
  328. package/resources/scripts/dev_tools/new_active_feature_folder_markdown.py +252 -0
  329. package/resources/scripts/dev_tools/new_active_feature_folder_models.py +136 -0
  330. package/resources/scripts/dev_tools/new_potential_bug_entry.py +465 -0
  331. package/resources/scripts/dev_tools/potential_to_issue.py +421 -0
  332. package/resources/scripts/dev_tools/potential_to_issue_content.py +212 -0
  333. package/resources/scripts/dev_tools/pr_context/__init__.py +0 -0
  334. package/resources/scripts/dev_tools/pr_context/collector.py +619 -0
  335. package/resources/scripts/dev_tools/pr_context/feature_docs.py +349 -0
  336. package/resources/scripts/dev_tools/pr_context/git.py +153 -0
  337. package/resources/scripts/dev_tools/pr_context/github.py +549 -0
  338. package/resources/scripts/dev_tools/pr_context/models.py +198 -0
  339. package/resources/scripts/dev_tools/pr_context/render.py +342 -0
  340. package/resources/scripts/dev_tools/pr_context/render_feature_excerpts.py +256 -0
  341. package/resources/scripts/dev_tools/pr_context/render_pr_helpers.py +291 -0
  342. package/resources/scripts/dev_tools/pr_context/summary_helpers.py +386 -0
  343. package/resources/scripts/dev_tools/pr_context/verification_evidence.py +171 -0
  344. package/resources/scripts/dev_tools/prompt_mode_contract.py +152 -0
  345. package/resources/scripts/dev_tools/push_down_claude_customizations.py +188 -0
  346. package/resources/scripts/dev_tools/push_down_codex_and_agents_customizations.py +139 -0
  347. package/resources/scripts/dev_tools/push_down_copilot_customizations.py +504 -0
  348. package/resources/scripts/dev_tools/push_down_copilot_customizations_filesystem.py +217 -0
  349. package/resources/scripts/dev_tools/push_down_copilot_customizations_rewrites.py +293 -0
  350. package/resources/scripts/dev_tools/resolve_file_prompt.py +457 -0
  351. package/resources/scripts/dev_tools/resolve_hard_lock_prompt.py +444 -0
  352. package/resources/scripts/dev_tools/validate_orchestration_artifacts.py +554 -0
  353. package/resources/templates/codex_native_converter.py +35 -0
  354. package/resources/templates/collect_commit_context.py +212 -0
  355. package/resources/templates/collect_pr_context.py +74 -0
  356. package/resources/templates/hello_pwsh.ps1 +3 -0
  357. package/resources/templates/hello_python.py +11 -0
  358. package/resources/templates/link-parent-child.ps1 +480 -0
  359. package/resources/templates/new-claude-worktree-session.ps1 +232 -0
  360. package/resources/templates/new-potential-entry.ps1 +187 -0
  361. package/resources/templates/new_active_feature_folder.py +67 -0
  362. package/resources/templates/new_potential_bug_entry.py +54 -0
  363. package/resources/templates/policy_audit/AGENTS.md +117 -0
  364. package/resources/templates/policy_audit/code-review.yyyy-MM-ddTHH-mm.md +165 -0
  365. package/resources/templates/policy_audit/feature-audit.yyyy-MM-ddTHH-mm.md +124 -0
  366. package/resources/templates/policy_audit/policy-audit.yyyy-MM-ddTHH-mm.md +649 -0
  367. package/resources/templates/potential_to_issue.py +55 -0
  368. package/resources/templates/push_down_claude_customizations.py +188 -0
  369. package/resources/templates/push_down_codex_and_agents_customizations.py +95 -0
  370. package/resources/templates/push_down_copilot_customizations.py +124 -0
  371. package/resources/templates/resolve_atomic_plan_prompt.py +75 -0
  372. package/resources/templates/resolve_hard_lock_prompt.py +65 -0
  373. package/resources/templates/run-poshqc-analyze-autofix.ps1 +16 -0
  374. package/resources/templates/run-poshqc-analyze.ps1 +26 -0
  375. package/resources/templates/run-poshqc-format.ps1 +26 -0
  376. package/resources/templates/run-poshqc-suite.ps1 +24 -0
  377. package/resources/templates/run-poshqc-test.ps1 +32 -0
  378. package/resources/templates/sync-agents-from-instructions.ps1 +400 -0
  379. package/resources/templates/validate_orchestration_artifacts.py +55 -0
  380. package/resources/templates/vscode-cli.helpers.ps1 +63 -0
@@ -0,0 +1,256 @@
1
+ """Feature-document excerpt helpers for PR context rendering."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from pathlib import Path
7
+ from typing import TYPE_CHECKING
8
+
9
+ from .models import FeatureDocExcerpt, section, truncate
10
+
11
+ if TYPE_CHECKING:
12
+ from collections.abc import Iterable
13
+
14
+
15
+ def parse_section(markdown: str, heading: str) -> str:
16
+ """Extract markdown content under a top-level `##` heading."""
17
+ escaped = re.escape(heading)
18
+ pattern = rf"^##\s+{escaped}\s*\r?\n(.*?)(?=^##\s+|\Z)"
19
+ match = re.search(pattern, markdown, flags=re.MULTILINE | re.DOTALL)
20
+ if not match:
21
+ return ""
22
+ return match.group(1).strip()
23
+
24
+
25
+ def _extract_issue_references(text: str) -> list[str]:
26
+ """Extract normalized issue reference tokens from freeform text."""
27
+ if not text:
28
+ return []
29
+ matches = re.findall(r"(?<!\w)#\d+|\b[A-Z][A-Z0-9]+-\d+\b", text)
30
+ seen: set[str] = set()
31
+ ordered: list[str] = []
32
+ for item in matches:
33
+ if item not in seen:
34
+ seen.add(item)
35
+ ordered.append(item)
36
+ return ordered
37
+
38
+
39
+ def completed_plan_tasks(markdown: str, *, limit: int = 10) -> list[str]:
40
+ """Return up to `limit` completed checklist items from markdown."""
41
+ tasks: list[str] = []
42
+ for line in markdown.splitlines():
43
+ if re.search(r"\[x\]", line, flags=re.IGNORECASE):
44
+ cleaned = re.sub(r"^[-*]\s*\[[xX]\]\s*", "", line).strip()
45
+ tasks.append(cleaned)
46
+ if len(tasks) >= limit:
47
+ break
48
+ return tasks
49
+
50
+
51
+ def directory_exists(path: Path) -> bool:
52
+ """Return whether the provided path exists."""
53
+ return path.exists()
54
+
55
+
56
+ def resolve_feature_dir(base_dir: Path, feature: str) -> Path | None:
57
+ """Resolve feature directory by exact, strong-pattern, then weak match."""
58
+ direct = base_dir / feature
59
+ if directory_exists(direct):
60
+ return direct
61
+
62
+ if not directory_exists(base_dir):
63
+ return None
64
+
65
+ pattern = re.compile(rf"(?:^|[-_]){re.escape(feature)}(?:[-_]|$)")
66
+ strong_matches: list[Path] = []
67
+ weak_matches: list[Path] = []
68
+
69
+ for candidate in sorted(base_dir.iterdir()):
70
+ if not candidate.is_dir():
71
+ continue
72
+ name = candidate.name
73
+ if pattern.search(name):
74
+ strong_matches.append(candidate)
75
+ elif feature in name:
76
+ weak_matches.append(candidate)
77
+
78
+ if strong_matches:
79
+ return strong_matches[0]
80
+ if weak_matches:
81
+ return weak_matches[0]
82
+ return None
83
+
84
+
85
+ def read_text_file(path: Path) -> str:
86
+ """Read UTF-8 text if the path exists, otherwise return an empty string."""
87
+ return path.read_text(encoding="utf-8") if path.exists() else ""
88
+
89
+
90
+ def extract_features_from_paths(changed_files: Iterable[str]) -> set[str]:
91
+ """Extract feature directory names from `docs/features/active/**` paths."""
92
+ features: set[str] = set()
93
+ for raw in changed_files:
94
+ parts = Path(raw).parts
95
+ if (
96
+ len(parts) >= 4
97
+ and parts[0] == "docs"
98
+ and parts[1] == "features"
99
+ and parts[2] == "active"
100
+ ):
101
+ features.add(parts[3])
102
+ return features
103
+
104
+
105
+ def extract_spec_parts(spec_text: str) -> list[str]:
106
+ """Extract high-value sections from a feature spec document."""
107
+ spec_parts: list[str] = []
108
+ for heading in (
109
+ "Context",
110
+ "Root Cause",
111
+ "Root Cause/Problem",
112
+ "Problem",
113
+ "Proposed Fix",
114
+ "Acceptance Criteria",
115
+ "Constraints & Risks",
116
+ "Behavior",
117
+ "Overview",
118
+ ):
119
+ section_text = parse_section(spec_text, heading)
120
+ if section_text:
121
+ spec_parts.append(f"{heading}: {truncate(section_text)}")
122
+ return spec_parts
123
+
124
+
125
+ def extract_plan_sections(plan_text: str) -> tuple[str, str]:
126
+ """Extract completed tasks and verification notes from a plan document."""
127
+ plan_tasks = completed_plan_tasks(plan_text)
128
+ plan_section = "\n".join(f"- {task}" for task in plan_tasks) if plan_tasks else ""
129
+ # Keep fallback order aligned with feature_docs for consistent semantics.
130
+ test_plan_section = parse_section(plan_text, "Verification")
131
+ if not test_plan_section:
132
+ test_plan_section = parse_section(plan_text, "Test Plan")
133
+ verification_block = (
134
+ "Plan verification notes:\n" + truncate(test_plan_section)
135
+ if test_plan_section
136
+ else ""
137
+ )
138
+ return plan_section, verification_block
139
+
140
+
141
+ def extract_story_parts(user_story_text: str, promoted_story_text: str) -> list[str]:
142
+ """Extract story statement/problem snippets from user-story content."""
143
+ story_parts: list[str] = []
144
+ story_statements = parse_section(user_story_text, "Story Statement")
145
+ if story_statements:
146
+ story_lines = [
147
+ line.strip("- ") for line in story_statements.splitlines() if line.strip()
148
+ ]
149
+ if story_lines:
150
+ story_parts.append(
151
+ "Story Statement:\n" + "\n".join(f"- {line}" for line in story_lines)
152
+ )
153
+ problem_section = parse_section(user_story_text, "Problem / Why")
154
+ if problem_section:
155
+ story_parts.append("Problem / Why:\n" + truncate(problem_section))
156
+ if not story_parts and promoted_story_text:
157
+ promoted_problem = parse_section(promoted_story_text, "Problem / Why")
158
+ if not promoted_problem:
159
+ promoted_problem = parse_section(promoted_story_text, "Summary")
160
+ if promoted_problem:
161
+ story_parts.append("Problem / Why:\n" + truncate(promoted_problem))
162
+ return story_parts
163
+
164
+
165
+ def build_excerpt_text(
166
+ feature: str,
167
+ story_parts: list[str],
168
+ spec_parts: list[str],
169
+ plan_section: str,
170
+ verification_block: str,
171
+ ) -> str:
172
+ """Build a formatted feature excerpt block from collected sections."""
173
+ lines: list[str] = [section(f"Feature doc: {feature}")]
174
+ if story_parts:
175
+ lines.append("User story excerpts:\n" + "\n\n".join(story_parts))
176
+ if spec_parts:
177
+ lines.append("Spec excerpts:\n" + "\n\n".join(spec_parts))
178
+ if plan_section:
179
+ lines.append("Plan completed tasks:\n" + plan_section)
180
+ if verification_block:
181
+ lines.append(verification_block)
182
+ if len(lines) == 1:
183
+ lines.append("(no spec/plan/user-story excerpts found)")
184
+ return "\n".join(lines)
185
+
186
+
187
+ def gather_feature_excerpts(
188
+ root: Path, changed_files: Iterable[str]
189
+ ) -> list[FeatureDocExcerpt]:
190
+ """Gather feature excerpt payloads for changed active-feature files."""
191
+ features = extract_features_from_paths(changed_files)
192
+ excerpts: list[FeatureDocExcerpt] = []
193
+ base_dir = root / "docs" / "features" / "active"
194
+ promoted_dir = root / "docs" / "features" / "potential" / "promoted"
195
+
196
+ for feature in sorted(features):
197
+ feature_dir = resolve_feature_dir(base_dir, feature)
198
+ promoted_feature_dir = resolve_feature_dir(promoted_dir, feature)
199
+ if feature_dir is None and promoted_feature_dir is None:
200
+ continue
201
+
202
+ active_dir = feature_dir or promoted_feature_dir
203
+ if active_dir is None:
204
+ continue
205
+
206
+ spec_path = active_dir / "spec.md"
207
+ plan_path = active_dir / "plan.md"
208
+ user_story_path: Path = active_dir / "user-story.md"
209
+ promoted_story_path = (
210
+ promoted_feature_dir / "user-story.md"
211
+ if promoted_feature_dir is not None
212
+ else None
213
+ )
214
+ promoted_story_text = (
215
+ read_text_file(promoted_story_path) if promoted_story_path else ""
216
+ )
217
+ if promoted_story_path is not None and not user_story_path.exists():
218
+ user_story_path = promoted_story_path
219
+
220
+ user_story_text = read_text_file(user_story_path)
221
+ if (
222
+ not user_story_text
223
+ and promoted_story_text
224
+ and promoted_story_path is not None
225
+ ):
226
+ user_story_text = promoted_story_text
227
+ user_story_path = promoted_story_path
228
+
229
+ spec_text = read_text_file(spec_path)
230
+ plan_text = read_text_file(plan_path)
231
+
232
+ spec_parts = extract_spec_parts(spec_text)
233
+ plan_section, verification_block = extract_plan_sections(plan_text)
234
+ story_parts = extract_story_parts(user_story_text, promoted_story_text)
235
+ excerpt_text = build_excerpt_text(
236
+ feature, story_parts, spec_parts, plan_section, verification_block
237
+ )
238
+
239
+ context_files = [
240
+ str(path.relative_to(root))
241
+ for path in (spec_path, plan_path, user_story_path)
242
+ if path and path.exists()
243
+ ]
244
+ issue_refs = _extract_issue_references(
245
+ "\n".join([spec_text, plan_text, user_story_text])
246
+ )
247
+ excerpts.append(
248
+ FeatureDocExcerpt(
249
+ feature=feature,
250
+ excerpt=excerpt_text,
251
+ issue_refs=issue_refs,
252
+ context_files=context_files,
253
+ )
254
+ )
255
+
256
+ return excerpts
@@ -0,0 +1,291 @@
1
+ """PR context rendering utility helpers extracted from render module."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from pathlib import Path
7
+ from typing import TYPE_CHECKING
8
+
9
+ from .models import (
10
+ CONVENTIONAL_TYPES,
11
+ IssueDetails,
12
+ PullRequestDetails,
13
+ format_list,
14
+ section,
15
+ truncate,
16
+ )
17
+
18
+ if TYPE_CHECKING:
19
+ from collections.abc import Iterable
20
+
21
+ from .git import GitClient
22
+
23
+
24
+ def select_default_base(git: GitClient) -> str | None:
25
+ """Select the first existing base ref from standard default candidates."""
26
+ candidates = [
27
+ "origin/main",
28
+ "origin/master",
29
+ "main",
30
+ "master",
31
+ "origin/develop",
32
+ "develop",
33
+ ]
34
+ for ref in candidates:
35
+ result = git.run(["rev-parse", "--verify", "--quiet", ref], allow_error=True)
36
+ if result.code == 0 and result.stdout.strip():
37
+ return ref
38
+ return None
39
+
40
+
41
+ def format_diff_path(path_text: str | None) -> str:
42
+ """Normalize git diff path output, including rename syntax variants."""
43
+ if path_text is None:
44
+ return ""
45
+ if path_text.strip() == "":
46
+ return path_text
47
+
48
+ trimmed = path_text.strip().strip('"')
49
+ trimmed = re.sub(r"\{[^{}]*\s=>\s([^{}]*)\}", r"\1", trimmed)
50
+
51
+ arrow_match = re.match(r"^\s*(.+?)\s=>\s(.+?)\s*$", trimmed)
52
+ if arrow_match:
53
+ return arrow_match.group(2)
54
+ return trimmed
55
+
56
+
57
+ def convert_numstat(numstat_text: str) -> tuple[int, int, list[str]]:
58
+ """Convert git numstat output into totals and raw path list."""
59
+ adds = 0
60
+ dels = 0
61
+ files: list[str] = []
62
+
63
+ for raw_line in numstat_text.splitlines():
64
+ if not raw_line.strip():
65
+ continue
66
+
67
+ parts = raw_line.split("\t")
68
+ if len(parts) < 3:
69
+ continue
70
+
71
+ add_part, del_part, file_part = parts[0], parts[1], parts[2]
72
+ if add_part.isdigit():
73
+ adds += int(add_part)
74
+ if del_part.isdigit():
75
+ dels += int(del_part)
76
+ files.append(file_part)
77
+
78
+ return adds, dels, files
79
+
80
+
81
+ def extension_summary(files: Iterable[str]) -> str:
82
+ """Summarize changed files by extension."""
83
+ counts: dict[str, int] = {}
84
+ for raw in files:
85
+ name = format_diff_path(raw)
86
+ ext = "(unknown)"
87
+ try:
88
+ suffix = Path(name).suffix
89
+ ext = suffix if suffix else "(noext)"
90
+ except ValueError:
91
+ fallback = re.search(r"\.([A-Za-z0-9_]+)$", name)
92
+ ext = f".{fallback.group(1)}" if fallback else "(unknown)"
93
+
94
+ counts[ext] = counts.get(ext, 0) + 1
95
+
96
+ lines = [f"{counts[k]:8d} {k}" for k in sorted(counts)]
97
+ return "\n".join(lines)
98
+
99
+
100
+ def extract_issue_references(text: str) -> list[str]:
101
+ """Extract issue tokens like #123 and ABC-123 in encounter order."""
102
+ if not text:
103
+ return []
104
+ matches = re.findall(r"(?<!\w)#\d+|\b[A-Z][A-Z0-9]+-\d+\b", text)
105
+ seen: set[str] = set()
106
+ ordered: list[str] = []
107
+ for item in matches:
108
+ if item not in seen:
109
+ seen.add(item)
110
+ ordered.append(item)
111
+ return ordered
112
+
113
+
114
+ def extract_merge_pr_numbers(subjects: Iterable[str]) -> list[str]:
115
+ """Extract merged PR numbers from commit subject lines."""
116
+ numbers: set[str] = set()
117
+ pattern = re.compile(r"Merge pull request #(\d+)", re.IGNORECASE)
118
+ for subj in subjects:
119
+ match = pattern.search(subj)
120
+ if match:
121
+ numbers.add(f"#{match.group(1)}")
122
+ return sorted(numbers)
123
+
124
+
125
+ def summarize_conventional_commits(subjects: str) -> str:
126
+ """Count conventional commit types in subject lines."""
127
+ counts = {key: 0 for key in CONVENTIONAL_TYPES}
128
+ counts["other"] = 0
129
+
130
+ for line in subjects.splitlines():
131
+ line = line.strip()
132
+ if not line:
133
+ continue
134
+ match = re.match(
135
+ r"(feat|fix|refactor|perf|docs|test|chore|build|ci|style)(\(|!|:)",
136
+ line,
137
+ )
138
+ label = match.group(1) if match else "other"
139
+ counts[label] += 1
140
+
141
+ non_zero = [(k, v) for k, v in counts.items() if v > 0]
142
+ if not non_zero:
143
+ return "(no recognizable conventional commit types)"
144
+ return "\n".join(f"{name:<9} : {value}" for name, value in non_zero)
145
+
146
+
147
+ def format_issue_details(issue: IssueDetails) -> str:
148
+ """Render structured issue details for PR context appendix output."""
149
+ comments_text = format_list(issue.comments, "(no comments)")
150
+ lines = [
151
+ section(f"Issue {issue.number}: {issue.title}"),
152
+ f"State: {issue.state}",
153
+ f"Author: {issue.author}",
154
+ f"Labels: {', '.join(issue.labels) if issue.labels else '(none)'}",
155
+ f"Assignees: {', '.join(issue.assignees) if issue.assignees else '(none)'}",
156
+ f"Created: {issue.created_at}",
157
+ f"Updated: {issue.updated_at}",
158
+ "",
159
+ truncate(issue.body, 1200),
160
+ "",
161
+ "Comments:",
162
+ comments_text,
163
+ ]
164
+ if issue.user_story_content:
165
+ lines.extend(
166
+ [
167
+ "",
168
+ f"User story ({issue.user_story_path or 'user-story.md'}):",
169
+ truncate(issue.user_story_content, 1200),
170
+ ]
171
+ )
172
+ return "\n".join(lines)
173
+
174
+
175
+ def format_pr_details(pr: PullRequestDetails) -> str:
176
+ """Render structured pull request details for PR context appendix output."""
177
+ return "\n".join(
178
+ [
179
+ section(f"Pull Request {pr.number}: {pr.title}"),
180
+ f"State: {pr.state}",
181
+ f"Author: {pr.author}",
182
+ f"Base: {pr.base_ref}",
183
+ f"Head: {pr.head_ref}",
184
+ f"Created: {pr.created_at}",
185
+ f"Updated: {pr.updated_at}",
186
+ f"Merged: {pr.merged_at or '(not merged)'}",
187
+ f"Labels: {', '.join(pr.labels) if pr.labels else '(none)'}",
188
+ f"Assignees: {', '.join(pr.assignees) if pr.assignees else '(none)'}",
189
+ truncate(pr.body, 1200),
190
+ "",
191
+ "Auto-close issues (from this PR):",
192
+ format_list(pr.closing_issues, "(none)"),
193
+ "",
194
+ "Files (first 15):",
195
+ format_list(pr.files_changed[:15], "(none)"),
196
+ ]
197
+ )
198
+
199
+
200
+ def build_close_candidates_section(
201
+ *,
202
+ verified: list[str],
203
+ author_asserted: list[str],
204
+ referenced: list[str],
205
+ verified_reason: str,
206
+ author_reason: str,
207
+ ) -> str:
208
+ """Render close-candidate section grouped by verification source."""
209
+ all_auto_close = set(verified + author_asserted + referenced)
210
+ author_auto_close = sorted(all_auto_close)
211
+ referenced_only = sorted(set(referenced) - all_auto_close)
212
+
213
+ return "\n".join(
214
+ [
215
+ section("Close candidates"),
216
+ "Auto-close issues (verified from GitHub PR metadata):",
217
+ format_list(verified, verified_reason),
218
+ "",
219
+ "Auto-close issues (author asserted):",
220
+ format_list(author_auto_close, author_reason),
221
+ "",
222
+ "Referenced issues (detected):",
223
+ format_list(referenced_only, "(none)"),
224
+ ]
225
+ )
226
+
227
+
228
+ def build_issues_to_autoclose_section(
229
+ *,
230
+ verified: list[str],
231
+ pending_primary: list[str],
232
+ readiness_signals: list[str],
233
+ ) -> str:
234
+ """Render approved autoclose section from verified and deterministic pending refs.
235
+
236
+ Purpose:
237
+ Build the summary section consumed by PR-generation prompts for allowed
238
+ autoclose declarations.
239
+
240
+ Args:
241
+ verified: Issues verified from GitHub PR metadata (`closingIssuesReferences`).
242
+ pending_primary: Deterministic primary issue refs eligible when
243
+ readiness is PASS.
244
+ readiness_signals: Normalized readiness states observed in feature docs.
245
+
246
+ Returns:
247
+ A formatted section with header
248
+ `===== Issues to autoclose (verified or pending) =====` and either a
249
+ deterministic list or conservative fallback text.
250
+
251
+ Side Effects:
252
+ None.
253
+ """
254
+ # Preserve stable, deterministic ordering: verified issues first, then
255
+ # pending deterministic issues not already verified.
256
+ ordered: list[str] = []
257
+ for issue in verified + pending_primary:
258
+ if issue and issue not in ordered:
259
+ ordered.append(issue)
260
+
261
+ if ordered:
262
+ body = format_list(ordered, "(none)")
263
+ else:
264
+ # Use explicit conservative wording when readiness is missing/non-PASS.
265
+ if any(signal == "PASS" for signal in readiness_signals):
266
+ body = (
267
+ "None (no verified closing issues and no deterministic pending issue)"
268
+ )
269
+ else:
270
+ body = "None (no verified closing issues and readiness not PASS)"
271
+
272
+ return "\n".join([section("Issues to autoclose (verified or pending)"), body])
273
+
274
+
275
+ def extract_changed_paths(context_text: str) -> list[str]:
276
+ """Extract changed file paths from the 'Changed files' section text."""
277
+ paths: list[str] = []
278
+ capture = False
279
+ for line in context_text.splitlines():
280
+ if line.startswith("===== Changed files"):
281
+ capture = True
282
+ continue
283
+ if capture:
284
+ if line.startswith("====="):
285
+ break
286
+ if line.strip() and "\t" in line:
287
+ path_part = line.split("\t")[-1]
288
+ paths.append(format_diff_path(path_part.strip()))
289
+ elif line.strip():
290
+ paths.append(format_diff_path(line.strip()))
291
+ return paths