@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,349 @@
1
+ from __future__ import annotations
2
+
3
+ import re
4
+ from pathlib import Path
5
+ from typing import TYPE_CHECKING
6
+
7
+ from .models import FeatureDocExcerpt, section, truncate
8
+ from .verification_evidence import discover_canonical_evidence_files
9
+
10
+ if TYPE_CHECKING:
11
+ from collections.abc import Iterable
12
+
13
+
14
+ def parse_section(markdown: str, heading: str) -> str:
15
+ escaped = re.escape(heading)
16
+ pattern = rf"^##\s+{escaped}\s*\r?\n(.*?)(?=^##\s+|\Z)"
17
+ match = re.search(pattern, markdown, flags=re.MULTILINE | re.DOTALL)
18
+ if not match:
19
+ return ""
20
+ return match.group(1).strip()
21
+
22
+
23
+ def completed_plan_tasks(markdown: str, *, limit: int = 10) -> list[str]:
24
+ tasks: list[str] = []
25
+ for line in markdown.splitlines():
26
+ if re.search(r"\[x\]", line, flags=re.IGNORECASE):
27
+ cleaned = re.sub(r"^[-*]\s*\[[xX]\]\s*", "", line).strip()
28
+ tasks.append(cleaned)
29
+ if len(tasks) >= limit:
30
+ break
31
+ return tasks
32
+
33
+
34
+ def extract_issue_references(text: str) -> list[str]:
35
+ if not text:
36
+ return []
37
+ matches = re.findall(r"(?<!\w)#\d+|\b[A-Z][A-Z0-9]+-\d+\b", text)
38
+ seen: set[str] = set()
39
+ ordered: list[str] = []
40
+ for item in matches:
41
+ if item not in seen:
42
+ seen.add(item)
43
+ ordered.append(item)
44
+ return ordered
45
+
46
+
47
+ def _resolve_feature_dir(base_dir: Path, feature: str) -> Path | None:
48
+ direct = base_dir / feature
49
+ if direct.exists():
50
+ return direct
51
+
52
+ pattern = re.compile(rf"(?:^|[-_]){re.escape(feature)}(?:[-_]|$)")
53
+ strong_matches: list[Path] = []
54
+ weak_matches: list[Path] = []
55
+
56
+ for candidate in sorted(base_dir.iterdir()):
57
+ if not candidate.is_dir():
58
+ continue
59
+ name = candidate.name
60
+ if pattern.search(name):
61
+ strong_matches.append(candidate)
62
+ elif feature in name:
63
+ weak_matches.append(candidate)
64
+
65
+ if strong_matches:
66
+ return strong_matches[0]
67
+ if weak_matches:
68
+ return weak_matches[0]
69
+ return None
70
+
71
+
72
+ def _read_text(path: Path) -> str:
73
+ return path.read_text(encoding="utf-8") if path.exists() else ""
74
+
75
+
76
+ def _latest_glob_path(directory: Path, pattern: str) -> Path | None:
77
+ """Return the lexicographically latest matching file path.
78
+
79
+ Purpose:
80
+ Feature folders commonly use timestamped filenames (for example
81
+ `plan.<timestamp>.md`). Lexicographic ordering over the timestamp suffix
82
+ yields deterministic "latest" selection.
83
+
84
+ Args:
85
+ directory (Path): Directory to search.
86
+ pattern (str): Glob pattern to match.
87
+
88
+ Returns:
89
+ Path | None: Latest matching path, or None if no matches.
90
+
91
+ Side Effects:
92
+ Reads directory entries.
93
+ """
94
+ matches = sorted(directory.glob(pattern))
95
+ return matches[-1] if matches else None
96
+
97
+
98
+ def _verification_text(plan_text: str) -> str:
99
+ for heading in ("Verification", "Test Plan"):
100
+ section_text = parse_section(plan_text, heading)
101
+ if section_text:
102
+ return section_text
103
+ return ""
104
+
105
+
106
+ def _parse_primary_issue_from_metadata(
107
+ *, spec_text: str, story_text: str, issue_text: str
108
+ ) -> str | None:
109
+ """Parse deterministic primary issue from metadata lines only.
110
+
111
+ Args:
112
+ spec_text: Full `spec.md` text for the feature.
113
+ story_text: Full `user-story.md` text for the feature.
114
+ issue_text: Full `issue.md` text for the feature (minor-audit source).
115
+
116
+ Returns:
117
+ A normalized issue reference (for example `#46`) when an explicit
118
+ metadata line `Issue: #NN` is found; otherwise `None`.
119
+
120
+ Side Effects:
121
+ None.
122
+ """
123
+ # Search metadata-style lines only so narrative mentions never become the
124
+ # deterministic primary issue source.
125
+ pattern = re.compile(r"^\s*[-*]?\s*Issue:\s*(#\d+)\s*$", re.IGNORECASE)
126
+
127
+ # Prefer spec metadata first, then story, then issue.md.
128
+ for source_text in (spec_text, story_text, issue_text):
129
+ for line in source_text.splitlines():
130
+ match = pattern.match(line)
131
+ if match:
132
+ return match.group(1)
133
+ return None
134
+
135
+
136
+ def _parse_readiness_value(text: str) -> str | None:
137
+ """Normalize readiness value from a feature-audit markdown payload.
138
+
139
+ Args:
140
+ text: Raw markdown content from a `feature-audit.*.md` file.
141
+
142
+ Returns:
143
+ One of `PASS`, `NEEDS REVISION`, `BLOCKED`, or `None`.
144
+
145
+ Side Effects:
146
+ None.
147
+ """
148
+ # Normalize away Markdown emphasis so template-driven lines like
149
+ # `**Overall feature readiness:** **PASS**` are parseable using a single
150
+ # canonical regex.
151
+ normalized = text.replace("**", "")
152
+ match = re.search(
153
+ r"^\s*(?:Readiness|Overall feature readiness):\s*(.+?)\s*$",
154
+ normalized,
155
+ flags=re.MULTILINE | re.IGNORECASE,
156
+ )
157
+ if not match:
158
+ return None
159
+ value = match.group(1).strip().upper()
160
+ if value in {"PASS", "NEEDS REVISION", "BLOCKED"}:
161
+ return value
162
+ return None
163
+
164
+
165
+ def _resolve_readiness_signal(feature_dir: Path) -> tuple[str | None, Path | None]:
166
+ """Resolve readiness signal from the newest readable `feature-audit.*.md`.
167
+
168
+ Args:
169
+ feature_dir: Active feature directory containing audit artifacts.
170
+
171
+ Returns:
172
+ tuple[str | None, Path | None]:
173
+ - Readiness (`PASS`, `NEEDS REVISION`, `BLOCKED`) or `None`.
174
+ - The audit file path that produced the readiness value, or `None`.
175
+
176
+ Side Effects:
177
+ Reads local feature audit files from disk.
178
+ """
179
+ audit_files = sorted(feature_dir.glob("feature-audit.*.md"))
180
+ # Evaluate newest-first based on lexicographic timestamp suffix.
181
+ # Intent: We prefer the newest audit that contains a parseable readiness
182
+ # marker, which allows older audits to coexist without overriding newer
183
+ # PASS/REVISION/BLOCKED states.
184
+ for audit_path in reversed(audit_files):
185
+ readiness = _parse_readiness_value(_read_text(audit_path))
186
+ if readiness:
187
+ return readiness, audit_path
188
+ return None, None
189
+
190
+
191
+ def gather_feature_excerpts(
192
+ root: Path, changed_files: Iterable[str]
193
+ ) -> list[FeatureDocExcerpt]:
194
+ features: set[str] = set()
195
+ for raw in changed_files:
196
+ parts = Path(raw).parts
197
+ if (
198
+ len(parts) >= 4
199
+ and parts[0] == "docs"
200
+ and parts[1] == "features"
201
+ and parts[2] == "active"
202
+ ):
203
+ features.add(parts[3])
204
+
205
+ excerpts: list[FeatureDocExcerpt] = []
206
+ base_dir = root / "docs" / "features" / "active"
207
+ promoted_dir = root / "docs" / "features" / "potential" / "promoted"
208
+ for feature in sorted(features):
209
+ feature_dir: Path | None = _resolve_feature_dir(base_dir, feature)
210
+ promoted_feature_dir: Path | None = _resolve_feature_dir(promoted_dir, feature)
211
+ if feature_dir is None and promoted_feature_dir is None:
212
+ continue
213
+
214
+ active_dir = feature_dir or promoted_feature_dir
215
+ if active_dir is None:
216
+ continue
217
+
218
+ spec_path = active_dir / "spec.md"
219
+ issue_path = active_dir / "issue.md"
220
+
221
+ # Resolve plan path:
222
+ # - Prefer `plan.md` for legacy features.
223
+ # - Fall back to newest `plan.<timestamp>.md` for minor-audit flows.
224
+ plan_path = active_dir / "plan.md"
225
+ if not plan_path.exists():
226
+ latest_plan = _latest_glob_path(active_dir, "plan.*.md")
227
+ if latest_plan is not None:
228
+ plan_path = latest_plan
229
+ user_story_path: Path = active_dir / "user-story.md"
230
+ promoted_story_path = (
231
+ promoted_feature_dir / "user-story.md"
232
+ if promoted_feature_dir is not None
233
+ else None
234
+ )
235
+
236
+ promoted_story_text = (
237
+ _read_text(promoted_story_path) if promoted_story_path else ""
238
+ )
239
+ if promoted_story_path is not None and not user_story_path.exists():
240
+ user_story_path = promoted_story_path
241
+
242
+ user_story_text = _read_text(user_story_path)
243
+ if (
244
+ not user_story_text
245
+ and promoted_story_text
246
+ and promoted_story_path is not None
247
+ ):
248
+ user_story_text = promoted_story_text
249
+ user_story_path = promoted_story_path
250
+
251
+ spec_text = _read_text(spec_path)
252
+ issue_text = _read_text(issue_path)
253
+ plan_text = _read_text(plan_path)
254
+ primary_issue_ref = _parse_primary_issue_from_metadata(
255
+ spec_text=spec_text,
256
+ story_text=user_story_text,
257
+ issue_text=issue_text,
258
+ )
259
+ readiness_signal, readiness_source = _resolve_readiness_signal(active_dir)
260
+
261
+ spec_parts: list[str] = []
262
+ for heading in (
263
+ "Context",
264
+ "Root Cause",
265
+ "Root Cause/Problem",
266
+ "Problem",
267
+ "Proposed Fix",
268
+ "Acceptance Criteria",
269
+ "Constraints & Risks",
270
+ "Behavior",
271
+ "Overview",
272
+ ):
273
+ section_text = parse_section(spec_text, heading)
274
+ if section_text:
275
+ spec_parts.append(f"{heading}: {truncate(section_text)}")
276
+
277
+ plan_tasks = completed_plan_tasks(plan_text)
278
+ plan_section = (
279
+ "\n".join(f"- {task}" for task in plan_tasks) if plan_tasks else ""
280
+ )
281
+ verification_text = _verification_text(plan_text)
282
+ verification_block = (
283
+ "Plan verification notes:\n" + truncate(verification_text)
284
+ if verification_text
285
+ else ""
286
+ )
287
+
288
+ story_parts: list[str] = []
289
+ story_statements = parse_section(user_story_text, "Story Statement")
290
+ if story_statements:
291
+ story_lines = [
292
+ line.strip("- ")
293
+ for line in story_statements.splitlines()
294
+ if line.strip()
295
+ ]
296
+ if story_lines:
297
+ story_parts.append(
298
+ "Story Statement:\n"
299
+ + "\n".join(f"- {line}" for line in story_lines)
300
+ )
301
+ problem_section = parse_section(user_story_text, "Problem / Why")
302
+ if problem_section:
303
+ story_parts.append("Problem / Why:\n" + truncate(problem_section))
304
+ if not story_parts and promoted_story_text:
305
+ promoted_problem = parse_section(promoted_story_text, "Problem / Why")
306
+ if not promoted_problem:
307
+ promoted_problem = parse_section(promoted_story_text, "Summary")
308
+ if promoted_problem:
309
+ story_parts.append("Problem / Why:\n" + truncate(promoted_problem))
310
+
311
+ lines: list[str] = [section(f"Feature doc: {feature}")]
312
+ if story_parts:
313
+ lines.append("User story excerpts:\n" + "\n\n".join(story_parts))
314
+ if spec_parts:
315
+ lines.append("Spec excerpts:\n" + "\n\n".join(spec_parts))
316
+ if plan_section:
317
+ lines.append("Plan completed tasks:\n" + plan_section)
318
+ if verification_block:
319
+ lines.append(verification_block)
320
+ if len(lines) == 1:
321
+ lines.append("(no spec/plan/user-story excerpts found)")
322
+
323
+ context_files = [
324
+ path.relative_to(root).as_posix()
325
+ for path in (spec_path, issue_path, plan_path, user_story_path)
326
+ if path.exists()
327
+ ]
328
+ if readiness_source is not None:
329
+ context_files.append(readiness_source.relative_to(root).as_posix())
330
+ # Include canonical evidence files so downstream PR authoring can cite
331
+ # only enumerated sources while preserving deterministic ordering.
332
+ evidence_context_files = [
333
+ path.as_posix() for path in discover_canonical_evidence_files(root, feature)
334
+ ]
335
+ issue_refs = extract_issue_references(
336
+ "\n".join([spec_text, issue_text, plan_text, user_story_text])
337
+ )
338
+ excerpts.append(
339
+ FeatureDocExcerpt(
340
+ feature=feature,
341
+ excerpt="\n".join(lines),
342
+ issue_refs=issue_refs,
343
+ context_files=sorted(set(context_files + evidence_context_files)),
344
+ primary_issue_ref=primary_issue_ref,
345
+ readiness_signal=readiness_signal,
346
+ )
347
+ )
348
+
349
+ return excerpts
@@ -0,0 +1,153 @@
1
+ """Git helpers for PR context collection."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import subprocess
6
+ from pathlib import Path
7
+ from typing import TYPE_CHECKING, Protocol
8
+
9
+ from .models import CommandResult
10
+
11
+ if TYPE_CHECKING:
12
+ from collections.abc import Sequence
13
+
14
+
15
+ class CommandRunner(Protocol):
16
+ """Runs shell commands and returns structured results."""
17
+
18
+ def run(
19
+ self,
20
+ args: Sequence[str],
21
+ *,
22
+ cwd: Path | None = None,
23
+ allow_error: bool = False,
24
+ ) -> CommandResult: ...
25
+
26
+
27
+ class SubprocessRunner(CommandRunner):
28
+ """Command runner that shells out using subprocess.run."""
29
+
30
+ def run(
31
+ self,
32
+ args: Sequence[str],
33
+ *,
34
+ cwd: Path | None = None,
35
+ allow_error: bool = False,
36
+ ) -> CommandResult:
37
+ """
38
+ Execute a command using subprocess and capture its output.
39
+
40
+ Purpose:
41
+ Run the provided arguments while capturing stdout, stderr, and the exit
42
+ code for downstream processing.
43
+
44
+ Args:
45
+ args (Sequence[str]): Command and arguments to execute.
46
+ cwd (Path | None): Optional working directory for the subprocess.
47
+ allow_error (bool): When False, raise on non-zero exit codes; otherwise
48
+ return the captured result regardless of status.
49
+
50
+ Returns:
51
+ CommandResult: Captured stdout, stderr, and exit code.
52
+
53
+ Raises:
54
+ RuntimeError: If the subprocess exits non-zero and allow_error is False.
55
+
56
+ Side Effects:
57
+ Spawns a subprocess decoded as UTF-8 with replacement for undecodable
58
+ bytes to avoid Windows code-page failures.
59
+ """
60
+ # We only invoke git with argument lists we construct, not user-supplied
61
+ # input.
62
+ completed = subprocess.run( # noqa: S603
63
+ args,
64
+ cwd=str(cwd) if cwd else None,
65
+ capture_output=True,
66
+ text=True,
67
+ encoding="utf-8",
68
+ errors="replace",
69
+ check=False,
70
+ shell=False,
71
+ )
72
+
73
+ stdout = (completed.stdout or "").rstrip("\n")
74
+ stderr = (completed.stderr or "").rstrip("\n")
75
+ result = CommandResult(
76
+ stdout=stdout, stderr=stderr, code=int(completed.returncode)
77
+ )
78
+
79
+ if not allow_error and result.code != 0:
80
+ joined = (stdout + "\n" + stderr).strip()
81
+ raise RuntimeError(f"{' '.join(args)} failed ({result.code}): {joined}")
82
+
83
+ return result
84
+
85
+
86
+ class GitClient:
87
+ """Thin wrapper around git for typed access."""
88
+
89
+ def __init__(self, runner: CommandRunner, cwd: Path) -> None:
90
+ self._runner = runner
91
+ self._cwd = cwd
92
+
93
+ @property
94
+ def cwd(self) -> Path:
95
+ """Current working directory for git operations."""
96
+ return self._cwd
97
+
98
+ def run(self, args: Sequence[str], *, allow_error: bool = False) -> CommandResult:
99
+ return self._runner.run(["git", *args], cwd=self._cwd, allow_error=allow_error)
100
+
101
+ def resolve_root(self) -> Path:
102
+ candidate = self._cwd / ".git"
103
+ if candidate.exists():
104
+ return self._cwd
105
+
106
+ top = self.run(["rev-parse", "--show-toplevel"]).stdout
107
+ # Preserve git's reported root without forcing OS-specific drive resolution
108
+ return Path(top)
109
+
110
+ def rev_parse(self, ref: str) -> str:
111
+ return self.run(["rev-parse", "--verify", ref]).stdout
112
+
113
+ def remote_verbose(self) -> str:
114
+ return self.run(["remote", "-v"]).stdout
115
+
116
+ def branch_name(self) -> str:
117
+ return self.run(["rev-parse", "--abbrev-ref", "HEAD"]).stdout
118
+
119
+ def upstream(self) -> str:
120
+ res = self.run(
121
+ ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"],
122
+ allow_error=True,
123
+ )
124
+ return res.stdout
125
+
126
+ def status_short(self) -> str:
127
+ return self.run(["status", "-sb"]).stdout
128
+
129
+ def untracked(self) -> str:
130
+ return self.run(["ls-files", "--others", "--exclude-standard"]).stdout
131
+
132
+ def diff_name_status(self, *, staged: bool) -> str:
133
+ args = ["diff", "--name-status"]
134
+ if staged:
135
+ args.insert(1, "--cached")
136
+ return self.run(args, allow_error=True).stdout
137
+
138
+ def diff_patch(self, *, staged: bool) -> str:
139
+ args = ["diff"]
140
+ if staged:
141
+ args.append("--cached")
142
+ return self.run(args, allow_error=True).stdout
143
+
144
+ def merge_base(self, base: str, head: str) -> str:
145
+ return self.run(["merge-base", base, head]).stdout
146
+
147
+ def log(self, fmt: str, rev_range: str) -> str:
148
+ return self.run(
149
+ ["log", "--date=short", fmt, rev_range], allow_error=True
150
+ ).stdout
151
+
152
+ def diff_range(self, args: Sequence[str]) -> str:
153
+ return self.run(["diff", *args], allow_error=True).stdout