@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.
- package/LICENSE +21 -0
- package/README.md +50 -0
- package/out/mcp-server.js +17323 -0
- package/package.json +36 -0
- package/resources/claude-customizations/.claude/agent-memory/orchestrator/MEMORY.md +3 -0
- package/resources/claude-customizations/.claude/agent-memory/orchestrator/feedback_repo_root_is_source_of_truth.md +11 -0
- package/resources/claude-customizations/.claude/agent-memory/orchestrator/feedback_vsce_verify_package_location.md +19 -0
- package/resources/claude-customizations/.claude/agent-memory/orchestrator/project_extension_location.md +11 -0
- package/resources/claude-customizations/.claude/agent-memory/prd-feature/MEMORY.md +1 -0
- package/resources/claude-customizations/.claude/agent-memory/prd-feature/project_push_down_pattern.md +13 -0
- package/resources/claude-customizations/.claude/agent-memory/task-researcher/MEMORY.md +3 -0
- package/resources/claude-customizations/.claude/agent-memory/task-researcher/project_push_down_claude_dir.md +11 -0
- package/resources/claude-customizations/.claude/agents/atomic-executor.md +135 -0
- package/resources/claude-customizations/.claude/agents/atomic-planner.md +71 -0
- package/resources/claude-customizations/.claude/agents/csharp-typed-engineer.md +69 -0
- package/resources/claude-customizations/.claude/agents/epic-review.md +40 -0
- package/resources/claude-customizations/.claude/agents/feature-review.md +136 -0
- package/resources/claude-customizations/.claude/agents/orchestrator.md +83 -0
- package/resources/claude-customizations/.claude/agents/powershell-typed-engineer.md +80 -0
- package/resources/claude-customizations/.claude/agents/prd-feature.md +42 -0
- package/resources/claude-customizations/.claude/agents/python-typed-engineer.md +72 -0
- package/resources/claude-customizations/.claude/agents/staged-review.md +41 -0
- package/resources/claude-customizations/.claude/agents/status-updater.md +41 -0
- package/resources/claude-customizations/.claude/agents/task-researcher.md +81 -0
- package/resources/claude-customizations/.claude/agents/typescript-engineer.md +24 -0
- package/resources/claude-customizations/.claude/hooks/check-powershell-test-purity.ps1 +111 -0
- package/resources/claude-customizations/.claude/hooks/check-python-test-purity.ps1 +146 -0
- package/resources/claude-customizations/.claude/hooks/enforce-evidence-locations.ps1 +150 -0
- package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +238 -0
- package/resources/claude-customizations/.claude/hooks/enforce-promotion-mcp-only.ps1 +147 -0
- package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +235 -0
- package/resources/claude-customizations/.claude/hooks/validate-bash.ps1 +69 -0
- package/resources/claude-customizations/.claude/hooks/validate-executor-output.ps1 +296 -0
- package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage.ps1 +389 -0
- package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +141 -0
- package/resources/claude-customizations/.claude/hooks/validate-planner-output.ps1 +288 -0
- package/resources/claude-customizations/.claude/hooks/validate-required-artifact-output.ps1 +171 -0
- package/resources/claude-customizations/.claude/hooks/validate-task-researcher-output.ps1 +142 -0
- package/resources/claude-customizations/.claude/rules/csharp.md +62 -0
- package/resources/claude-customizations/.claude/rules/general-code-change.md +71 -0
- package/resources/claude-customizations/.claude/rules/general-unit-test.md +60 -0
- package/resources/claude-customizations/.claude/rules/powershell.md +97 -0
- package/resources/claude-customizations/.claude/rules/python-suppressions.md +143 -0
- package/resources/claude-customizations/.claude/rules/python.md +99 -0
- package/resources/claude-customizations/.claude/rules/self-explanatory-code-commenting.md +97 -0
- package/resources/claude-customizations/.claude/rules/tonality.md +80 -0
- package/resources/claude-customizations/.claude/rules/typescript-suppressions.md +66 -0
- package/resources/claude-customizations/.claude/rules/typescript.md +45 -0
- package/resources/claude-customizations/.claude/settings.json +144 -0
- package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +102 -0
- package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +189 -0
- package/resources/claude-customizations/.claude/skills/commit-message/SKILL.md +65 -0
- package/resources/claude-customizations/.claude/skills/csharp-change-budget-router/SKILL.md +90 -0
- package/resources/claude-customizations/.claude/skills/csharp-orchestration-state-machine/SKILL.md +58 -0
- package/resources/claude-customizations/.claude/skills/csharp-qa-gate/SKILL.md +77 -0
- package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +164 -0
- package/resources/claude-customizations/.claude/skills/execute-hard-lock/SKILL.md +82 -0
- package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +115 -0
- package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +167 -0
- package/resources/claude-customizations/.claude/skills/fill-feature-docs/SKILL.md +22 -0
- package/resources/claude-customizations/.claude/skills/invoke-csharp-engineer/SKILL.md +64 -0
- package/resources/claude-customizations/.claude/skills/invoke-powershell-engineer/SKILL.md +65 -0
- package/resources/claude-customizations/.claude/skills/invoke-python-engineer/SKILL.md +64 -0
- package/resources/claude-customizations/.claude/skills/make-skill-template/SKILL.md +147 -0
- package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +132 -0
- package/resources/claude-customizations/.claude/skills/policy-audit-template-usage/SKILL.md +49 -0
- package/resources/claude-customizations/.claude/skills/policy-compliance-order/SKILL.md +40 -0
- package/resources/claude-customizations/.claude/skills/powershell-change-budget-router/SKILL.md +49 -0
- package/resources/claude-customizations/.claude/skills/powershell-orchestration-state-machine/SKILL.md +58 -0
- package/resources/claude-customizations/.claude/skills/powershell-qa-gate/SKILL.md +77 -0
- package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +50 -0
- package/resources/claude-customizations/.claude/skills/pr-base-branch-merge-base/SKILL.md +56 -0
- package/resources/claude-customizations/.claude/skills/pr-context-artifacts/SKILL.md +30 -0
- package/resources/claude-customizations/.claude/skills/python-change-budget-router/SKILL.md +79 -0
- package/resources/claude-customizations/.claude/skills/python-qa-gate/SKILL.md +77 -0
- package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +40 -0
- package/resources/claude-customizations/.claude/skills/research-issue/SKILL.md +67 -0
- package/resources/claude-customizations/.claude/skills/review-epic/SKILL.md +21 -0
- package/resources/claude-customizations/.claude/skills/review-feature/SKILL.md +25 -0
- package/resources/claude-customizations/.claude/skills/review-staged/SKILL.md +21 -0
- package/resources/claude-customizations/.claude/skills/skill-canonical-location-audit/SKILL.md +49 -0
- package/resources/claude-customizations/.claude/skills/translate-copilot-to-claude/SKILL.md +295 -0
- package/resources/claude-customizations/.claude/skills/update-status/SKILL.md +21 -0
- package/resources/claude-dir-customizations/.mcp.json +8 -0
- package/resources/codex-and-agents-customizations/.agents/README.md +86 -0
- package/resources/codex-and-agents-customizations/.agents/skills/README.md +49 -0
- package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +107 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-executor/SKILL.md +73 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-plan-contract/SKILL.md +194 -0
- package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +87 -0
- package/resources/codex-and-agents-customizations/.agents/skills/commit-message/SKILL.md +70 -0
- package/resources/codex-and-agents-customizations/.agents/skills/commit-message-conventions/SKILL.md +95 -0
- package/resources/codex-and-agents-customizations/.agents/skills/csharp/SKILL.md +67 -0
- package/resources/codex-and-agents-customizations/.agents/skills/csharp-change-budget-router/SKILL.md +94 -0
- package/resources/codex-and-agents-customizations/.agents/skills/csharp-orchestration-state-machine/SKILL.md +64 -0
- package/resources/codex-and-agents-customizations/.agents/skills/csharp-qa-gate/SKILL.md +82 -0
- package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +168 -0
- package/resources/codex-and-agents-customizations/.agents/skills/execute-hard-lock/SKILL.md +88 -0
- package/resources/codex-and-agents-customizations/.agents/skills/feature-promotion-lifecycle/SKILL.md +129 -0
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review/SKILL.md +106 -0
- package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +181 -0
- package/resources/codex-and-agents-customizations/.agents/skills/fill-feature-docs/SKILL.md +27 -0
- package/resources/codex-and-agents-customizations/.agents/skills/invoke-csharp-engineer/SKILL.md +73 -0
- package/resources/codex-and-agents-customizations/.agents/skills/invoke-powershell-engineer/SKILL.md +74 -0
- package/resources/codex-and-agents-customizations/.agents/skills/invoke-python-engineer/SKILL.md +73 -0
- package/resources/codex-and-agents-customizations/.agents/skills/make-skill-template/SKILL.md +152 -0
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +143 -0
- package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +317 -0
- package/resources/codex-and-agents-customizations/.agents/skills/policy-audit-template-usage/SKILL.md +53 -0
- package/resources/codex-and-agents-customizations/.agents/skills/policy-compliance-order/SKILL.md +49 -0
- package/resources/codex-and-agents-customizations/.agents/skills/powershell/SKILL.md +102 -0
- package/resources/codex-and-agents-customizations/.agents/skills/powershell-change-budget-router/SKILL.md +53 -0
- package/resources/codex-and-agents-customizations/.agents/skills/powershell-orchestration-state-machine/SKILL.md +64 -0
- package/resources/codex-and-agents-customizations/.agents/skills/powershell-qa-gate/SKILL.md +83 -0
- package/resources/codex-and-agents-customizations/.agents/skills/pr-author/SKILL.md +55 -0
- package/resources/codex-and-agents-customizations/.agents/skills/pr-authoring/SKILL.md +124 -0
- package/resources/codex-and-agents-customizations/.agents/skills/pr-base-branch-merge-base/SKILL.md +60 -0
- package/resources/codex-and-agents-customizations/.agents/skills/pr-context-artifacts/SKILL.md +34 -0
- package/resources/codex-and-agents-customizations/.agents/skills/python/SKILL.md +104 -0
- package/resources/codex-and-agents-customizations/.agents/skills/python-change-budget-router/SKILL.md +84 -0
- package/resources/codex-and-agents-customizations/.agents/skills/python-qa-gate/SKILL.md +82 -0
- package/resources/codex-and-agents-customizations/.agents/skills/python-suppressions/SKILL.md +148 -0
- package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +49 -0
- package/resources/codex-and-agents-customizations/.agents/skills/repo-automation-adapter/SKILL.md +142 -0
- package/resources/codex-and-agents-customizations/.agents/skills/repo-automation-adapter/agents/openai.yaml +5 -0
- package/resources/codex-and-agents-customizations/.agents/skills/research-issue/SKILL.md +72 -0
- package/resources/codex-and-agents-customizations/.agents/skills/review-epic/SKILL.md +26 -0
- package/resources/codex-and-agents-customizations/.agents/skills/review-feature/SKILL.md +30 -0
- package/resources/codex-and-agents-customizations/.agents/skills/review-staged/SKILL.md +26 -0
- package/resources/codex-and-agents-customizations/.agents/skills/self-explanatory-code-commenting/SKILL.md +102 -0
- package/resources/codex-and-agents-customizations/.agents/skills/skill-canonical-location-audit/SKILL.md +52 -0
- package/resources/codex-and-agents-customizations/.agents/skills/translate-copilot-to-claude/SKILL.md +317 -0
- package/resources/codex-and-agents-customizations/.agents/skills/typescript/SKILL.md +50 -0
- package/resources/codex-and-agents-customizations/.agents/skills/typescript-suppressions/SKILL.md +71 -0
- package/resources/codex-and-agents-customizations/.agents/skills/update-status/SKILL.md +26 -0
- package/resources/codex-and-agents-customizations/.codex/agents/5.1-beast-adjusted.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/5.1-thinking-beast-mode-adjusted.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/api-architect.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +151 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +93 -0
- package/resources/codex-and-agents-customizations/.codex/agents/atomic-planning.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/commentary-remediation.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/commit-steward.toml +20 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-atomic-executor.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-atomic-planning.toml +25 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-orchestrator.toml +56 -0
- package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer.toml +97 -0
- package/resources/codex-and-agents-customizations/.codex/agents/epic-review.toml +52 -0
- package/resources/codex-and-agents-customizations/.codex/agents/expert-nextjs-developer.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/expert-react-frontend-engineer.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +149 -0
- package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer.toml +60 -0
- package/resources/codex-and-agents-customizations/.codex/agents/gpt-5-beast-mode.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/hlbpa.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/mentor.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +121 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-atomic-executor.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-atomic-planning.toml +25 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-di-unit-test-engineer.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-orchestrator.toml +56 -0
- package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer.toml +108 -0
- package/resources/codex-and-agents-customizations/.codex/agents/pr-author.toml +26 -0
- package/resources/codex-and-agents-customizations/.codex/agents/prd-feature.toml +53 -0
- package/resources/codex-and-agents-customizations/.codex/agents/prd.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/pytest-unit-test-coding.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-atomic-executor.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-atomic-planning.toml +25 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-execution-only-typed.toml +24 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-orchestrator.toml +54 -0
- package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer.toml +100 -0
- package/resources/codex-and-agents-customizations/.codex/agents/staged-review.toml +53 -0
- package/resources/codex-and-agents-customizations/.codex/agents/status-updater.toml +53 -0
- package/resources/codex-and-agents-customizations/.codex/agents/task-researcher.toml +103 -0
- package/resources/codex-and-agents-customizations/.codex/agents/tdd-green.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/tdd-red.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/tdd-refactor.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/agents/typescript-engineer.toml +48 -0
- package/resources/codex-and-agents-customizations/.codex/agents/voidbeast-gpt41enhanced.toml +23 -0
- package/resources/codex-and-agents-customizations/.codex/codex-web-setup.plan.md +26 -0
- package/resources/codex-and-agents-customizations/.codex/codex-web-setup.sh +384 -0
- package/resources/codex-and-agents-customizations/.codex/config.toml +137 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/check-powershell-test-purity.ps1 +113 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/check-python-test-purity.ps1 +149 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-evidence-locations.ps1 +153 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +241 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-promotion-mcp-only.ps1 +150 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +238 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-bash.ps1 +72 -0
- package/resources/codex-and-agents-customizations/.codex/hooks/validate-feature-review-coverage.ps1 +265 -0
- package/resources/codex-and-agents-customizations/.codex/prompts/feature-review-remediate.md +10 -0
- package/resources/codex-and-agents-customizations/.codex/prompts/generate-commit-message-repo.md +11 -0
- package/resources/codex-and-agents-customizations/.codex/prompts/generate-pr.md +15 -0
- package/resources/codex-and-agents-customizations/.codex/prompts/orchestrate-work.md +22 -0
- package/resources/codex-and-agents-customizations/AGENTS.md +317 -0
- package/resources/customizations/.github/agents/5.1-Beast-adjusted.agent.md +181 -0
- package/resources/customizations/.github/agents/5.1-Thinking-Beast-Mode-adjusted.agent.md +361 -0
- package/resources/customizations/.github/agents/Powershell DI Unit Test Engineer.agent.md +192 -0
- package/resources/customizations/.github/agents/api-architect.agent.md +40 -0
- package/resources/customizations/.github/agents/atomic_executor.agent.md +251 -0
- package/resources/customizations/.github/agents/atomic_planning.agent.md +658 -0
- package/resources/customizations/.github/agents/commentary-remediation.agent.md +35 -0
- package/resources/customizations/.github/agents/commit-steward.agent.md +200 -0
- package/resources/customizations/.github/agents/csharp-atomic-executor.agent.md +288 -0
- package/resources/customizations/.github/agents/csharp-atomic-planning.agent.md +354 -0
- package/resources/customizations/.github/agents/csharp-orchestrator.agent.md +375 -0
- package/resources/customizations/.github/agents/csharp-typed-engineer.agent.md +285 -0
- package/resources/customizations/.github/agents/epic-review.agent.md +374 -0
- package/resources/customizations/.github/agents/expert-nextjs-developer.agent.md +477 -0
- package/resources/customizations/.github/agents/expert-react-frontend-engineer.agent.md +739 -0
- package/resources/customizations/.github/agents/feature-review.agent.md +49 -0
- package/resources/customizations/.github/agents/gpt-5-beast-mode.agent.md +116 -0
- package/resources/customizations/.github/agents/hlbpa.agent.md +219 -0
- package/resources/customizations/.github/agents/mentor.agent.md +32 -0
- package/resources/customizations/.github/agents/orchestrator.agent.md +449 -0
- package/resources/customizations/.github/agents/powershell-atomic-executor.agent.md +287 -0
- package/resources/customizations/.github/agents/powershell-atomic-planning.agent.md +647 -0
- package/resources/customizations/.github/agents/powershell-orchestrator.agent.md +382 -0
- package/resources/customizations/.github/agents/powershell-typed-engineer.agent.md +293 -0
- package/resources/customizations/.github/agents/pr-author.agent.md +138 -0
- package/resources/customizations/.github/agents/prd-feature.agent.md +52 -0
- package/resources/customizations/.github/agents/prd.agent.md +202 -0
- package/resources/customizations/.github/agents/pytest-unit-test-coding.agent.md +202 -0
- package/resources/customizations/.github/agents/python-atomic-executor.agent.md +289 -0
- package/resources/customizations/.github/agents/python-atomic-planning.agent.md +429 -0
- package/resources/customizations/.github/agents/python-execution-only-typed.agent.md +217 -0
- package/resources/customizations/.github/agents/python-orchestrator.agent.md +380 -0
- package/resources/customizations/.github/agents/python-typed-engineer.agent.md +271 -0
- package/resources/customizations/.github/agents/staged-review.agent.md +246 -0
- package/resources/customizations/.github/agents/status_updater.agent.md +279 -0
- package/resources/customizations/.github/agents/task-researcher.agent.md +298 -0
- package/resources/customizations/.github/agents/tdd-green.agent.md +60 -0
- package/resources/customizations/.github/agents/tdd-red.agent.md +66 -0
- package/resources/customizations/.github/agents/tdd-refactor.agent.md +94 -0
- package/resources/customizations/.github/agents/typescript-engineer.agent.md +167 -0
- package/resources/customizations/.github/agents/voidbeast-gpt41enhanced.agent.md +230 -0
- package/resources/customizations/.github/codex/execute-hard-lock.prompt.md +105 -0
- package/resources/customizations/.github/codex/resume-hard-lock.prompt.md +92 -0
- package/resources/customizations/.github/copilot-instructions.md +7 -0
- package/resources/customizations/.github/instructions/csharp-code-change.instructions.md +184 -0
- package/resources/customizations/.github/instructions/csharp-unit-test.instructions.md +52 -0
- package/resources/customizations/.github/instructions/general-code-change.instructions.md +290 -0
- package/resources/customizations/.github/instructions/general-unit-test.instructions.md +106 -0
- package/resources/customizations/.github/instructions/github-actions-ci-cd-best-practices.instructions.md +607 -0
- package/resources/customizations/.github/instructions/github-actions.instructions.md +23 -0
- package/resources/customizations/.github/instructions/powershell-code-change.instructions.md +81 -0
- package/resources/customizations/.github/instructions/powershell-unit-test.instructions.md +69 -0
- package/resources/customizations/.github/instructions/python-code-change.instructions.md +232 -0
- package/resources/customizations/.github/instructions/python-suppressions.instructions.md +609 -0
- package/resources/customizations/.github/instructions/python-unit-test.instructions.md +71 -0
- package/resources/customizations/.github/instructions/self-explanatory-code-commenting.instructions.md +238 -0
- package/resources/customizations/.github/instructions/tonality.instructions.md +133 -0
- package/resources/customizations/.github/instructions/typescript-code-change.instructions.md +203 -0
- package/resources/customizations/.github/instructions/typescript-suppressions.instructions.md +157 -0
- package/resources/customizations/.github/instructions/typescript-unit-test.instructions.md +112 -0
- package/resources/customizations/.github/prompts/add-educational-comments.prompt.md +129 -0
- package/resources/customizations/.github/prompts/breakdown-bug-prd.prompt.md +29 -0
- package/resources/customizations/.github/prompts/breakdown-epic-arch.prompt.md +66 -0
- package/resources/customizations/.github/prompts/breakdown-epic-pm.prompt.md +58 -0
- package/resources/customizations/.github/prompts/breakdown-feature-implementation.prompt.md +128 -0
- package/resources/customizations/.github/prompts/breakdown-feature-prd.prompt.md +61 -0
- package/resources/customizations/.github/prompts/code-exemplars-blueprint-generator.prompt.md +126 -0
- package/resources/customizations/.github/prompts/drafts/create-github-issues-feature-from-implementation-plan.prompt.md +28 -0
- package/resources/customizations/.github/prompts/drafts/create-implementation-plan.prompt.md +158 -0
- package/resources/customizations/.github/prompts/drafts/create-technical-spike.prompt.md +231 -0
- package/resources/customizations/.github/prompts/drafts/potential-feature-prd.prompt.md +19 -0
- package/resources/customizations/.github/prompts/drafts/update-implementation-plan.prompt.md +158 -0
- package/resources/customizations/.github/prompts/execute-plan-template.md +21 -0
- package/resources/customizations/.github/prompts/export-chat.prompt.md +7 -0
- package/resources/customizations/.github/prompts/fillout-prd-feature.prompt.md +46 -0
- package/resources/customizations/.github/prompts/generate-atomic-plan.prompt.md +96 -0
- package/resources/customizations/.github/prompts/generate-commit-message-repo.prompt.md +108 -0
- package/resources/customizations/.github/prompts/generate-pr.prompt.md +151 -0
- package/resources/customizations/.github/prompts/javascript-typescript-jest.prompt.md +44 -0
- package/resources/customizations/.github/prompts/orchestrate-csharp-work.prompt.md +66 -0
- package/resources/customizations/.github/prompts/orchestrate-powershell-work.prompt.md +50 -0
- package/resources/customizations/.github/prompts/orchestrate-python-work.prompt.md +50 -0
- package/resources/customizations/.github/prompts/orchestrate-work.prompt.md +66 -0
- package/resources/customizations/.github/prompts/remediate-comments.prompt.md +53 -0
- package/resources/customizations/.github/prompts/research-issue.prompt.md +125 -0
- package/resources/customizations/.github/prompts/review-epic.prompt.md +94 -0
- package/resources/customizations/.github/prompts/review-feature.prompt.md +130 -0
- package/resources/customizations/.github/prompts/review-staged.prompt.md +43 -0
- package/resources/customizations/.github/prompts/update_status.prompt.md +68 -0
- package/resources/customizations/.github/skills/README.md +26 -0
- package/resources/customizations/.github/skills/acceptance-criteria-tracking/SKILL.md +102 -0
- package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +174 -0
- package/resources/customizations/.github/skills/csharp-change-budget-router/SKILL.md +48 -0
- package/resources/customizations/.github/skills/csharp-orchestration-state-machine/SKILL.md +57 -0
- package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +135 -0
- package/resources/customizations/.github/skills/feature-promotion-lifecycle/SKILL.md +121 -0
- package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +153 -0
- package/resources/customizations/.github/skills/make-skill-template/SKILL.md +147 -0
- package/resources/customizations/.github/skills/policy-audit-template-usage/SKILL.md +48 -0
- package/resources/customizations/.github/skills/policy-compliance-order/SKILL.md +37 -0
- package/resources/customizations/.github/skills/powershell-change-budget-router/SKILL.md +48 -0
- package/resources/customizations/.github/skills/powershell-orchestration-state-machine/SKILL.md +57 -0
- package/resources/customizations/.github/skills/pr-base-branch-merge-base/SKILL.md +55 -0
- package/resources/customizations/.github/skills/pr-context-artifacts/SKILL.md +29 -0
- package/resources/customizations/.github/skills/remediation-handoff-atomic-planner/SKILL.md +39 -0
- package/resources/customizations/.github/skills/skill-canonical-location-audit/SKILL.md +48 -0
- package/resources/feature-templates/bug/plan.yyyy-MM-ddTHH-mm.md +44 -0
- package/resources/feature-templates/bug/potential_bug.md +59 -0
- package/resources/feature-templates/bug/spec.md +99 -0
- package/resources/feature-templates/epic/initiative.md +43 -0
- package/resources/feature-templates/feature/plan.yyyy-MM-ddTHH-mm.md +53 -0
- package/resources/feature-templates/feature/spec.md +66 -0
- package/resources/feature-templates/feature/user-story.md +42 -0
- package/resources/feature-templates/potential/template.md +33 -0
- package/resources/feature-templates/refactor/plan.yyyy-MM-ddTHH-mm.md +52 -0
- package/resources/feature-templates/refactor/spec.md +69 -0
- package/resources/powershell/PoshQC/PoshQC.Analyzer.psm1 +254 -0
- package/resources/powershell/PoshQC/PoshQC.FileDiscovery.psm1 +138 -0
- package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +409 -0
- package/resources/powershell/PoshQC/PoshQC.psd1 +31 -0
- package/resources/powershell/PoshQC/PoshQC.psm1 +101 -0
- package/resources/powershell/PoshQC/README.md +80 -0
- package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +59 -0
- package/resources/powershell/PoshQC/settings/pssa.settings.psd1 +55 -0
- package/resources/scripts/dev_tools/__init__.py +0 -0
- package/resources/scripts/dev_tools/agentic_sync.py +819 -0
- package/resources/scripts/dev_tools/codex_native_converter/__init__.py +11 -0
- package/resources/scripts/dev_tools/codex_native_converter/__main__.py +6 -0
- package/resources/scripts/dev_tools/codex_native_converter/cli.py +11 -0
- package/resources/scripts/dev_tools/new_active_feature_folder.py +79 -0
- package/resources/scripts/dev_tools/new_active_feature_folder_docs.py +268 -0
- package/resources/scripts/dev_tools/new_active_feature_folder_flow.py +366 -0
- package/resources/scripts/dev_tools/new_active_feature_folder_io.py +306 -0
- package/resources/scripts/dev_tools/new_active_feature_folder_markdown.py +252 -0
- package/resources/scripts/dev_tools/new_active_feature_folder_models.py +136 -0
- package/resources/scripts/dev_tools/new_potential_bug_entry.py +465 -0
- package/resources/scripts/dev_tools/potential_to_issue.py +421 -0
- package/resources/scripts/dev_tools/potential_to_issue_content.py +212 -0
- package/resources/scripts/dev_tools/pr_context/__init__.py +0 -0
- package/resources/scripts/dev_tools/pr_context/collector.py +619 -0
- package/resources/scripts/dev_tools/pr_context/feature_docs.py +349 -0
- package/resources/scripts/dev_tools/pr_context/git.py +153 -0
- package/resources/scripts/dev_tools/pr_context/github.py +549 -0
- package/resources/scripts/dev_tools/pr_context/models.py +198 -0
- package/resources/scripts/dev_tools/pr_context/render.py +342 -0
- package/resources/scripts/dev_tools/pr_context/render_feature_excerpts.py +256 -0
- package/resources/scripts/dev_tools/pr_context/render_pr_helpers.py +291 -0
- package/resources/scripts/dev_tools/pr_context/summary_helpers.py +386 -0
- package/resources/scripts/dev_tools/pr_context/verification_evidence.py +171 -0
- package/resources/scripts/dev_tools/prompt_mode_contract.py +152 -0
- package/resources/scripts/dev_tools/push_down_claude_customizations.py +188 -0
- package/resources/scripts/dev_tools/push_down_codex_and_agents_customizations.py +139 -0
- package/resources/scripts/dev_tools/push_down_copilot_customizations.py +504 -0
- package/resources/scripts/dev_tools/push_down_copilot_customizations_filesystem.py +217 -0
- package/resources/scripts/dev_tools/push_down_copilot_customizations_rewrites.py +293 -0
- package/resources/scripts/dev_tools/resolve_file_prompt.py +457 -0
- package/resources/scripts/dev_tools/resolve_hard_lock_prompt.py +444 -0
- package/resources/scripts/dev_tools/validate_orchestration_artifacts.py +554 -0
- package/resources/templates/codex_native_converter.py +35 -0
- package/resources/templates/collect_commit_context.py +212 -0
- package/resources/templates/collect_pr_context.py +74 -0
- package/resources/templates/hello_pwsh.ps1 +3 -0
- package/resources/templates/hello_python.py +11 -0
- package/resources/templates/link-parent-child.ps1 +480 -0
- package/resources/templates/new-claude-worktree-session.ps1 +232 -0
- package/resources/templates/new-potential-entry.ps1 +187 -0
- package/resources/templates/new_active_feature_folder.py +67 -0
- package/resources/templates/new_potential_bug_entry.py +54 -0
- package/resources/templates/policy_audit/AGENTS.md +117 -0
- package/resources/templates/policy_audit/code-review.yyyy-MM-ddTHH-mm.md +165 -0
- package/resources/templates/policy_audit/feature-audit.yyyy-MM-ddTHH-mm.md +124 -0
- package/resources/templates/policy_audit/policy-audit.yyyy-MM-ddTHH-mm.md +649 -0
- package/resources/templates/potential_to_issue.py +55 -0
- package/resources/templates/push_down_claude_customizations.py +188 -0
- package/resources/templates/push_down_codex_and_agents_customizations.py +95 -0
- package/resources/templates/push_down_copilot_customizations.py +124 -0
- package/resources/templates/resolve_atomic_plan_prompt.py +75 -0
- package/resources/templates/resolve_hard_lock_prompt.py +65 -0
- package/resources/templates/run-poshqc-analyze-autofix.ps1 +16 -0
- package/resources/templates/run-poshqc-analyze.ps1 +26 -0
- package/resources/templates/run-poshqc-format.ps1 +26 -0
- package/resources/templates/run-poshqc-suite.ps1 +24 -0
- package/resources/templates/run-poshqc-test.ps1 +32 -0
- package/resources/templates/sync-agents-from-instructions.ps1 +400 -0
- package/resources/templates/validate_orchestration_artifacts.py +55 -0
- package/resources/templates/vscode-cli.helpers.ps1 +63 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from .models import FeatureDocExcerpt, section, truncate
|
|
8
|
+
from .verification_evidence import discover_canonical_evidence_files
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from collections.abc import Iterable
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def parse_section(markdown: str, heading: str) -> str:
|
|
15
|
+
escaped = re.escape(heading)
|
|
16
|
+
pattern = rf"^##\s+{escaped}\s*\r?\n(.*?)(?=^##\s+|\Z)"
|
|
17
|
+
match = re.search(pattern, markdown, flags=re.MULTILINE | re.DOTALL)
|
|
18
|
+
if not match:
|
|
19
|
+
return ""
|
|
20
|
+
return match.group(1).strip()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def completed_plan_tasks(markdown: str, *, limit: int = 10) -> list[str]:
|
|
24
|
+
tasks: list[str] = []
|
|
25
|
+
for line in markdown.splitlines():
|
|
26
|
+
if re.search(r"\[x\]", line, flags=re.IGNORECASE):
|
|
27
|
+
cleaned = re.sub(r"^[-*]\s*\[[xX]\]\s*", "", line).strip()
|
|
28
|
+
tasks.append(cleaned)
|
|
29
|
+
if len(tasks) >= limit:
|
|
30
|
+
break
|
|
31
|
+
return tasks
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def extract_issue_references(text: str) -> list[str]:
|
|
35
|
+
if not text:
|
|
36
|
+
return []
|
|
37
|
+
matches = re.findall(r"(?<!\w)#\d+|\b[A-Z][A-Z0-9]+-\d+\b", text)
|
|
38
|
+
seen: set[str] = set()
|
|
39
|
+
ordered: list[str] = []
|
|
40
|
+
for item in matches:
|
|
41
|
+
if item not in seen:
|
|
42
|
+
seen.add(item)
|
|
43
|
+
ordered.append(item)
|
|
44
|
+
return ordered
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _resolve_feature_dir(base_dir: Path, feature: str) -> Path | None:
|
|
48
|
+
direct = base_dir / feature
|
|
49
|
+
if direct.exists():
|
|
50
|
+
return direct
|
|
51
|
+
|
|
52
|
+
pattern = re.compile(rf"(?:^|[-_]){re.escape(feature)}(?:[-_]|$)")
|
|
53
|
+
strong_matches: list[Path] = []
|
|
54
|
+
weak_matches: list[Path] = []
|
|
55
|
+
|
|
56
|
+
for candidate in sorted(base_dir.iterdir()):
|
|
57
|
+
if not candidate.is_dir():
|
|
58
|
+
continue
|
|
59
|
+
name = candidate.name
|
|
60
|
+
if pattern.search(name):
|
|
61
|
+
strong_matches.append(candidate)
|
|
62
|
+
elif feature in name:
|
|
63
|
+
weak_matches.append(candidate)
|
|
64
|
+
|
|
65
|
+
if strong_matches:
|
|
66
|
+
return strong_matches[0]
|
|
67
|
+
if weak_matches:
|
|
68
|
+
return weak_matches[0]
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _read_text(path: Path) -> str:
|
|
73
|
+
return path.read_text(encoding="utf-8") if path.exists() else ""
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _latest_glob_path(directory: Path, pattern: str) -> Path | None:
|
|
77
|
+
"""Return the lexicographically latest matching file path.
|
|
78
|
+
|
|
79
|
+
Purpose:
|
|
80
|
+
Feature folders commonly use timestamped filenames (for example
|
|
81
|
+
`plan.<timestamp>.md`). Lexicographic ordering over the timestamp suffix
|
|
82
|
+
yields deterministic "latest" selection.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
directory (Path): Directory to search.
|
|
86
|
+
pattern (str): Glob pattern to match.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Path | None: Latest matching path, or None if no matches.
|
|
90
|
+
|
|
91
|
+
Side Effects:
|
|
92
|
+
Reads directory entries.
|
|
93
|
+
"""
|
|
94
|
+
matches = sorted(directory.glob(pattern))
|
|
95
|
+
return matches[-1] if matches else None
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _verification_text(plan_text: str) -> str:
|
|
99
|
+
for heading in ("Verification", "Test Plan"):
|
|
100
|
+
section_text = parse_section(plan_text, heading)
|
|
101
|
+
if section_text:
|
|
102
|
+
return section_text
|
|
103
|
+
return ""
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _parse_primary_issue_from_metadata(
|
|
107
|
+
*, spec_text: str, story_text: str, issue_text: str
|
|
108
|
+
) -> str | None:
|
|
109
|
+
"""Parse deterministic primary issue from metadata lines only.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
spec_text: Full `spec.md` text for the feature.
|
|
113
|
+
story_text: Full `user-story.md` text for the feature.
|
|
114
|
+
issue_text: Full `issue.md` text for the feature (minor-audit source).
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
A normalized issue reference (for example `#46`) when an explicit
|
|
118
|
+
metadata line `Issue: #NN` is found; otherwise `None`.
|
|
119
|
+
|
|
120
|
+
Side Effects:
|
|
121
|
+
None.
|
|
122
|
+
"""
|
|
123
|
+
# Search metadata-style lines only so narrative mentions never become the
|
|
124
|
+
# deterministic primary issue source.
|
|
125
|
+
pattern = re.compile(r"^\s*[-*]?\s*Issue:\s*(#\d+)\s*$", re.IGNORECASE)
|
|
126
|
+
|
|
127
|
+
# Prefer spec metadata first, then story, then issue.md.
|
|
128
|
+
for source_text in (spec_text, story_text, issue_text):
|
|
129
|
+
for line in source_text.splitlines():
|
|
130
|
+
match = pattern.match(line)
|
|
131
|
+
if match:
|
|
132
|
+
return match.group(1)
|
|
133
|
+
return None
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _parse_readiness_value(text: str) -> str | None:
|
|
137
|
+
"""Normalize readiness value from a feature-audit markdown payload.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
text: Raw markdown content from a `feature-audit.*.md` file.
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
One of `PASS`, `NEEDS REVISION`, `BLOCKED`, or `None`.
|
|
144
|
+
|
|
145
|
+
Side Effects:
|
|
146
|
+
None.
|
|
147
|
+
"""
|
|
148
|
+
# Normalize away Markdown emphasis so template-driven lines like
|
|
149
|
+
# `**Overall feature readiness:** **PASS**` are parseable using a single
|
|
150
|
+
# canonical regex.
|
|
151
|
+
normalized = text.replace("**", "")
|
|
152
|
+
match = re.search(
|
|
153
|
+
r"^\s*(?:Readiness|Overall feature readiness):\s*(.+?)\s*$",
|
|
154
|
+
normalized,
|
|
155
|
+
flags=re.MULTILINE | re.IGNORECASE,
|
|
156
|
+
)
|
|
157
|
+
if not match:
|
|
158
|
+
return None
|
|
159
|
+
value = match.group(1).strip().upper()
|
|
160
|
+
if value in {"PASS", "NEEDS REVISION", "BLOCKED"}:
|
|
161
|
+
return value
|
|
162
|
+
return None
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _resolve_readiness_signal(feature_dir: Path) -> tuple[str | None, Path | None]:
|
|
166
|
+
"""Resolve readiness signal from the newest readable `feature-audit.*.md`.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
feature_dir: Active feature directory containing audit artifacts.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
tuple[str | None, Path | None]:
|
|
173
|
+
- Readiness (`PASS`, `NEEDS REVISION`, `BLOCKED`) or `None`.
|
|
174
|
+
- The audit file path that produced the readiness value, or `None`.
|
|
175
|
+
|
|
176
|
+
Side Effects:
|
|
177
|
+
Reads local feature audit files from disk.
|
|
178
|
+
"""
|
|
179
|
+
audit_files = sorted(feature_dir.glob("feature-audit.*.md"))
|
|
180
|
+
# Evaluate newest-first based on lexicographic timestamp suffix.
|
|
181
|
+
# Intent: We prefer the newest audit that contains a parseable readiness
|
|
182
|
+
# marker, which allows older audits to coexist without overriding newer
|
|
183
|
+
# PASS/REVISION/BLOCKED states.
|
|
184
|
+
for audit_path in reversed(audit_files):
|
|
185
|
+
readiness = _parse_readiness_value(_read_text(audit_path))
|
|
186
|
+
if readiness:
|
|
187
|
+
return readiness, audit_path
|
|
188
|
+
return None, None
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def gather_feature_excerpts(
|
|
192
|
+
root: Path, changed_files: Iterable[str]
|
|
193
|
+
) -> list[FeatureDocExcerpt]:
|
|
194
|
+
features: set[str] = set()
|
|
195
|
+
for raw in changed_files:
|
|
196
|
+
parts = Path(raw).parts
|
|
197
|
+
if (
|
|
198
|
+
len(parts) >= 4
|
|
199
|
+
and parts[0] == "docs"
|
|
200
|
+
and parts[1] == "features"
|
|
201
|
+
and parts[2] == "active"
|
|
202
|
+
):
|
|
203
|
+
features.add(parts[3])
|
|
204
|
+
|
|
205
|
+
excerpts: list[FeatureDocExcerpt] = []
|
|
206
|
+
base_dir = root / "docs" / "features" / "active"
|
|
207
|
+
promoted_dir = root / "docs" / "features" / "potential" / "promoted"
|
|
208
|
+
for feature in sorted(features):
|
|
209
|
+
feature_dir: Path | None = _resolve_feature_dir(base_dir, feature)
|
|
210
|
+
promoted_feature_dir: Path | None = _resolve_feature_dir(promoted_dir, feature)
|
|
211
|
+
if feature_dir is None and promoted_feature_dir is None:
|
|
212
|
+
continue
|
|
213
|
+
|
|
214
|
+
active_dir = feature_dir or promoted_feature_dir
|
|
215
|
+
if active_dir is None:
|
|
216
|
+
continue
|
|
217
|
+
|
|
218
|
+
spec_path = active_dir / "spec.md"
|
|
219
|
+
issue_path = active_dir / "issue.md"
|
|
220
|
+
|
|
221
|
+
# Resolve plan path:
|
|
222
|
+
# - Prefer `plan.md` for legacy features.
|
|
223
|
+
# - Fall back to newest `plan.<timestamp>.md` for minor-audit flows.
|
|
224
|
+
plan_path = active_dir / "plan.md"
|
|
225
|
+
if not plan_path.exists():
|
|
226
|
+
latest_plan = _latest_glob_path(active_dir, "plan.*.md")
|
|
227
|
+
if latest_plan is not None:
|
|
228
|
+
plan_path = latest_plan
|
|
229
|
+
user_story_path: Path = active_dir / "user-story.md"
|
|
230
|
+
promoted_story_path = (
|
|
231
|
+
promoted_feature_dir / "user-story.md"
|
|
232
|
+
if promoted_feature_dir is not None
|
|
233
|
+
else None
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
promoted_story_text = (
|
|
237
|
+
_read_text(promoted_story_path) if promoted_story_path else ""
|
|
238
|
+
)
|
|
239
|
+
if promoted_story_path is not None and not user_story_path.exists():
|
|
240
|
+
user_story_path = promoted_story_path
|
|
241
|
+
|
|
242
|
+
user_story_text = _read_text(user_story_path)
|
|
243
|
+
if (
|
|
244
|
+
not user_story_text
|
|
245
|
+
and promoted_story_text
|
|
246
|
+
and promoted_story_path is not None
|
|
247
|
+
):
|
|
248
|
+
user_story_text = promoted_story_text
|
|
249
|
+
user_story_path = promoted_story_path
|
|
250
|
+
|
|
251
|
+
spec_text = _read_text(spec_path)
|
|
252
|
+
issue_text = _read_text(issue_path)
|
|
253
|
+
plan_text = _read_text(plan_path)
|
|
254
|
+
primary_issue_ref = _parse_primary_issue_from_metadata(
|
|
255
|
+
spec_text=spec_text,
|
|
256
|
+
story_text=user_story_text,
|
|
257
|
+
issue_text=issue_text,
|
|
258
|
+
)
|
|
259
|
+
readiness_signal, readiness_source = _resolve_readiness_signal(active_dir)
|
|
260
|
+
|
|
261
|
+
spec_parts: list[str] = []
|
|
262
|
+
for heading in (
|
|
263
|
+
"Context",
|
|
264
|
+
"Root Cause",
|
|
265
|
+
"Root Cause/Problem",
|
|
266
|
+
"Problem",
|
|
267
|
+
"Proposed Fix",
|
|
268
|
+
"Acceptance Criteria",
|
|
269
|
+
"Constraints & Risks",
|
|
270
|
+
"Behavior",
|
|
271
|
+
"Overview",
|
|
272
|
+
):
|
|
273
|
+
section_text = parse_section(spec_text, heading)
|
|
274
|
+
if section_text:
|
|
275
|
+
spec_parts.append(f"{heading}: {truncate(section_text)}")
|
|
276
|
+
|
|
277
|
+
plan_tasks = completed_plan_tasks(plan_text)
|
|
278
|
+
plan_section = (
|
|
279
|
+
"\n".join(f"- {task}" for task in plan_tasks) if plan_tasks else ""
|
|
280
|
+
)
|
|
281
|
+
verification_text = _verification_text(plan_text)
|
|
282
|
+
verification_block = (
|
|
283
|
+
"Plan verification notes:\n" + truncate(verification_text)
|
|
284
|
+
if verification_text
|
|
285
|
+
else ""
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
story_parts: list[str] = []
|
|
289
|
+
story_statements = parse_section(user_story_text, "Story Statement")
|
|
290
|
+
if story_statements:
|
|
291
|
+
story_lines = [
|
|
292
|
+
line.strip("- ")
|
|
293
|
+
for line in story_statements.splitlines()
|
|
294
|
+
if line.strip()
|
|
295
|
+
]
|
|
296
|
+
if story_lines:
|
|
297
|
+
story_parts.append(
|
|
298
|
+
"Story Statement:\n"
|
|
299
|
+
+ "\n".join(f"- {line}" for line in story_lines)
|
|
300
|
+
)
|
|
301
|
+
problem_section = parse_section(user_story_text, "Problem / Why")
|
|
302
|
+
if problem_section:
|
|
303
|
+
story_parts.append("Problem / Why:\n" + truncate(problem_section))
|
|
304
|
+
if not story_parts and promoted_story_text:
|
|
305
|
+
promoted_problem = parse_section(promoted_story_text, "Problem / Why")
|
|
306
|
+
if not promoted_problem:
|
|
307
|
+
promoted_problem = parse_section(promoted_story_text, "Summary")
|
|
308
|
+
if promoted_problem:
|
|
309
|
+
story_parts.append("Problem / Why:\n" + truncate(promoted_problem))
|
|
310
|
+
|
|
311
|
+
lines: list[str] = [section(f"Feature doc: {feature}")]
|
|
312
|
+
if story_parts:
|
|
313
|
+
lines.append("User story excerpts:\n" + "\n\n".join(story_parts))
|
|
314
|
+
if spec_parts:
|
|
315
|
+
lines.append("Spec excerpts:\n" + "\n\n".join(spec_parts))
|
|
316
|
+
if plan_section:
|
|
317
|
+
lines.append("Plan completed tasks:\n" + plan_section)
|
|
318
|
+
if verification_block:
|
|
319
|
+
lines.append(verification_block)
|
|
320
|
+
if len(lines) == 1:
|
|
321
|
+
lines.append("(no spec/plan/user-story excerpts found)")
|
|
322
|
+
|
|
323
|
+
context_files = [
|
|
324
|
+
path.relative_to(root).as_posix()
|
|
325
|
+
for path in (spec_path, issue_path, plan_path, user_story_path)
|
|
326
|
+
if path.exists()
|
|
327
|
+
]
|
|
328
|
+
if readiness_source is not None:
|
|
329
|
+
context_files.append(readiness_source.relative_to(root).as_posix())
|
|
330
|
+
# Include canonical evidence files so downstream PR authoring can cite
|
|
331
|
+
# only enumerated sources while preserving deterministic ordering.
|
|
332
|
+
evidence_context_files = [
|
|
333
|
+
path.as_posix() for path in discover_canonical_evidence_files(root, feature)
|
|
334
|
+
]
|
|
335
|
+
issue_refs = extract_issue_references(
|
|
336
|
+
"\n".join([spec_text, issue_text, plan_text, user_story_text])
|
|
337
|
+
)
|
|
338
|
+
excerpts.append(
|
|
339
|
+
FeatureDocExcerpt(
|
|
340
|
+
feature=feature,
|
|
341
|
+
excerpt="\n".join(lines),
|
|
342
|
+
issue_refs=issue_refs,
|
|
343
|
+
context_files=sorted(set(context_files + evidence_context_files)),
|
|
344
|
+
primary_issue_ref=primary_issue_ref,
|
|
345
|
+
readiness_signal=readiness_signal,
|
|
346
|
+
)
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
return excerpts
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""Git helpers for PR context collection."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import subprocess
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import TYPE_CHECKING, Protocol
|
|
8
|
+
|
|
9
|
+
from .models import CommandResult
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from collections.abc import Sequence
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CommandRunner(Protocol):
|
|
16
|
+
"""Runs shell commands and returns structured results."""
|
|
17
|
+
|
|
18
|
+
def run(
|
|
19
|
+
self,
|
|
20
|
+
args: Sequence[str],
|
|
21
|
+
*,
|
|
22
|
+
cwd: Path | None = None,
|
|
23
|
+
allow_error: bool = False,
|
|
24
|
+
) -> CommandResult: ...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class SubprocessRunner(CommandRunner):
|
|
28
|
+
"""Command runner that shells out using subprocess.run."""
|
|
29
|
+
|
|
30
|
+
def run(
|
|
31
|
+
self,
|
|
32
|
+
args: Sequence[str],
|
|
33
|
+
*,
|
|
34
|
+
cwd: Path | None = None,
|
|
35
|
+
allow_error: bool = False,
|
|
36
|
+
) -> CommandResult:
|
|
37
|
+
"""
|
|
38
|
+
Execute a command using subprocess and capture its output.
|
|
39
|
+
|
|
40
|
+
Purpose:
|
|
41
|
+
Run the provided arguments while capturing stdout, stderr, and the exit
|
|
42
|
+
code for downstream processing.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
args (Sequence[str]): Command and arguments to execute.
|
|
46
|
+
cwd (Path | None): Optional working directory for the subprocess.
|
|
47
|
+
allow_error (bool): When False, raise on non-zero exit codes; otherwise
|
|
48
|
+
return the captured result regardless of status.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
CommandResult: Captured stdout, stderr, and exit code.
|
|
52
|
+
|
|
53
|
+
Raises:
|
|
54
|
+
RuntimeError: If the subprocess exits non-zero and allow_error is False.
|
|
55
|
+
|
|
56
|
+
Side Effects:
|
|
57
|
+
Spawns a subprocess decoded as UTF-8 with replacement for undecodable
|
|
58
|
+
bytes to avoid Windows code-page failures.
|
|
59
|
+
"""
|
|
60
|
+
# We only invoke git with argument lists we construct, not user-supplied
|
|
61
|
+
# input.
|
|
62
|
+
completed = subprocess.run( # noqa: S603
|
|
63
|
+
args,
|
|
64
|
+
cwd=str(cwd) if cwd else None,
|
|
65
|
+
capture_output=True,
|
|
66
|
+
text=True,
|
|
67
|
+
encoding="utf-8",
|
|
68
|
+
errors="replace",
|
|
69
|
+
check=False,
|
|
70
|
+
shell=False,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
stdout = (completed.stdout or "").rstrip("\n")
|
|
74
|
+
stderr = (completed.stderr or "").rstrip("\n")
|
|
75
|
+
result = CommandResult(
|
|
76
|
+
stdout=stdout, stderr=stderr, code=int(completed.returncode)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
if not allow_error and result.code != 0:
|
|
80
|
+
joined = (stdout + "\n" + stderr).strip()
|
|
81
|
+
raise RuntimeError(f"{' '.join(args)} failed ({result.code}): {joined}")
|
|
82
|
+
|
|
83
|
+
return result
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class GitClient:
|
|
87
|
+
"""Thin wrapper around git for typed access."""
|
|
88
|
+
|
|
89
|
+
def __init__(self, runner: CommandRunner, cwd: Path) -> None:
|
|
90
|
+
self._runner = runner
|
|
91
|
+
self._cwd = cwd
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def cwd(self) -> Path:
|
|
95
|
+
"""Current working directory for git operations."""
|
|
96
|
+
return self._cwd
|
|
97
|
+
|
|
98
|
+
def run(self, args: Sequence[str], *, allow_error: bool = False) -> CommandResult:
|
|
99
|
+
return self._runner.run(["git", *args], cwd=self._cwd, allow_error=allow_error)
|
|
100
|
+
|
|
101
|
+
def resolve_root(self) -> Path:
|
|
102
|
+
candidate = self._cwd / ".git"
|
|
103
|
+
if candidate.exists():
|
|
104
|
+
return self._cwd
|
|
105
|
+
|
|
106
|
+
top = self.run(["rev-parse", "--show-toplevel"]).stdout
|
|
107
|
+
# Preserve git's reported root without forcing OS-specific drive resolution
|
|
108
|
+
return Path(top)
|
|
109
|
+
|
|
110
|
+
def rev_parse(self, ref: str) -> str:
|
|
111
|
+
return self.run(["rev-parse", "--verify", ref]).stdout
|
|
112
|
+
|
|
113
|
+
def remote_verbose(self) -> str:
|
|
114
|
+
return self.run(["remote", "-v"]).stdout
|
|
115
|
+
|
|
116
|
+
def branch_name(self) -> str:
|
|
117
|
+
return self.run(["rev-parse", "--abbrev-ref", "HEAD"]).stdout
|
|
118
|
+
|
|
119
|
+
def upstream(self) -> str:
|
|
120
|
+
res = self.run(
|
|
121
|
+
["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"],
|
|
122
|
+
allow_error=True,
|
|
123
|
+
)
|
|
124
|
+
return res.stdout
|
|
125
|
+
|
|
126
|
+
def status_short(self) -> str:
|
|
127
|
+
return self.run(["status", "-sb"]).stdout
|
|
128
|
+
|
|
129
|
+
def untracked(self) -> str:
|
|
130
|
+
return self.run(["ls-files", "--others", "--exclude-standard"]).stdout
|
|
131
|
+
|
|
132
|
+
def diff_name_status(self, *, staged: bool) -> str:
|
|
133
|
+
args = ["diff", "--name-status"]
|
|
134
|
+
if staged:
|
|
135
|
+
args.insert(1, "--cached")
|
|
136
|
+
return self.run(args, allow_error=True).stdout
|
|
137
|
+
|
|
138
|
+
def diff_patch(self, *, staged: bool) -> str:
|
|
139
|
+
args = ["diff"]
|
|
140
|
+
if staged:
|
|
141
|
+
args.append("--cached")
|
|
142
|
+
return self.run(args, allow_error=True).stdout
|
|
143
|
+
|
|
144
|
+
def merge_base(self, base: str, head: str) -> str:
|
|
145
|
+
return self.run(["merge-base", base, head]).stdout
|
|
146
|
+
|
|
147
|
+
def log(self, fmt: str, rev_range: str) -> str:
|
|
148
|
+
return self.run(
|
|
149
|
+
["log", "--date=short", fmt, rev_range], allow_error=True
|
|
150
|
+
).stdout
|
|
151
|
+
|
|
152
|
+
def diff_range(self, args: Sequence[str]) -> str:
|
|
153
|
+
return self.run(["diff", *args], allow_error=True).stdout
|