@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,386 @@
1
+ """Helper routines for PR context rendering and summarization."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from datetime import datetime, timezone
7
+ from typing import TYPE_CHECKING
8
+
9
+ from .models import (
10
+ IssueDetails,
11
+ PullRequestDetails,
12
+ format_list,
13
+ section,
14
+ truncate_lines,
15
+ )
16
+
17
+ if TYPE_CHECKING:
18
+ from pathlib import Path
19
+
20
+ from .git import GitClient
21
+
22
+ __all__ = [
23
+ "append_generation_timestamp",
24
+ "bucket_text",
25
+ "extract_digest_bullets",
26
+ "is_scoping_doc",
27
+ "issue_appendix",
28
+ "issue_digest",
29
+ "last_with_truncation",
30
+ "parse_name_status_map",
31
+ "parse_numstat_detailed",
32
+ "parse_section",
33
+ "pr_appendix",
34
+ "pr_digest",
35
+ "scoping_doc_changes",
36
+ ]
37
+
38
+
39
+ def last_with_truncation(items: list[str], limit: int) -> tuple[list[str], bool]:
40
+ if len(items) <= limit:
41
+ return items, False
42
+ return items[-limit:], True
43
+
44
+
45
+ def extract_digest_bullets(body: str, *, headings: list[str], limit: int) -> list[str]:
46
+ bullets: list[str] = []
47
+ for heading in headings:
48
+ section_text = parse_section(body, heading)
49
+ if not section_text:
50
+ continue
51
+ for line in section_text.splitlines():
52
+ if not line.strip():
53
+ continue
54
+ cleaned = line.lstrip("-*").strip()
55
+ bullets.append(f"{heading}: {cleaned}")
56
+ if len(bullets) >= limit:
57
+ return bullets
58
+ return bullets[:limit]
59
+
60
+
61
+ def issue_digest(issue: IssueDetails) -> str:
62
+ bullets = extract_digest_bullets(
63
+ issue.body,
64
+ headings=[
65
+ "Why",
66
+ "Context",
67
+ "Root Cause",
68
+ "Constraints",
69
+ "Acceptance Criteria",
70
+ "Test Strategy",
71
+ "Risks",
72
+ "Verification",
73
+ "Follow-ups",
74
+ ],
75
+ limit=8,
76
+ )
77
+ if not bullets:
78
+ bullets.append(f"State: {issue.state}")
79
+ if issue.labels:
80
+ bullets.append(f"Labels: {', '.join(issue.labels)}")
81
+
82
+ selected_comments, truncated = last_with_truncation(issue.comments, 3)
83
+ comment_block = (
84
+ "\n".join(f"- {comment}" for comment in selected_comments)
85
+ if selected_comments
86
+ else "(no comments)"
87
+ )
88
+ if truncated:
89
+ comment_block += "\nTRUNCATED: last 3 comments shown"
90
+
91
+ metadata = [
92
+ f"Identifier: {issue.number}",
93
+ f"Title: {issue.title}",
94
+ f"Author: {issue.author}",
95
+ f"Assignees: {', '.join(issue.assignees) if issue.assignees else '(none)'}",
96
+ f"Labels: {', '.join(issue.labels) if issue.labels else '(none)'}",
97
+ f"State: {issue.state}",
98
+ f"Last updated: {issue.updated_at}",
99
+ ]
100
+ return "\n".join(
101
+ [
102
+ "\n".join(metadata),
103
+ "Key bullets:",
104
+ "\n".join(f"- {entry}" for entry in bullets),
105
+ "",
106
+ "Recent comments:",
107
+ comment_block,
108
+ ]
109
+ )
110
+
111
+
112
+ def pr_digest(pr: PullRequestDetails) -> str:
113
+ bullets = extract_digest_bullets(
114
+ pr.body,
115
+ headings=[
116
+ "Why",
117
+ "Context",
118
+ "Root Cause",
119
+ "Constraints",
120
+ "Acceptance Criteria",
121
+ "Test Strategy",
122
+ "Risks",
123
+ "Verification",
124
+ "Follow-ups",
125
+ ],
126
+ limit=8,
127
+ )
128
+ if not bullets:
129
+ if pr.files_changed:
130
+ bullets.append(
131
+ f"Touches files: {', '.join(pr.files_changed[:3])}"
132
+ + (" ..." if len(pr.files_changed) > 3 else "")
133
+ )
134
+ bullets.append(f"State: {pr.state}")
135
+
136
+ metadata = [
137
+ f"Identifier: {pr.number}",
138
+ f"Title: {pr.title}",
139
+ f"Author: {pr.author}",
140
+ f"Base/Head: {pr.base_ref} <- {pr.head_ref}",
141
+ f"Last updated: {pr.updated_at}",
142
+ ]
143
+ return "\n".join(
144
+ [
145
+ "\n".join(metadata),
146
+ "Key bullets:",
147
+ "\n".join(f"- {entry}" for entry in bullets),
148
+ ]
149
+ )
150
+
151
+
152
+ def issue_appendix(issue: IssueDetails) -> str:
153
+ body_text = truncate_lines(issue.body, 120)
154
+ comments, truncated = last_with_truncation(issue.comments, 10)
155
+ comment_text = (
156
+ "\n".join(f"- {c}" for c in comments) if comments else "(no comments)"
157
+ )
158
+ if truncated:
159
+ comment_text += "\nTRUNCATED: last 10 comments shown"
160
+ user_story_block = ""
161
+ if issue.user_story_content:
162
+ user_story_block = "\n".join(
163
+ [
164
+ "",
165
+ f"User story ({issue.user_story_path or 'user-story.md'}):",
166
+ truncate_lines(issue.user_story_content, 120),
167
+ ]
168
+ )
169
+ return "\n".join(
170
+ [
171
+ section(f"Issue {issue.number}: {issue.title}"),
172
+ f"State: {issue.state}",
173
+ f"Labels: {', '.join(issue.labels) if issue.labels else '(none)'}",
174
+ f"Assignees: {', '.join(issue.assignees) if issue.assignees else '(none)'}",
175
+ f"Author: {issue.author}",
176
+ f"Created: {issue.created_at}",
177
+ f"Updated: {issue.updated_at}",
178
+ "",
179
+ body_text,
180
+ "",
181
+ "Comments:",
182
+ comment_text,
183
+ user_story_block,
184
+ ]
185
+ )
186
+
187
+
188
+ def pr_appendix(pr: PullRequestDetails) -> str:
189
+ body_text = truncate_lines(pr.body, 120)
190
+ return "\n".join(
191
+ [
192
+ section(f"Pull Request {pr.number}: {pr.title}"),
193
+ f"State: {pr.state}",
194
+ f"Author: {pr.author}",
195
+ f"Base: {pr.base_ref}",
196
+ f"Head: {pr.head_ref}",
197
+ f"Created: {pr.created_at}",
198
+ f"Updated: {pr.updated_at}",
199
+ f"Merged: {pr.merged_at or '(not merged)'}",
200
+ f"Labels: {', '.join(pr.labels) if pr.labels else '(none)'}",
201
+ f"Assignees: {', '.join(pr.assignees) if pr.assignees else '(none)'}",
202
+ "",
203
+ body_text,
204
+ "",
205
+ "Auto-close issues (from this PR):",
206
+ format_list(pr.closing_issues, "(none)"),
207
+ "",
208
+ "Files (first 25):",
209
+ format_list(pr.files_changed[:25], "(none)"),
210
+ ]
211
+ )
212
+
213
+
214
+ def parse_numstat_detailed(
215
+ numstat_text: str,
216
+ ) -> tuple[int, int, dict[str, tuple[int, int]]]:
217
+ adds_total = 0
218
+ dels_total = 0
219
+ per_file: dict[str, tuple[int, int]] = {}
220
+ for raw_line in numstat_text.splitlines():
221
+ if not raw_line.strip():
222
+ continue
223
+ parts = raw_line.split("\t")
224
+ if len(parts) < 3:
225
+ continue
226
+ add_part, del_part, file_part = parts[0], parts[1], parts[2]
227
+ add_count = int(add_part) if add_part.isdigit() else 0
228
+ del_count = int(del_part) if del_part.isdigit() else 0
229
+ adds_total += add_count
230
+ dels_total += del_count
231
+ per_file[format_diff_path(file_part)] = (add_count, del_count)
232
+ return adds_total, dels_total, per_file
233
+
234
+
235
+ def parse_name_status_map(name_status_text: str) -> dict[str, str]:
236
+ mapping: dict[str, str] = {}
237
+ for raw_line in name_status_text.splitlines():
238
+ if not raw_line.strip():
239
+ continue
240
+ parts = raw_line.split("\t")
241
+ if len(parts) < 2:
242
+ continue
243
+ status = parts[0].strip()
244
+ path = format_diff_path(parts[-1].strip())
245
+ mapping[path] = status
246
+ return mapping
247
+
248
+
249
+ def is_scoping_doc(path: str) -> bool:
250
+ lowered = path.lower()
251
+ return bool(
252
+ lowered.startswith("docs/features/")
253
+ and (
254
+ lowered.endswith("/spec.md")
255
+ or lowered.endswith("/plan.md")
256
+ or lowered.endswith("/bug-remediation-plan.md")
257
+ or lowered.endswith("/user-story.md")
258
+ or lowered.endswith("/readme.md")
259
+ )
260
+ )
261
+
262
+
263
+ def scoping_doc_changes(
264
+ *,
265
+ git: GitClient,
266
+ merge_base: str | None,
267
+ head_sha: str | None,
268
+ root: Path,
269
+ name_status_text: str,
270
+ numstat_details: dict[str, tuple[int, int]],
271
+ ) -> list[tuple[str, bool, list[str], str | None]]:
272
+ if not merge_base or not head_sha:
273
+ return []
274
+ changes: list[tuple[str, bool, list[str], str | None]] = []
275
+ name_status_map = parse_name_status_map(name_status_text)
276
+ for path, status in name_status_map.items():
277
+ if not is_scoping_doc(path):
278
+ continue
279
+ additions, deletions = numstat_details.get(path, (0, 0))
280
+ reasons: list[str] = []
281
+ material = False
282
+ if status.startswith("A"):
283
+ material = True
284
+ reasons.append("new scoping doc")
285
+ if additions + deletions >= 15:
286
+ material = True
287
+ reasons.append(">=15 lines changed")
288
+
289
+ diff_text = git.diff_range(["--unified=0", merge_base, head_sha, "--", path])
290
+ heading_touched = False
291
+ for line in diff_text.splitlines():
292
+ if not line.startswith("+") or line.startswith("+++"):
293
+ continue
294
+ stripped = line.lstrip("+").strip()
295
+ if any(
296
+ stripped.lower().startswith(prefix.lower())
297
+ for prefix in (
298
+ "## Context",
299
+ "## Root Cause",
300
+ "## Proposed Fix",
301
+ "## Acceptance Criteria",
302
+ "## Test Strategy",
303
+ "## Risks",
304
+ )
305
+ ):
306
+ heading_touched = True
307
+ break
308
+ if heading_touched:
309
+ material = True
310
+ reasons.append("key section touched")
311
+
312
+ added_lines = [
313
+ line.lstrip("+").strip()
314
+ for line in diff_text.splitlines()
315
+ if line.startswith("+") and not line.startswith("+++")
316
+ ]
317
+ if added_lines and all(
318
+ (not line or line.startswith("[") or line.startswith("http"))
319
+ for line in added_lines
320
+ ):
321
+ reasons.append("link/whitespace-only changes")
322
+ if (
323
+ not heading_touched
324
+ and additions + deletions < 15
325
+ and not status.startswith("A")
326
+ ):
327
+ material = False
328
+
329
+ excerpt = None
330
+ doc_path = root / path
331
+ if material and doc_path.exists():
332
+ content = doc_path.read_text(encoding="utf-8")
333
+ excerpt_parts: list[str] = []
334
+ for heading in (
335
+ "Acceptance Criteria",
336
+ "Root Cause",
337
+ "Proposed Fix",
338
+ "Test Strategy",
339
+ ):
340
+ section_text = parse_section(content, heading)
341
+ if section_text:
342
+ excerpt_parts.append(
343
+ f"{heading}:\n{truncate_lines(section_text, 40)}"
344
+ )
345
+ excerpt = "\n\n".join(excerpt_parts[:3]) if excerpt_parts else None
346
+
347
+ changes.append((path, material, reasons, excerpt))
348
+ return changes
349
+
350
+
351
+ def bucket_text(name: str, entries: list[tuple[str, tuple[int, int]]]) -> str:
352
+ if not entries:
353
+ return f"{name}: 0 files"
354
+ sorted_entries = sorted(
355
+ entries, key=lambda item: item[1][0] + item[1][1], reverse=True
356
+ )
357
+ lines = [
358
+ f"{name}: {len(entries)} files",
359
+ *(f"- {path} (+{adds}/-{dels})" for path, (adds, dels) in sorted_entries[:10]),
360
+ ]
361
+ return "\n".join(lines)
362
+
363
+
364
+ def parse_section(markdown: str, heading: str) -> str:
365
+ escaped = re.escape(heading)
366
+ pattern = rf"^##\s+{escaped}\s*\r?\n(.*?)(?=^##\s+|\Z)"
367
+ match = re.search(pattern, markdown, flags=re.MULTILINE | re.DOTALL)
368
+ if not match:
369
+ return ""
370
+ return match.group(1).strip()
371
+
372
+
373
+ def format_diff_path(path_text: str | None) -> str:
374
+ from .render import format_diff_path as _fmt
375
+
376
+ return _fmt(path_text) if path_text is not None else ""
377
+
378
+
379
+ def append_generation_timestamp() -> str:
380
+ """Generate a timestamp section showing when context was collected.
381
+
382
+ Returns:
383
+ Formatted timestamp section with UTC time
384
+ """
385
+ timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S %Z")
386
+ return section("Context generated") + "\n" + timestamp + "\n"
@@ -0,0 +1,171 @@
1
+ """Discover and parse canonical feature verification evidence artifacts.
2
+
3
+ Purpose:
4
+ Provide deterministic discovery and strict schema parsing for canonical
5
+ evidence markdown files so PR context generation can make traceable
6
+ verification claims.
7
+
8
+ Flow:
9
+ 1. Discover canonical evidence files under active feature folders.
10
+ 2. Parse required schema fields from each markdown file.
11
+ 3. Normalize pass/fail/unparseable status from EXIT_CODE.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from dataclasses import dataclass
17
+ from typing import TYPE_CHECKING, Literal
18
+
19
+ if TYPE_CHECKING:
20
+ from pathlib import Path
21
+
22
+ REQUIRED_FIELDS: tuple[str, str, str] = ("Timestamp", "Command", "EXIT_CODE")
23
+ CANONICAL_GLOBS: tuple[str, str, str] = (
24
+ "evidence/qa-gates/**/*.md",
25
+ "evidence/regression-testing/**/*.md",
26
+ "evidence/other/**/*.md",
27
+ )
28
+
29
+ NormalizedResult = Literal["pass", "fail", "unparseable"]
30
+
31
+
32
+ @dataclass(frozen=True)
33
+ class VerificationEvidenceRecord:
34
+ """Represent one parsed canonical evidence artifact.
35
+
36
+ Purpose:
37
+ Carry all fields needed to render verification rows and preserve source
38
+ traceability to a specific feature evidence file.
39
+
40
+ Attributes:
41
+ feature: Active feature folder identifier.
42
+ source_file: Repository-relative evidence file path.
43
+ timestamp: Parsed `Timestamp` field when present.
44
+ command: Parsed `Command` field when present.
45
+ exit_code: Parsed `EXIT_CODE` integer when parseable.
46
+ normalized_result: Deterministic status (`pass`, `fail`, `unparseable`).
47
+ """
48
+
49
+ feature: str
50
+ source_file: str
51
+ timestamp: str | None
52
+ command: str | None
53
+ exit_code: int | None
54
+ normalized_result: NormalizedResult
55
+
56
+
57
+ def discover_canonical_evidence_files(root: Path, feature: str) -> list[Path]:
58
+ """Discover canonical evidence files for one active feature.
59
+
60
+ Args:
61
+ root: Repository root path.
62
+ feature: Active feature directory name under `docs/features/active`.
63
+
64
+ Returns:
65
+ Sorted, deduplicated repository-relative paths for canonical evidence files.
66
+
67
+ Side Effects:
68
+ Reads filesystem metadata through globbing.
69
+ """
70
+ feature_root = root / "docs" / "features" / "active" / feature
71
+ if not feature_root.exists() or not feature_root.is_dir():
72
+ return []
73
+
74
+ discovered: set[Path] = set()
75
+ # Search canonical evidence roots in a fixed order, then sort for stability.
76
+ for pattern in CANONICAL_GLOBS:
77
+ for candidate in feature_root.glob(pattern):
78
+ if candidate.is_file():
79
+ discovered.add(candidate.relative_to(root))
80
+ return sorted(discovered)
81
+
82
+
83
+ def parse_verification_evidence_markdown(
84
+ *, feature: str, source_file: str, markdown: str
85
+ ) -> VerificationEvidenceRecord:
86
+ """Parse required schema fields and normalize verification status.
87
+
88
+ Args:
89
+ feature: Active feature identifier owning the evidence file.
90
+ source_file: Repository-relative evidence file path.
91
+ markdown: Raw markdown content to parse.
92
+
93
+ Returns:
94
+ A normalized evidence record with `pass`, `fail`, or `unparseable` result.
95
+
96
+ Side Effects:
97
+ None.
98
+ """
99
+ parsed: dict[str, str] = {}
100
+
101
+ # Parse `Key: value` rows once and keep only required schema fields.
102
+ for raw_line in markdown.splitlines():
103
+ if ":" not in raw_line:
104
+ continue
105
+ key, value = raw_line.split(":", 1)
106
+ key = key.strip()
107
+ if key in REQUIRED_FIELDS:
108
+ parsed[key] = value.strip()
109
+
110
+ timestamp = parsed.get("Timestamp")
111
+ command = parsed.get("Command")
112
+ exit_code_raw = parsed.get("EXIT_CODE")
113
+
114
+ if not timestamp or not command or exit_code_raw is None:
115
+ return VerificationEvidenceRecord(
116
+ feature=feature,
117
+ source_file=source_file,
118
+ timestamp=timestamp,
119
+ command=command,
120
+ exit_code=None,
121
+ normalized_result="unparseable",
122
+ )
123
+
124
+ try:
125
+ exit_code = int(exit_code_raw)
126
+ except ValueError:
127
+ return VerificationEvidenceRecord(
128
+ feature=feature,
129
+ source_file=source_file,
130
+ timestamp=timestamp,
131
+ command=command,
132
+ exit_code=None,
133
+ normalized_result="unparseable",
134
+ )
135
+
136
+ normalized_result: NormalizedResult = "pass" if exit_code == 0 else "fail"
137
+ return VerificationEvidenceRecord(
138
+ feature=feature,
139
+ source_file=source_file,
140
+ timestamp=timestamp,
141
+ command=command,
142
+ exit_code=exit_code,
143
+ normalized_result=normalized_result,
144
+ )
145
+
146
+
147
+ def parse_verification_evidence_file(
148
+ *, root: Path, feature: str, relative_path: Path
149
+ ) -> VerificationEvidenceRecord:
150
+ """Read and parse one canonical evidence file.
151
+
152
+ Args:
153
+ root: Repository root path.
154
+ feature: Active feature identifier.
155
+ relative_path: Repository-relative evidence file path.
156
+
157
+ Returns:
158
+ Parsed normalized evidence record.
159
+
160
+ Raises:
161
+ OSError: Propagated when the evidence file cannot be read.
162
+
163
+ Side Effects:
164
+ Reads evidence file content from disk.
165
+ """
166
+ markdown = (root / relative_path).read_text(encoding="utf-8")
167
+ return parse_verification_evidence_markdown(
168
+ feature=feature,
169
+ source_file=relative_path.as_posix(),
170
+ markdown=markdown,
171
+ )
@@ -0,0 +1,152 @@
1
+ """Shared issue.md work-mode contract helpers for prompt resolvers.
2
+
3
+ Purpose:
4
+ Centralize parsing and fail-closed work-mode resolution so all prompt
5
+ resolvers use one deterministic contract:
6
+ 1) Parse persisted issue marker when valid.
7
+ 2) Normalize legacy `full` markers to a canonical full-mode variant.
8
+ 3) Fall back to `full-feature` when marker is missing or malformed.
9
+ 4) Surface an auditable fallback or normalization reason string.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import re
15
+
16
+ CANONICAL_WORK_MODES = ("minor-audit", "full-feature", "full-bug")
17
+ LEGACY_FULL_MODE = "full"
18
+ ACCEPTED_WORK_MODES = (*CANONICAL_WORK_MODES, LEGACY_FULL_MODE)
19
+
20
+
21
+ def normalize_requested_work_mode(requested_mode: str, promotion_type: str) -> str:
22
+ """Normalize a requested work mode into a canonical persisted value.
23
+
24
+ Purpose:
25
+ Convert user-facing or legacy CLI values into canonical persisted
26
+ markers. Plain `full` remains accepted for backward compatibility but is
27
+ normalized to the deterministic variant that matches the promotion
28
+ target.
29
+
30
+ Args:
31
+ requested_mode (str): Requested work mode from CLI or caller.
32
+ promotion_type (str): Promotion or feature type (`feature`, `bug`, etc.).
33
+
34
+ Returns:
35
+ str: Canonical work mode (`minor-audit`, `full-feature`, or `full-bug`).
36
+
37
+ Raises:
38
+ ValueError: If the request is invalid or incompatible with the type.
39
+ """
40
+ if requested_mode not in ACCEPTED_WORK_MODES:
41
+ raise ValueError(
42
+ "work_mode must be one of: minor-audit, full-feature, full-bug, full"
43
+ )
44
+
45
+ if requested_mode == "minor-audit":
46
+ return requested_mode
47
+
48
+ is_bug = promotion_type == "bug"
49
+ if requested_mode == LEGACY_FULL_MODE:
50
+ return "full-bug" if is_bug else "full-feature"
51
+
52
+ if requested_mode == "full-bug" and not is_bug:
53
+ raise ValueError("full-bug may only be used with bug work")
54
+
55
+ if requested_mode == "full-feature" and is_bug:
56
+ raise ValueError("full-feature may not be used with bug work")
57
+
58
+ return requested_mode
59
+
60
+
61
+ def parse_issue_work_mode(issue_content: str) -> tuple[str | None, bool]:
62
+ """Parse the work-mode marker from issue.md content.
63
+
64
+ Purpose:
65
+ Extract a valid `- Work Mode:` marker value from issue content while
66
+ distinguishing malformed marker lines from truly missing markers.
67
+
68
+ Args:
69
+ issue_content (str): Raw `issue.md` file content.
70
+
71
+ Returns:
72
+ tuple[str | None, bool]:
73
+ - Parsed mode (`minor-audit`, `full-feature`, `full-bug`, or legacy
74
+ `full`) when valid; otherwise None.
75
+ - Boolean indicating whether a malformed marker line was detected.
76
+
77
+ Side Effects:
78
+ None.
79
+ """
80
+ valid_match = re.search(
81
+ r"(?im)^-\s*Work Mode:\s*(minor-audit|full-feature|full-bug|full)\s*$",
82
+ issue_content,
83
+ )
84
+ if valid_match is not None:
85
+ return valid_match.group(1), False
86
+
87
+ malformed_match = re.search(r"(?im)^-\s*Work Mode:\s*(.+)\s*$", issue_content)
88
+ return None, malformed_match is not None
89
+
90
+
91
+ def resolve_selected_work_mode(issue_content: str | None) -> str:
92
+ """Resolve selected work mode with fail-closed behavior.
93
+
94
+ Purpose:
95
+ Provide a deterministic selected mode for templates by honoring a valid
96
+ marker when present, normalize legacy `full` to `full-feature`, and fail
97
+ closed to `full-feature` for all other states.
98
+
99
+ Args:
100
+ issue_content (str | None): Raw issue content, or None when the file is
101
+ unavailable.
102
+
103
+ Returns:
104
+ str: `minor-audit`, `full-feature`, or `full-bug`.
105
+
106
+ Side Effects:
107
+ None.
108
+ """
109
+ if issue_content is None:
110
+ return "full-feature"
111
+
112
+ parsed_mode, _has_malformed_marker = parse_issue_work_mode(issue_content)
113
+ if parsed_mode is not None:
114
+ if parsed_mode == LEGACY_FULL_MODE:
115
+ return "full-feature"
116
+ return parsed_mode
117
+
118
+ return "full-feature"
119
+
120
+
121
+ def build_fallback_reason(issue_content: str | None) -> str:
122
+ """Build a deterministic fallback reason for mode resolution.
123
+
124
+ Purpose:
125
+ Produce a stable reason string suitable for prompt substitution and
126
+ audit evidence, aligned with fail-closed mode semantics.
127
+
128
+ Args:
129
+ issue_content (str | None): Raw issue content, or None when missing or
130
+ unreadable.
131
+
132
+ Returns:
133
+ str: `none` when no fallback was needed, otherwise an explicit reason.
134
+
135
+ Side Effects:
136
+ None.
137
+ """
138
+ if issue_content is None:
139
+ return "issue.md missing; fail closed to full-feature"
140
+
141
+ parsed_mode, has_malformed_marker = parse_issue_work_mode(issue_content)
142
+ if parsed_mode is not None:
143
+ if parsed_mode == LEGACY_FULL_MODE:
144
+ return (
145
+ "issue.md Work Mode marker uses legacy full; normalized to full-feature"
146
+ )
147
+ return "none"
148
+
149
+ if has_malformed_marker:
150
+ return "issue.md Work Mode marker malformed; fail closed to full-feature"
151
+
152
+ return "issue.md Work Mode marker missing; fail closed to full-feature"