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