@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,421 @@
1
+ """Promote a potential feature file to a GitHub issue using the gh CLI."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import os
7
+ import shutil
8
+ import subprocess
9
+ from dataclasses import dataclass
10
+ from pathlib import Path
11
+ from typing import TYPE_CHECKING, Protocol
12
+
13
+ from dev_tools.potential_to_issue_content import (
14
+ BUG_SECTION_HEADINGS,
15
+ PLACEHOLDER,
16
+ build_body,
17
+ build_bug_body,
18
+ build_minor_audit_body,
19
+ extract_last_updated,
20
+ get_feature_name,
21
+ get_feature_path,
22
+ get_section,
23
+ normalize_smart_punctuation,
24
+ parse_issue_reference,
25
+ update_metadata_lines,
26
+ )
27
+ from dev_tools.prompt_mode_contract import (
28
+ ACCEPTED_WORK_MODES,
29
+ normalize_requested_work_mode,
30
+ )
31
+
32
+ if TYPE_CHECKING:
33
+ from collections.abc import Callable, Iterable
34
+
35
+ PROMOTION_TYPES = ("epic", "feature", "refactor", "bug")
36
+ WORK_MODES = ACCEPTED_WORK_MODES
37
+ TITLE_PREFIXES = {
38
+ "epic": "Epic",
39
+ "feature": "Feature",
40
+ "refactor": "Refactor",
41
+ "bug": "Bug",
42
+ }
43
+ FEATURE_LABEL_COLOR = "0e8a16"
44
+ FEATURE_LABEL_DESCRIPTION = "Feature work"
45
+
46
+
47
+ class PromotionError(Exception):
48
+ """Raised when a promotion precondition fails."""
49
+
50
+
51
+ @dataclass
52
+ class GhResult:
53
+ output: list[str]
54
+ exit_code: int
55
+
56
+
57
+ class GhClient(Protocol):
58
+ def is_authenticated(self) -> bool: ...
59
+
60
+ def issue_create(self, title: str, body: str, promotion_type: str) -> GhResult: ...
61
+
62
+ def ensure_label(self, label: str) -> GhResult: ...
63
+
64
+ def issue_view(self, issue_number: str) -> GhResult: ...
65
+
66
+
67
+ @dataclass
68
+ class RealGhClient(GhClient):
69
+ gh_path: str | None = None
70
+
71
+ def __post_init__(self) -> None:
72
+ if self.gh_path is None:
73
+ self.gh_path = shutil.which("gh")
74
+ if not self.gh_path:
75
+ raise FileNotFoundError(
76
+ "gh CLI not found on PATH. Install gh and authenticate first."
77
+ )
78
+
79
+ def is_authenticated(self) -> bool:
80
+ gh_exe = self.gh_path
81
+ if gh_exe is None:
82
+ return False
83
+
84
+ result = subprocess.run( # noqa: S603 - static analysis can't verify runtime validation
85
+ [gh_exe, "auth", "status"],
86
+ capture_output=True,
87
+ check=False,
88
+ )
89
+ return result.returncode == 0
90
+
91
+ def _run(self, args: list[str], body: str | None = None) -> GhResult:
92
+ gh_exe = self.gh_path
93
+ if gh_exe is None:
94
+ raise RuntimeError("gh CLI path was not resolved")
95
+
96
+ proc: subprocess.CompletedProcess[str] = (
97
+ subprocess.run( # noqa: S603 - static analysis can't verify runtime validation
98
+ [gh_exe, *args],
99
+ input=body,
100
+ text=True,
101
+ encoding="utf-8",
102
+ capture_output=True,
103
+ check=False,
104
+ )
105
+ )
106
+ stdout = proc.stdout or ""
107
+ stderr = proc.stderr or ""
108
+ combined = stdout + stderr
109
+ return GhResult(output=combined.splitlines(), exit_code=int(proc.returncode))
110
+
111
+ def issue_create(self, title: str, body: str, promotion_type: str) -> GhResult:
112
+ args = [
113
+ "issue",
114
+ "create",
115
+ "--title",
116
+ title,
117
+ "--body-file",
118
+ "-",
119
+ "--label",
120
+ promotion_type,
121
+ ]
122
+ return self._run(args, body)
123
+
124
+ def ensure_label(self, label: str) -> GhResult:
125
+ args = [
126
+ "label",
127
+ "create",
128
+ label,
129
+ "--color",
130
+ FEATURE_LABEL_COLOR,
131
+ "--description",
132
+ FEATURE_LABEL_DESCRIPTION,
133
+ ]
134
+ return self._run(args)
135
+
136
+ def issue_view(self, issue_number: str) -> GhResult:
137
+ args = [
138
+ "issue",
139
+ "view",
140
+ issue_number,
141
+ "--json",
142
+ "number,title,url,author,updatedAt",
143
+ ]
144
+ return self._run(args)
145
+
146
+
147
+ class FileSystem(Protocol):
148
+ def resolve_path(self, path_str: str) -> Path: ...
149
+
150
+ def exists(self, path: Path) -> bool: ...
151
+
152
+ def read_text(self, path: Path) -> str: ...
153
+
154
+ def write_text(self, path: Path, content: str) -> None: ...
155
+
156
+ def write_lines(self, path: Path, lines: Iterable[str]) -> None: ...
157
+
158
+ def ensure_dir(self, path: Path) -> None: ...
159
+
160
+ def move(self, src: Path, dest: Path) -> None: ...
161
+
162
+
163
+ @dataclass
164
+ class RealFileSystem(FileSystem):
165
+ def resolve_path(self, path_str: str) -> Path:
166
+ return Path(path_str).expanduser().resolve()
167
+
168
+ def exists(self, path: Path) -> bool:
169
+ return path.exists()
170
+
171
+ def read_text(self, path: Path) -> str:
172
+ return path.read_text(encoding="utf-8")
173
+
174
+ def write_text(self, path: Path, content: str) -> None:
175
+ path.write_text(content, encoding="utf-8")
176
+
177
+ def write_lines(self, path: Path, lines: Iterable[str]) -> None:
178
+ joined = "\n".join(lines)
179
+ path.write_text(joined, encoding="utf-8")
180
+
181
+ def ensure_dir(self, path: Path) -> None:
182
+ path.mkdir(parents=True, exist_ok=True)
183
+
184
+ def move(self, src: Path, dest: Path) -> None:
185
+ dest.parent.mkdir(parents=True, exist_ok=True)
186
+ shutil.move(str(src), str(dest))
187
+
188
+
189
+ @dataclass
190
+ class PromotionOutcome:
191
+ exit_code: int
192
+ messages: list[str]
193
+ destination: Path | None = None
194
+
195
+
196
+ def _resolve_workspace() -> Path:
197
+ return Path.cwd()
198
+
199
+
200
+ def _default(message: str) -> None:
201
+ print(message)
202
+
203
+
204
+ def _is_missing_label_failure(output: list[str], label: str) -> bool:
205
+ """Return whether gh output reports a missing-label create failure."""
206
+ expected_fragment = f"could not add label: '{label}' not found"
207
+ return any(expected_fragment in line.lower() for line in output)
208
+
209
+
210
+ def promote_potential(
211
+ potential_path: str,
212
+ promotion_type: str = "feature",
213
+ *,
214
+ fs: FileSystem | None = None,
215
+ gh: GhClient | None = None,
216
+ workspace: Path | None = None,
217
+ work_mode: str = "full",
218
+ emit: Callable[[str], None] = _default,
219
+ ) -> PromotionOutcome:
220
+ if promotion_type not in PROMOTION_TYPES:
221
+ raise PromotionError(f"Invalid promotion type: {promotion_type}")
222
+ if work_mode not in WORK_MODES:
223
+ raise PromotionError(f"Invalid work mode: {work_mode}")
224
+
225
+ filesystem = fs or RealFileSystem()
226
+ gh_client = gh or RealGhClient()
227
+ workspace_path = workspace or _resolve_workspace()
228
+
229
+ if not gh_client.is_authenticated():
230
+ raise PromotionError(
231
+ "GitHub CLI is not authenticated. Run 'gh auth login' first."
232
+ )
233
+
234
+ resolved = filesystem.resolve_path(potential_path)
235
+ if not filesystem.exists(resolved):
236
+ raise PromotionError(f"Potential file not found: {potential_path}")
237
+
238
+ content = filesystem.read_text(resolved)
239
+ if not content.strip():
240
+ raise PromotionError(f"Potential file is empty: {resolved}")
241
+
242
+ feature_name = get_feature_name(content, resolved)
243
+ feature_path = get_feature_path(feature_name)
244
+ prefix = TITLE_PREFIXES.get(promotion_type, "Feature")
245
+ issue_title = normalize_smart_punctuation(f"{prefix}: {feature_name}")
246
+
247
+ def _relative_path() -> str:
248
+ try:
249
+ return os.path.relpath(resolved, workspace_path)
250
+ except ValueError:
251
+ return str(resolved)
252
+
253
+ relative_path = Path(_relative_path()).as_posix()
254
+
255
+ try:
256
+ selected_mode = normalize_requested_work_mode(work_mode, promotion_type)
257
+ except ValueError as exc:
258
+ raise PromotionError(str(exc)) from exc
259
+ fallback_reason = ""
260
+
261
+ if selected_mode == "minor-audit":
262
+ problem = get_section(content, "Problem / Why") or PLACEHOLDER
263
+ implementation_intent = get_section(content, "Proposed Behavior") or PLACEHOLDER
264
+ acceptance_criteria = (
265
+ get_section(content, "Acceptance Criteria (early draft)") or PLACEHOLDER
266
+ )
267
+ dependencies_risks = get_section(content, "Constraints & Risks") or PLACEHOLDER
268
+ verification_steps = (
269
+ get_section(content, "Test Conditions to Consider") or PLACEHOLDER
270
+ )
271
+ evidence_checklist = get_section(content, "Evidence Checklist")
272
+ if not evidence_checklist:
273
+ evidence_checklist = (
274
+ "- [ ] Baseline\n- [ ] End-state\n- [ ] Targeted verification"
275
+ )
276
+ body = build_minor_audit_body(
277
+ selected_mode,
278
+ problem,
279
+ implementation_intent,
280
+ acceptance_criteria,
281
+ dependencies_risks,
282
+ verification_steps,
283
+ evidence_checklist,
284
+ relative_path,
285
+ )
286
+ elif promotion_type == "bug":
287
+ bug_sections = {
288
+ heading: get_section(content, heading) or PLACEHOLDER
289
+ for heading in BUG_SECTION_HEADINGS
290
+ }
291
+ body = build_bug_body(selected_mode, bug_sections, relative_path)
292
+ else:
293
+ problem = get_section(content, "Problem / Why") or PLACEHOLDER
294
+ behavior = get_section(content, "Proposed Behavior") or PLACEHOLDER
295
+ criteria = (
296
+ get_section(content, "Acceptance Criteria (early draft)") or PLACEHOLDER
297
+ )
298
+ constraints = get_section(content, "Constraints & Risks") or PLACEHOLDER
299
+ tests = get_section(content, "Test Conditions to Consider") or PLACEHOLDER
300
+ body = build_body(
301
+ selected_mode,
302
+ problem,
303
+ behavior,
304
+ criteria,
305
+ constraints,
306
+ tests,
307
+ relative_path,
308
+ )
309
+ body = normalize_smart_punctuation(body)
310
+
311
+ messages: list[str] = []
312
+
313
+ def _emit(msg: str) -> None:
314
+ messages.append(msg)
315
+ emit(msg)
316
+
317
+ _emit(f"Selected mode: {selected_mode}")
318
+ if fallback_reason:
319
+ _emit(f"Fallback reason: {fallback_reason}")
320
+ _emit(f"Creating issue: {issue_title} (label: {promotion_type})")
321
+ create_result = gh_client.issue_create(issue_title, body, promotion_type)
322
+
323
+ # Recover only from the known missing-label failure for the selected
324
+ # promotion label so other gh errors still fail fast with their original
325
+ # output.
326
+ if _is_missing_label_failure(create_result.output, promotion_type):
327
+ _emit("Missing promotion label detected; ensuring label exists and retrying.")
328
+ ensure_label_result = gh_client.ensure_label(promotion_type)
329
+ for line in ensure_label_result.output:
330
+ _emit(line)
331
+ if ensure_label_result.exit_code == 0:
332
+ create_result = gh_client.issue_create(issue_title, body, promotion_type)
333
+
334
+ if create_result.exit_code != 0:
335
+ output_lines = create_result.output or [
336
+ f"gh CLI exited with code {create_result.exit_code}"
337
+ ]
338
+ for line in output_lines:
339
+ _emit(line)
340
+ return PromotionOutcome(exit_code=create_result.exit_code, messages=messages)
341
+
342
+ for line in create_result.output:
343
+ _emit(line)
344
+
345
+ issue_url, issue_number = parse_issue_reference(create_result.output)
346
+
347
+ last_updated: str | None = None
348
+ if issue_number:
349
+ view_result = gh_client.issue_view(issue_number)
350
+ if view_result.exit_code == 0 and view_result.output:
351
+ last_updated = extract_last_updated("\n".join(view_result.output))
352
+
353
+ if issue_number and issue_url:
354
+ lines = content.splitlines()
355
+ updated_lines = update_metadata_lines(
356
+ lines,
357
+ feature_name,
358
+ issue_number,
359
+ issue_url,
360
+ last_updated,
361
+ feature_path,
362
+ )
363
+ filesystem.write_lines(resolved, updated_lines)
364
+ _emit(f"Updated potential file with issue metadata: {resolved}")
365
+
366
+ promoted_dir = workspace_path / "docs" / "features" / "potential" / "promoted"
367
+ filesystem.ensure_dir(promoted_dir)
368
+ dest_path = promoted_dir / resolved.name
369
+ filesystem.move(resolved, dest_path)
370
+ _emit(f"Moved potential file to promoted folder: {dest_path}")
371
+
372
+ return PromotionOutcome(exit_code=0, messages=messages, destination=dest_path)
373
+
374
+
375
+ def parse_args() -> argparse.Namespace:
376
+ parser = argparse.ArgumentParser(
377
+ description="Create a GitHub issue from a potential feature file using gh CLI.",
378
+ )
379
+ parser.add_argument(
380
+ "--potential-path",
381
+ required=True,
382
+ help="Path to the potential feature markdown file.",
383
+ )
384
+ parser.add_argument(
385
+ "--promotion-type",
386
+ choices=PROMOTION_TYPES,
387
+ default="feature",
388
+ help="Promotion type label to attach to the issue.",
389
+ )
390
+ parser.add_argument(
391
+ "--work-mode",
392
+ choices=WORK_MODES,
393
+ default="full",
394
+ help=(
395
+ "Work mode routing. Canonical values are minor-audit, full-feature, "
396
+ "and full-bug; full is accepted as a backward-compatible alias."
397
+ ),
398
+ )
399
+ return parser.parse_args()
400
+
401
+
402
+ def main() -> None:
403
+ args = parse_args()
404
+ try:
405
+ outcome = promote_potential(
406
+ potential_path=args.potential_path,
407
+ promotion_type=args.promotion_type,
408
+ work_mode=args.work_mode,
409
+ )
410
+ except (PromotionError, FileNotFoundError) as exc:
411
+ print(str(exc))
412
+ raise SystemExit(1) from exc
413
+ except subprocess.SubprocessError as exc: # pragma: no cover
414
+ print(f"gh CLI execution failed: {exc}")
415
+ raise SystemExit(1) from exc
416
+
417
+ raise SystemExit(outcome.exit_code)
418
+
419
+
420
+ if __name__ == "__main__":
421
+ main()
@@ -0,0 +1,212 @@
1
+ """Content and metadata helpers for potential-to-issue promotion workflows."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import re
7
+ from datetime import datetime
8
+ from typing import TYPE_CHECKING
9
+
10
+ if TYPE_CHECKING:
11
+ from pathlib import Path
12
+
13
+ PLACEHOLDER = "(not provided in potential file)"
14
+ ISSUE_URL_PATTERN = re.compile(r"https?://\S+/issues/(\d+)")
15
+ BUG_SECTION_HEADINGS = [
16
+ "Summary",
17
+ "Environment",
18
+ "Steps to Reproduce",
19
+ "Expected Behavior",
20
+ "Actual Behavior",
21
+ "Logs / Screenshots",
22
+ "Impact / Severity",
23
+ ]
24
+ SMART_PUNCTUATION_MAP = {
25
+ "\u201c": '"',
26
+ "\u201d": '"',
27
+ "\u2018": "'",
28
+ "\u2019": "'",
29
+ "\u2013": "-",
30
+ "\u2014": "-",
31
+ "\u00a0": " ",
32
+ }
33
+
34
+
35
+ def strip_potential_marker(value: str) -> str:
36
+ """Remove `(Potential...)` suffix markers from heading values."""
37
+ cleaned = re.sub(r"\s*\(Potential[^)]*\)", "", value, flags=re.IGNORECASE).strip()
38
+ return cleaned or value.strip()
39
+
40
+
41
+ def get_feature_name(content: str, file_path: Path) -> str:
42
+ """Derive feature name from markdown heading or filename fallback."""
43
+ heading_match = re.search(r"^\s*#\s+(.+)$", content, flags=re.MULTILINE)
44
+ if heading_match:
45
+ feature_name = strip_potential_marker(heading_match.group(1))
46
+ if feature_name:
47
+ return feature_name
48
+
49
+ name = file_path.name
50
+ return name[:-3] if name.lower().endswith(".md") else name
51
+
52
+
53
+ def get_feature_path(feature_name: str) -> str:
54
+ """Convert feature name into a safe path token."""
55
+ replaced = re.sub(r"\s+", "_", feature_name)
56
+ return re.sub(r"[^A-Za-z0-9_-]", "", replaced)
57
+
58
+
59
+ def get_section(content: str, heading: str) -> str:
60
+ """Extract markdown section body for a top-level `##` heading."""
61
+ escaped = re.escape(heading)
62
+ pattern = rf"^##\s+{escaped}\s*\r?\n(.*?)(?=^##\s+|\Z)"
63
+ match = re.search(pattern, content, flags=re.MULTILINE | re.DOTALL)
64
+ if not match:
65
+ return ""
66
+ return match.group(1).strip()
67
+
68
+
69
+ def build_body(
70
+ work_mode: str,
71
+ problem: str,
72
+ behavior: str,
73
+ criteria: str,
74
+ constraints: str,
75
+ tests: str,
76
+ relative_path: str,
77
+ ) -> str:
78
+ """Construct the standard full-feature issue body."""
79
+ return (
80
+ f"- Work Mode: {work_mode}\n"
81
+ f"## Problem / Why\n{problem}\n\n"
82
+ f"## Proposed Behavior\n{behavior}\n\n"
83
+ f"## Acceptance Criteria\n{criteria}\n\n"
84
+ f"## Constraints & Risks\n{constraints}\n\n"
85
+ f"## Test Conditions\n{tests}\n\n"
86
+ f"## Source\nFrom: {relative_path}\n"
87
+ )
88
+
89
+
90
+ def build_bug_body(work_mode: str, sections: dict[str, str], relative_path: str) -> str:
91
+ """Construct the bug issue body from canonical bug section headings."""
92
+ parts = [f"- Work Mode: {work_mode}"]
93
+ parts.extend(
94
+ f"## {heading}\n{sections[heading]}" for heading in BUG_SECTION_HEADINGS
95
+ )
96
+ parts.append(f"## Source\nFrom: {relative_path}")
97
+ return "\n\n".join(parts) + "\n"
98
+
99
+
100
+ def evaluate_minor_audit_eligibility(content: str) -> tuple[bool, str]:
101
+ """Evaluate deterministic eligibility for minor-audit mode."""
102
+ lower = content.lower()
103
+ if "bootstrapped" in lower or "pre-cooked" in lower:
104
+ return True, "eligible: bootstrapped/pre-cooked"
105
+
106
+ production_files = len(
107
+ re.findall(r"^\s*-\s*(?:production\s+)?file\s*:", content, flags=re.MULTILINE)
108
+ )
109
+ has_low_risk = "low integration risk" in lower or "risk: low" in lower
110
+ if production_files <= 3 and has_low_risk:
111
+ return True, "eligible: <=3 production files and low integration risk"
112
+ if production_files > 3:
113
+ return False, "fallback: production file count exceeds 3"
114
+ return False, "fallback: missing low integration risk signal"
115
+
116
+
117
+ def build_minor_audit_body(
118
+ work_mode: str,
119
+ problem: str,
120
+ implementation_intent: str,
121
+ acceptance_criteria: str,
122
+ dependencies_risks: str,
123
+ verification_steps: str,
124
+ evidence_checklist: str,
125
+ relative_path: str,
126
+ ) -> str:
127
+ """Build required issue sections for the minor-audit mode."""
128
+ return (
129
+ f"- Work Mode: {work_mode}\n"
130
+ f"## Problem / Why\n{problem}\n\n"
131
+ f"## Implementation Intent\n{implementation_intent}\n\n"
132
+ f"## Acceptance Criteria\n{acceptance_criteria}\n\n"
133
+ f"## Dependencies / Risks\n{dependencies_risks}\n\n"
134
+ f"## Verification Steps\n{verification_steps}\n\n"
135
+ f"## Evidence Checklist\n{evidence_checklist}\n\n"
136
+ f"## Source\nFrom: {relative_path}\n"
137
+ )
138
+
139
+
140
+ def parse_issue_reference(output: list[str]) -> tuple[str | None, str | None]:
141
+ """Parse created issue URL and number from gh output lines."""
142
+ text = "\n".join(output)
143
+ match = ISSUE_URL_PATTERN.search(text)
144
+ if not match:
145
+ return None, None
146
+ return match.group(0), match.group(1)
147
+
148
+
149
+ def extract_last_updated(issue_json: str) -> str | None:
150
+ """Extract issue updated date from gh JSON payload."""
151
+ try:
152
+ data = json.loads(issue_json)
153
+ except json.JSONDecodeError:
154
+ return None
155
+
156
+ updated_raw = data.get("updatedAt")
157
+ if not isinstance(updated_raw, str):
158
+ return None
159
+
160
+ try:
161
+ dt = datetime.fromisoformat(updated_raw.replace("Z", "+00:00"))
162
+ except ValueError:
163
+ return None
164
+ return dt.date().isoformat()
165
+
166
+
167
+ def find_meta_end(lines: list[str]) -> int:
168
+ """Locate insertion point where header metadata block ends."""
169
+ for idx, line in enumerate(lines):
170
+ if line.lstrip().startswith("## "):
171
+ return idx
172
+ return len(lines)
173
+
174
+
175
+ def normalize_smart_punctuation(text: str) -> str:
176
+ """Replace common smart punctuation characters with ASCII equivalents."""
177
+ return text.translate(str.maketrans(SMART_PUNCTUATION_MAP))
178
+
179
+
180
+ def set_line_value(lines: list[str], label: str, value: str, meta_end: int) -> int:
181
+ """Set or insert a metadata line and return updated metadata boundary index."""
182
+ pattern = re.compile(rf"^- {re.escape(label)}:")
183
+ for idx, line in enumerate(lines):
184
+ if pattern.match(line):
185
+ lines[idx] = f"- {label}: {value}"
186
+ return meta_end
187
+ lines.insert(meta_end, f"- {label}: {value}")
188
+ return meta_end + 1
189
+
190
+
191
+ def update_metadata_lines(
192
+ lines: list[str],
193
+ feature_name: str,
194
+ issue_number: str,
195
+ issue_url: str,
196
+ last_updated: str | None,
197
+ feature_path: str,
198
+ ) -> list[str]:
199
+ """Apply issue metadata updates to potential markdown lines."""
200
+ if lines:
201
+ lines[0] = f"# {feature_name} (Issue #{issue_number})"
202
+
203
+ meta_end = find_meta_end(lines)
204
+ meta_end = set_line_value(lines, "Issue", f"#{issue_number}", meta_end)
205
+ meta_end = set_line_value(lines, "Issue URL", issue_url, meta_end)
206
+ if last_updated:
207
+ meta_end = set_line_value(lines, "Last Updated", last_updated, meta_end)
208
+ status_value = (
209
+ f"Promoted -> docs/features/active/{feature_path}/ (Issue #{issue_number})"
210
+ )
211
+ set_line_value(lines, "Status", status_value, meta_end)
212
+ return lines