@danmoisan/drm-copilot-mcp 1.1.17 → 1.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/out/mcp-server.js +1405 -684
  2. package/package.json +6 -4
  3. package/resources/claude-customizations/.claude/agents/atomic-executor.md +11 -0
  4. package/resources/claude-customizations/.claude/agents/atomic-planner.md +10 -0
  5. package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +12 -4
  6. package/resources/claude-customizations/.claude/agents/epic-planner.md +5 -4
  7. package/resources/claude-customizations/.claude/agents/feature-review.md +16 -5
  8. package/resources/claude-customizations/.claude/agents/orchestrator.md +21 -7
  9. package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +37 -13
  10. package/resources/claude-customizations/.claude/agents/parallel-planner.md +9 -6
  11. package/resources/claude-customizations/.claude/agents/pr-author.md +15 -2
  12. package/resources/claude-customizations/.claude/agents/prd-feature.md +1 -1
  13. package/resources/claude-customizations/.claude/hooks/check-powershell-test-purity.ps1 +7 -1
  14. package/resources/claude-customizations/.claude/hooks/check-python-test-purity.ps1 +7 -1
  15. package/resources/claude-customizations/.claude/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
  16. package/resources/claude-customizations/.claude/hooks/enforce-completion-consistency.ps1 +111 -46
  17. package/resources/claude-customizations/.claude/hooks/enforce-completion-helpers.ps1 +105 -0
  18. package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +8 -1
  19. package/resources/claude-customizations/.claude/hooks/enforce-epic-invocation-origin.ps1 +7 -1
  20. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-resolution.ps1 +116 -59
  21. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +55 -23
  22. package/resources/claude-customizations/.claude/hooks/enforce-epic-wave-barrier.ps1 +74 -75
  23. package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate-resolution.ps1 +127 -35
  24. package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +61 -57
  25. package/resources/claude-customizations/.claude/hooks/enforce-evidence-locations.ps1 +7 -1
  26. package/resources/claude-customizations/.claude/hooks/enforce-feature-folder-order.ps1 +129 -39
  27. package/resources/claude-customizations/.claude/hooks/enforce-mermaid-validation.ps1 +7 -1
  28. package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +9 -3
  29. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +39 -51
  30. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
  31. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
  32. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
  33. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +17 -12
  34. package/resources/claude-customizations/.claude/hooks/enforce-parallel-abandon-gate.ps1 +9 -3
  35. package/resources/claude-customizations/.claude/hooks/enforce-parallel-cohort-barrier.ps1 +65 -50
  36. package/resources/claude-customizations/.claude/hooks/enforce-parallel-drift-gate.ps1 +49 -42
  37. package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +54 -72
  38. package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +8 -2
  39. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-command-allowlist.ps1 +279 -0
  40. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +129 -75
  41. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.artifact-root.ps1 +233 -0
  42. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.docs-only.ps1 +224 -0
  43. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.ps1 +69 -24
  44. package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner-helpers.ps1 +29 -18
  45. package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner.ps1 +10 -4
  46. package/resources/claude-customizations/.claude/hooks/enforce-promotion-mcp-only.ps1 +14 -5
  47. package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +8 -2
  48. package/resources/claude-customizations/.claude/hooks/feature-folder-resolution.ps1 +373 -0
  49. package/resources/claude-customizations/.claude/hooks/feature-review-coverage-thresholds.ps1 +85 -0
  50. package/resources/claude-customizations/.claude/hooks/hook-command-heredoc.ps1 +119 -0
  51. package/resources/claude-customizations/.claude/hooks/hook-command-invocation-operands.ps1 +198 -0
  52. package/resources/claude-customizations/.claude/hooks/hook-command-invocation.ps1 +254 -255
  53. package/resources/claude-customizations/.claude/hooks/hook-command-payload-powershell.ps1 +201 -0
  54. package/resources/claude-customizations/.claude/hooks/hook-command-payload.ps1 +484 -0
  55. package/resources/claude-customizations/.claude/hooks/hook-command-scanner.ps1 +27 -110
  56. package/resources/claude-customizations/.claude/hooks/hook-dependency-guard.ps1 +114 -0
  57. package/resources/claude-customizations/.claude/hooks/hook-docs-only-diff.ps1 +493 -0
  58. package/resources/claude-customizations/.claude/hooks/subagentstop-envelope.ps1 +192 -0
  59. package/resources/claude-customizations/.claude/hooks/validate-bash.ps1 +9 -3
  60. package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +40 -42
  61. package/resources/claude-customizations/.claude/hooks/validate-executor-output.ps1 +66 -38
  62. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-metrics.ps1 +180 -0
  63. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-rules.ps1 +195 -0
  64. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage.ps1 +141 -395
  65. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-resolution.ps1 +311 -0
  66. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-routing.ps1 +170 -0
  67. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +115 -190
  68. package/resources/claude-customizations/.claude/hooks/validate-planner-output.ps1 +64 -32
  69. package/resources/claude-customizations/.claude/hooks/validate-pr-author-output.ps1 +39 -44
  70. package/resources/claude-customizations/.claude/hooks/validate-prd-feature-output.ps1 +43 -14
  71. package/resources/claude-customizations/.claude/hooks/validate-required-artifact-output.ps1 +66 -36
  72. package/resources/claude-customizations/.claude/hooks/validate-task-researcher-output.ps1 +31 -34
  73. package/resources/claude-customizations/.claude/lib/bash/mutate-parallel-run.sh +191 -0
  74. package/resources/claude-customizations/.claude/lib/bash/parallel-cohorts.sh +13 -3
  75. package/resources/claude-customizations/.claude/lib/bash/parallel-lane-assertion.sh +4 -2
  76. package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-cli.sh +152 -0
  77. package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-ops.sh +193 -0
  78. package/resources/claude-customizations/.claude/lib/bash/parallel-mutation.sh +322 -0
  79. package/resources/claude-customizations/.claude/lib/bash/remove-parallel-item.sh +146 -0
  80. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +23 -33
  81. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusTokenShape.psm1 +86 -6
  82. package/resources/claude-customizations/.claude/lib/ci-gate/Invoke-CiGateParser.ps1 +91 -19
  83. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorState.psm1 +6 -13
  84. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateEpicWaveBarrier.psm1 +346 -0
  85. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +396 -0
  86. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateReceipts.psm1 +22 -15
  87. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRemediationAccounting.psm1 +337 -0
  88. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateRoutingContract.psm1 +9 -1
  89. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeItemResolution.psm1 +79 -2
  90. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunResolution.psm1 +3 -3
  91. package/resources/claude-customizations/.claude/rules/architecture-boundaries.md +5 -5
  92. package/resources/claude-customizations/.claude/rules/csharp.md +2 -2
  93. package/resources/claude-customizations/.claude/rules/general-code-change.md +1 -1
  94. package/resources/claude-customizations/.claude/rules/general-unit-test.md +3 -2
  95. package/resources/claude-customizations/.claude/rules/orchestrator-state.md +153 -4
  96. package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +50 -5
  97. package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +47 -8
  98. package/resources/claude-customizations/.claude/rules/quality-tiers.md +11 -7
  99. package/resources/claude-customizations/.claude/rules/shell.md +10 -8
  100. package/resources/claude-customizations/.claude/rules/typescript.md +1 -1
  101. package/resources/claude-customizations/.claude/settings.json +3 -4
  102. package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +9 -1
  103. package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +7 -1
  104. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +11 -3
  105. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup-worktrees.sh +11 -2
  106. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_detached_lib.sh +1 -1
  107. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh +171 -5
  108. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_lib.sh +1 -1
  109. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_report_records_lib.sh +6 -43
  110. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_scan_helper.sh +6 -15
  111. package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +45 -11
  112. package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +1 -1
  113. package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
  114. package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +10 -0
  115. package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +7 -4
  116. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +42 -16
  117. package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +52 -14
  118. package/resources/claude-customizations/.claude/skills/parallel-close/SKILL.md +22 -9
  119. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +97 -19
  120. package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +63 -7
  121. package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +35 -12
  122. package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +3 -1
  123. package/resources/claude-customizations/.claude/skills/quota-throttling/SKILL.md +1 -1
  124. package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +7 -3
  125. package/resources/claude-customizations/pack-manifests/core.json +25 -0
  126. package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +9 -1
  127. package/resources/codex-and-agents-customizations/.agents/skills/architecture-boundaries/SKILL.md +5 -5
  128. package/resources/codex-and-agents-customizations/.agents/skills/atomic-executor/SKILL.md +11 -0
  129. package/resources/codex-and-agents-customizations/.agents/skills/atomic-plan-contract/SKILL.md +4 -0
  130. package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +10 -0
  131. package/resources/codex-and-agents-customizations/.agents/skills/csharp/SKILL.md +2 -2
  132. package/resources/codex-and-agents-customizations/.agents/skills/csharp-qa-gate/SKILL.md +2 -2
  133. package/resources/codex-and-agents-customizations/.agents/skills/epic-orchestrate/SKILL.md +13 -3
  134. package/resources/codex-and-agents-customizations/.agents/skills/epic-plan/SKILL.md +17 -1
  135. package/resources/codex-and-agents-customizations/.agents/skills/epic-run/SKILL.md +2 -1
  136. package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
  137. package/resources/codex-and-agents-customizations/.agents/skills/feature-promotion-lifecycle/SKILL.md +1 -1
  138. package/resources/codex-and-agents-customizations/.agents/skills/feature-review/SKILL.md +30 -6
  139. package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +16 -6
  140. package/resources/codex-and-agents-customizations/.agents/skills/general-code-change/SKILL.md +1 -1
  141. package/resources/codex-and-agents-customizations/.agents/skills/general-unit-test/SKILL.md +3 -2
  142. package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +43 -11
  143. package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-state/SKILL.md +41 -2
  144. package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +19 -4
  145. package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +11 -7
  146. package/resources/codex-and-agents-customizations/.agents/skills/remediation-handoff-atomic-planner/SKILL.md +2 -0
  147. package/resources/codex-and-agents-customizations/.agents/skills/translate-claude-to-codex/SKILL.md +1 -1
  148. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp/SKILL.md +2 -2
  149. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +2 -2
  150. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c1.toml +11 -0
  151. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c2.toml +11 -0
  152. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3-elevated.toml +11 -0
  153. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3.toml +11 -0
  154. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c4.toml +11 -0
  155. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +11 -0
  156. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c1.toml +10 -0
  157. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c2.toml +10 -0
  158. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3-elevated.toml +10 -0
  159. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3.toml +10 -0
  160. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c4.toml +10 -0
  161. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +10 -0
  162. package/resources/codex-and-agents-customizations/.codex/agents/epic-orchestrator.toml +2 -1
  163. package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +6 -6
  164. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c1.toml +1 -0
  165. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c2.toml +1 -0
  166. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3-elevated.toml +1 -0
  167. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c3.toml +1 -0
  168. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer-c4.toml +1 -0
  169. package/resources/codex-and-agents-customizations/.codex/agents/feature-reviewer.toml +1 -0
  170. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +3 -3
  171. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +3 -3
  172. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +3 -3
  173. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +3 -3
  174. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +3 -3
  175. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +3 -3
  176. package/resources/codex-and-agents-customizations/.codex/codex-web-setup.sh +318 -273
  177. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  178. package/resources/codex-and-agents-customizations/.codex/hooks/check-powershell-test-purity.ps1 +7 -1
  179. package/resources/codex-and-agents-customizations/.codex/hooks/check-python-test-purity.ps1 +7 -1
  180. package/resources/codex-and-agents-customizations/.codex/hooks/codex-epic-child-launch-attestation.ps1 +1 -1
  181. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
  182. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1 +8 -2
  183. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-consistency.ps1 +97 -44
  184. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-helpers.ps1 +105 -0
  185. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-child-worktree-binding.ps1 +7 -1
  186. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +37 -5
  187. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1 +6 -0
  188. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-root-invocation.ps1 +7 -1
  189. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-wave-barrier.ps1 +7 -1
  190. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-worktree-removal-gate.ps1 +54 -41
  191. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-evidence-locations.ps1 +7 -1
  192. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +35 -14
  193. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
  194. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
  195. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
  196. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +24 -11
  197. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +8 -2
  198. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-promotion-mcp-only.ps1 +13 -4
  199. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +8 -2
  200. package/resources/codex-and-agents-customizations/.codex/hooks/feature-folder-resolution.ps1 +373 -0
  201. package/resources/codex-and-agents-customizations/.codex/hooks/feature-review-coverage-thresholds.ps1 +85 -0
  202. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-heredoc.ps1 +119 -0
  203. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation-operands.ps1 +198 -0
  204. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation.ps1 +254 -255
  205. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload-powershell.ps1 +201 -0
  206. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload.ps1 +484 -0
  207. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-scanner.ps1 +27 -110
  208. package/resources/codex-and-agents-customizations/.codex/hooks/hook-dependency-guard.ps1 +114 -0
  209. package/resources/codex-and-agents-customizations/.codex/hooks/hook-docs-only-diff.ps1 +493 -0
  210. package/resources/codex-and-agents-customizations/.codex/hooks/validate-bash.ps1 +8 -2
  211. package/resources/codex-and-agents-customizations/.codex/hooks/validate-codex-subagent-routing.ps1 +7 -1
  212. package/resources/codex-and-agents-customizations/.codex/hooks/validate-feature-review-coverage.ps1 +24 -8
  213. package/resources/codex-and-agents-customizations/pack-manifests/core.json +9 -0
  214. package/resources/customizations/.github/agents/csharp-typed-engineer.agent.md +2 -2
  215. package/resources/customizations/.github/instructions/csharp-code-change.instructions.md +4 -4
  216. package/resources/customizations/.github/instructions/csharp-unit-test.instructions.md +2 -2
  217. package/resources/customizations/.github/skills/acceptance-criteria-tracking/SKILL.md +9 -1
  218. package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +4 -0
  219. package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
  220. package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +1 -1
  221. package/resources/powershell/PoshQC/PoshQC.Coverage.psm1 +314 -0
  222. package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +25 -28
  223. package/resources/powershell/PoshQC/PoshQC.psm1 +1 -0
  224. package/resources/powershell/PoshQC/README.md +8 -2
  225. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +2 -315
@@ -0,0 +1,337 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Portable remediation-loop review-outcome and accounting checks (R5-R11).
4
+
5
+ .DESCRIPTION
6
+ Destination-runtime PowerShell port of the issue #484 invariants the
7
+ authoritative Python validator applies to a checkpoint's remediation_loop:
8
+ the review-outcome rules R8a, R8b, R9a-R9d, and R10, and the accounting
9
+ rules R5, R6, R7a, R7b, and R11, matching the error-string templates in
10
+ `scripts/dev_tools/_orchestrator_state_remediation_loop.py` and the rules
11
+ document `.claude/rules/orchestrator-state.md`.
12
+
13
+ The receipts module calls the exported entry point after its unchanged
14
+ per-cycle checks, passing the cycle list or $null when cycles is absent or
15
+ not a list, so the new checks also run for a loop with review outcomes and
16
+ no cycles.
17
+
18
+ Every comparison against the verdict and class vocabulary is case-sensitive
19
+ (-ccontains, -cnotcontains, -ceq). An integer is a JSON number deserialized
20
+ as [int] or [long]; a boolean is never an integer. Values interpolated into
21
+ a message ({v}) render through ConvertTo-PythonDisplayText so the text
22
+ matches Python's str().
23
+
24
+ Every function is pure: it reads no file, starts no process, and never
25
+ mutates its input. Each check returns a string array, empty when valid.
26
+ CONVENTION: this module fails fast at module scope and imports its siblings with -ErrorAction Stop.
27
+ #>
28
+
29
+ Set-StrictMode -Version Latest
30
+ $ErrorActionPreference = 'Stop'
31
+
32
+ # Import the shared checkpoint-value primitives, resolved relative to this
33
+ # module's directory so the import travels with the pushed-down pack.
34
+ Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'OrchestratorStateCheckpointValue.psm1') -Force -ErrorAction Stop
35
+
36
+ # Loop and cycle keys read by the accounting rules.
37
+ $script:REVIEW_OUTCOMES_KEY = 'review_outcomes'
38
+ $script:COMPLETED_ATTEMPTS_KEY = 'completed_attempts'
39
+ $script:CANDIDATE_APPLIED_KEY = 'candidate_applied'
40
+ $script:OPENED_BY_REVIEW_KEY = 'opened_by_review'
41
+ $script:COMPLETED_EXECUTION_STATUS = 'complete'
42
+
43
+ # Review verdicts and remediability classes in spec table order, and the two
44
+ # derived class partitions. Pinned to the Python constants of the same names.
45
+ $script:REVIEW_VERDICTS = @('PASS', 'REMEDIATION_REQUIRED', 'HALT_NON_REMEDIABLE', 'AWAITING_CI')
46
+ $script:REMEDIABILITY_CLASSES = @('autonomous', 'external_dependency', 'policy_hold', 'awaiting_ci', 'human_decision_required')
47
+ $script:NON_REMEDIABLE_CLASSES = @('external_dependency', 'policy_hold', 'awaiting_ci', 'human_decision_required')
48
+ $script:HALT_CLASSES = @('external_dependency', 'policy_hold', 'human_decision_required')
49
+ $script:REMEDIABLE_CLASS = 'autonomous'
50
+ $script:REMEDIATION_REQUIRED_VERDICT = 'REMEDIATION_REQUIRED'
51
+
52
+
53
+ function Test-RemediationStrictInteger {
54
+ <#
55
+ .SYNOPSIS
56
+ Report whether a deserialized JSON value is an integer and not a boolean.
57
+ .DESCRIPTION
58
+ Private predicate mirroring Python's isinstance(value, int) and not
59
+ isinstance(value, bool). ConvertFrom-Json materializes a JSON integer as
60
+ [int] or [long] and a JSON boolean as [bool].
61
+ .PARAMETER Value
62
+ The deserialized JSON value to classify. May be $null.
63
+ .OUTPUTS
64
+ System.Boolean - $true only for an [int] or [long] value.
65
+ #>
66
+ [CmdletBinding()]
67
+ [OutputType([bool])]
68
+ param(
69
+ [Parameter(Mandatory = $true)]
70
+ [AllowNull()]
71
+ [object] $Value
72
+ )
73
+
74
+ return (($Value -is [int]) -or ($Value -is [long])) -and -not ($Value -is [bool])
75
+ }
76
+
77
+ function Get-RemediationReviewVerdict {
78
+ <#
79
+ .SYNOPSIS
80
+ Derive a review verdict from its findings' remediability classes.
81
+ .DESCRIPTION
82
+ Private helper mirroring derive_review_verdict. Evaluates, in order: no
83
+ classes yields PASS; any autonomous class yields REMEDIATION_REQUIRED;
84
+ any member of HALT_CLASSES yields HALT_NON_REMEDIABLE; otherwise
85
+ AWAITING_CI. A member outside REMEDIABILITY_CLASSES (compared
86
+ case-sensitively) raises a terminating error whose message begins
87
+ 'invalid remediability: '.
88
+ .PARAMETER Remediability
89
+ The remediability class of every blocking finding; may be empty and may
90
+ repeat a class.
91
+ .OUTPUTS
92
+ System.String - one of the four review verdicts.
93
+ #>
94
+ [CmdletBinding()]
95
+ [OutputType([string])]
96
+ param(
97
+ [Parameter(Mandatory = $true)]
98
+ [AllowEmptyCollection()]
99
+ [string[]] $Remediability
100
+ )
101
+
102
+ foreach ($value in $Remediability) {
103
+ if ($script:REMEDIABILITY_CLASSES -cnotcontains $value) {
104
+ throw "invalid remediability: $value"
105
+ }
106
+ }
107
+
108
+ if ($Remediability.Count -eq 0) { return 'PASS' }
109
+ if ($Remediability -ccontains $script:REMEDIABLE_CLASS) { return 'REMEDIATION_REQUIRED' }
110
+ foreach ($value in $Remediability) {
111
+ if ($script:HALT_CLASSES -ccontains $value) { return 'HALT_NON_REMEDIABLE' }
112
+ }
113
+ return 'AWAITING_CI'
114
+ }
115
+
116
+ function Get-RemediationReviewOutcomeError {
117
+ <#
118
+ .SYNOPSIS
119
+ Return one review outcome's errors (R9a-R9d, then R10).
120
+ .DESCRIPTION
121
+ Private helper mirroring _validate_review_outcome. Checks the verdict
122
+ (string check before membership), the findings list, and each finding's
123
+ remediability (string check before membership); R10 runs only when none
124
+ of those checks produced an error for the outcome.
125
+ .PARAMETER Index
126
+ The outcome's zero-based position, used for error context.
127
+ .PARAMETER Outcome
128
+ The deserialized outcome object.
129
+ .OUTPUTS
130
+ System.String[] - zero or more error strings.
131
+ #>
132
+ [CmdletBinding()]
133
+ [OutputType([string[]])]
134
+ param(
135
+ [Parameter(Mandatory = $true)]
136
+ [int] $Index,
137
+
138
+ [Parameter(Mandatory = $true)]
139
+ [psobject] $Outcome
140
+ )
141
+
142
+ $errors = [System.Collections.Generic.List[string]]::new()
143
+ $prefix = "Checkpoint remediation review outcome #$Index"
144
+
145
+ $verdict = (Get-CheckpointObjectMember -Owner $Outcome -Name 'verdict').Value
146
+ if (-not ($verdict -is [string]) -or ($script:REVIEW_VERDICTS -cnotcontains [string]$verdict)) {
147
+ $rendered = ConvertTo-PythonDisplayText -Value $verdict
148
+ $errors.Add("$prefix verdict must be one of PASS, REMEDIATION_REQUIRED, HALT_NON_REMEDIABLE, AWAITING_CI; got: $rendered")
149
+ }
150
+
151
+ $classes = [System.Collections.Generic.List[string]]::new()
152
+ $findings = (Get-CheckpointObjectMember -Owner $Outcome -Name 'findings').Value
153
+ if (-not (Test-CheckpointListValue -Value $findings)) {
154
+ $errors.Add("$prefix findings must be a list.")
155
+ } else {
156
+ $findingIndex = 0
157
+ foreach ($finding in @($findings)) {
158
+ if (-not (Test-CheckpointObjectValue -Value $finding)) {
159
+ $errors.Add("$prefix finding #$findingIndex must be an object.")
160
+ } else {
161
+ $remediability = (Get-CheckpointObjectMember -Owner $finding -Name 'remediability').Value
162
+ if (-not ($remediability -is [string]) -or ($script:REMEDIABILITY_CLASSES -cnotcontains [string]$remediability)) {
163
+ $rendered = ConvertTo-PythonDisplayText -Value $remediability
164
+ $errors.Add("$prefix finding #$findingIndex remediability must be one of autonomous, external_dependency, policy_hold, awaiting_ci, human_decision_required; got: $rendered")
165
+ } else {
166
+ $classes.Add([string]$remediability)
167
+ }
168
+ }
169
+ $findingIndex++
170
+ }
171
+ }
172
+
173
+ # R10 compares only a well-formed outcome; any shape error above suppresses it.
174
+ if ($errors.Count -eq 0) {
175
+ $expected = Get-RemediationReviewVerdict -Remediability $classes.ToArray()
176
+ if (-not ([string]$verdict -ceq $expected)) {
177
+ $errors.Add("$prefix verdict $verdict does not match its findings (expected $expected).")
178
+ }
179
+ }
180
+
181
+ return $errors.ToArray()
182
+ }
183
+
184
+ function Get-RemediationReviewOutcomeListError {
185
+ <#
186
+ .SYNOPSIS
187
+ Return the review-outcome errors (R8a, R8b, then each outcome).
188
+ .DESCRIPTION
189
+ Private helper mirroring _validate_review_outcomes. An absent
190
+ review_outcomes key yields no errors; a present non-list value yields R8a
191
+ alone; otherwise each non-object outcome yields R8b and is skipped.
192
+ .PARAMETER RemediationLoop
193
+ The deserialized remediation_loop object.
194
+ .OUTPUTS
195
+ System.String[] - zero or more error strings.
196
+ #>
197
+ [CmdletBinding()]
198
+ [OutputType([string[]])]
199
+ param(
200
+ [Parameter(Mandatory = $true)]
201
+ [psobject] $RemediationLoop
202
+ )
203
+
204
+ $errors = [System.Collections.Generic.List[string]]::new()
205
+ $member = Get-CheckpointObjectMember -Owner $RemediationLoop -Name $script:REVIEW_OUTCOMES_KEY
206
+ if (-not $member.Present) { return $errors.ToArray() }
207
+ if (-not (Test-CheckpointListValue -Value $member.Value)) {
208
+ $errors.Add('Checkpoint remediation_loop review_outcomes must be a list.')
209
+ return $errors.ToArray()
210
+ }
211
+
212
+ $index = 0
213
+ foreach ($outcome in @($member.Value)) {
214
+ if (-not (Test-CheckpointObjectValue -Value $outcome)) {
215
+ $errors.Add("Checkpoint remediation review outcome #$index must be an object.")
216
+ } else {
217
+ $errors.AddRange([string[]]@(Get-RemediationReviewOutcomeError -Index $index -Outcome $outcome))
218
+ }
219
+ $index++
220
+ }
221
+
222
+ return $errors.ToArray()
223
+ }
224
+
225
+ function Test-RemediationOpenedByReview {
226
+ <#
227
+ .SYNOPSIS
228
+ Report whether an index names a REMEDIATION_REQUIRED outcome object.
229
+ .DESCRIPTION
230
+ Private predicate for R11: the value must be an integer (not a boolean)
231
+ from 0 to one less than the outcome count of a list review_outcomes, and
232
+ the indexed entry must be an object whose verdict is exactly
233
+ REMEDIATION_REQUIRED. A negative index is out of range.
234
+ .PARAMETER OpenedByReview
235
+ The raw opened_by_review value. May be $null.
236
+ .PARAMETER Outcomes
237
+ The raw review_outcomes value. May be $null.
238
+ .OUTPUTS
239
+ System.Boolean - $true only when the reference is valid.
240
+ #>
241
+ [CmdletBinding()]
242
+ [OutputType([bool])]
243
+ param(
244
+ [Parameter(Mandatory = $true)]
245
+ [AllowNull()]
246
+ [object] $OpenedByReview,
247
+
248
+ [Parameter(Mandatory = $true)]
249
+ [AllowNull()]
250
+ [object] $Outcomes
251
+ )
252
+
253
+ if (-not (Test-RemediationStrictInteger -Value $OpenedByReview)) { return $false }
254
+ if (-not (Test-CheckpointListValue -Value $Outcomes)) { return $false }
255
+ $outcomeList = @($Outcomes)
256
+ if ($OpenedByReview -lt 0 -or $OpenedByReview -ge $outcomeList.Count) { return $false }
257
+ $target = $outcomeList[[int]$OpenedByReview]
258
+ if (-not (Test-CheckpointObjectValue -Value $target)) { return $false }
259
+ $verdict = (Get-CheckpointObjectMember -Owner $target -Name 'verdict').Value
260
+ return ($verdict -is [string]) -and ([string]$verdict -ceq $script:REMEDIATION_REQUIRED_VERDICT)
261
+ }
262
+
263
+ function Get-OrchestratorStateRemediationAccountingError {
264
+ <#
265
+ .SYNOPSIS
266
+ Return the remediation_loop review-outcome and accounting errors (R5-R11).
267
+ .DESCRIPTION
268
+ Public entry mirroring the issue #484 tail of _validate_remediation_loop.
269
+ Returns, in order: the review-outcome errors (R8a; otherwise per outcome
270
+ R8b, R9a, R9b, R9c or R9d per finding, then R10); then, for each object
271
+ cycle in order, R5, R6, and R11; then R7a, otherwise R7b. With none of the
272
+ new keys present it returns nothing.
273
+ .PARAMETER RemediationLoop
274
+ The deserialized remediation_loop object.
275
+ .PARAMETER Cycle
276
+ The loop's cycles list, or $null when cycles is absent or not a list.
277
+ .OUTPUTS
278
+ System.String[] - zero or more error strings.
279
+ #>
280
+ [CmdletBinding()]
281
+ [OutputType([string[]])]
282
+ param(
283
+ [Parameter(Mandatory = $true)]
284
+ [psobject] $RemediationLoop,
285
+
286
+ [Parameter(Mandatory = $true)]
287
+ [AllowNull()]
288
+ [AllowEmptyCollection()]
289
+ [object] $Cycle
290
+ )
291
+
292
+ $errors = [System.Collections.Generic.List[string]]::new()
293
+ $errors.AddRange([string[]]@(Get-RemediationReviewOutcomeListError -RemediationLoop $RemediationLoop))
294
+
295
+ $outcomes = (Get-CheckpointObjectMember -Owner $RemediationLoop -Name $script:REVIEW_OUTCOMES_KEY).Value
296
+ $appliedCount = 0
297
+ $cycleItems = @()
298
+ if ($null -ne $Cycle) { $cycleItems = @($Cycle) }
299
+ $index = 0
300
+ foreach ($item in $cycleItems) {
301
+ if (Test-CheckpointObjectValue -Value $item) {
302
+ $prefix = "Checkpoint remediation cycle #$index"
303
+ $applied = Get-CheckpointObjectMember -Owner $item -Name $script:CANDIDATE_APPLIED_KEY
304
+ if ($applied.Present) {
305
+ if (-not ($applied.Value -is [bool])) {
306
+ $errors.Add("$prefix candidate_applied must be a boolean.")
307
+ } elseif ($applied.Value) {
308
+ $appliedCount++
309
+ $executionStatus = (Get-CheckpointObjectMember -Owner $item -Name 'execution_status').Value
310
+ if (-not ($executionStatus -is [string]) -or -not ([string]$executionStatus -ceq $script:COMPLETED_EXECUTION_STATUS)) {
311
+ $errors.Add("$prefix candidate_applied is true but execution_status is not 'complete'.")
312
+ }
313
+ }
314
+ }
315
+ $opened = Get-CheckpointObjectMember -Owner $item -Name $script:OPENED_BY_REVIEW_KEY
316
+ if ($opened.Present -and -not (Test-RemediationOpenedByReview -OpenedByReview $opened.Value -Outcomes $outcomes)) {
317
+ $errors.Add("$prefix opened_by_review must reference a review outcome whose verdict is REMEDIATION_REQUIRED.")
318
+ }
319
+ }
320
+ $index++
321
+ }
322
+
323
+ $attempts = Get-CheckpointObjectMember -Owner $RemediationLoop -Name $script:COMPLETED_ATTEMPTS_KEY
324
+ if ($attempts.Present) {
325
+ if (-not (Test-RemediationStrictInteger -Value $attempts.Value) -or $attempts.Value -lt 0) {
326
+ $errors.Add('Checkpoint remediation_loop completed_attempts must be a non-negative integer.')
327
+ } elseif ($attempts.Value -ne $appliedCount) {
328
+ $errors.Add("Checkpoint remediation_loop completed_attempts is $($attempts.Value) but $appliedCount cycles have candidate_applied true.")
329
+ }
330
+ }
331
+
332
+ return $errors.ToArray()
333
+ }
334
+
335
+ # Only the entry point is exported; the verdict helper and the per-outcome and
336
+ # per-reference checks stay private to this module.
337
+ Export-ModuleMember -Function Get-OrchestratorStateRemediationAccountingError
@@ -5,7 +5,8 @@
5
5
  .DESCRIPTION
6
6
  Destination-runtime PowerShell port of `validate_routing_contract` in
7
7
  `scripts/dev_tools/_orchestrator_state_routing.py`, covering parity-inventory
8
- rows C6.1 through C6.14:
8
+ rows C6.1 through C6.15. The C6.15 adoption waiver affects only receipt
9
+ presence (C6.9); the declared-list equality checks are unchanged:
9
10
 
10
11
  C6.1 routing matrix carries no routes object (returns)
11
12
  C6.2 no route selected (returns)
@@ -21,6 +22,7 @@
21
22
  C6.12 lifecycle_operations must be a list when present
22
23
  C6.13 per non-object lifecycle operation
23
24
  C6.14 per lifecycle operation that did not use the MCP surface
25
+ C6.15 issue_adoption field and waiver rules (OrchestratorStateIssueAdoption.psm1)
24
26
 
25
27
  The routing matrix is read from `OrchestratorStateRoutingMatrix.psm1`, which
26
28
  implements deviation PD-1: the constants are pinned and no disk read occurs at
@@ -56,6 +58,7 @@ $ErrorActionPreference = 'Stop'
56
58
  # pushed-down pack regardless of the working directory.
57
59
  Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'OrchestratorStateCheckpointValue.psm1') -Force -ErrorAction Stop
58
60
  Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'OrchestratorStateRoutingMatrix.psm1') -Force -ErrorAction Stop
61
+ Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'OrchestratorStateIssueAdoption.psm1') -Force -ErrorAction Stop
59
62
 
60
63
  # The promotion-entry MCP tools and the promotion type that triggers substitution.
61
64
  $script:FEATURE_PROMOTION_ENTRY_TOOL = 'new_potential_entry'
@@ -410,11 +413,16 @@ function Get-OrchestratorStateRoutingContractError {
410
413
  }
411
414
 
412
415
  $actualTools = @(Get-CheckpointAcknowledgedName -State $State -ArrayKey 'mcp_call_receipts' -NameKey 'tool' -FlagKey 'ok')
416
+ # C6.15: a valid issue_adoption record waives the receipt requirement for the
417
+ # tools it lists; any adoption error waives nothing.
418
+ $adoption = Get-OrchestratorStateIssueAdoptionResult -State $State -RouteId $routeId -RequiredMcpTool ([string[]]$requiredMcpTools) -SuccessfulTool ([string[]]$actualTools)
413
419
  foreach ($tool in $requiredMcpTools) {
420
+ if (@($adoption.WaivedTools) -ccontains $tool) { continue }
414
421
  if ($actualTools -cnotcontains $tool) {
415
422
  $errors.Add("Checkpoint missing successful MCP receipt: $tool.")
416
423
  }
417
424
  }
425
+ $errors.AddRange([string[]]@($adoption.Errors))
418
426
 
419
427
  # C6.10 to C6.14: the two empty-list fields and the lifecycle operations.
420
428
  foreach ($key in $script:COMPLETION_EMPTY_LIST_KEYS) {
@@ -21,7 +21,8 @@
21
21
  PowerShell 7+. Re-uses its siblings for enumeration, the marker test, the ascent,
22
22
  the branch reader, normalisation, the join, the result constructor, and both
23
23
  reason-code accessors, re-implementing none. Neither reason-code literal appears
24
- here. Its only filesystem read is the checkpoint-text seam. Mirrored byte-identically.
24
+ here. Its only filesystem read is still the checkpoint-text seam, including for the
25
+ item-by-pull-request resolver added for issue #850. Mirrored byte-identically.
25
26
  CONVENTION: this module fails fast at module scope and imports its siblings with -ErrorAction Stop.
26
27
  #>
27
28
 
@@ -395,6 +396,81 @@ function Resolve-WorktreeItemTarget {
395
396
  return (Resolve-WorktreeItemTargetByIssue -Session $session -Issue $issues[0])
396
397
  }
397
398
 
399
+ # Private: whether checkpoint text records a pull request number in pr_gate.pr_number or
400
+ # in a standalone_merge_authorizations entry whose pr_number is a positive JSON integer.
401
+ function Test-WorktreeItemCheckpointRecordsPr {
402
+ [CmdletBinding()]
403
+ [OutputType([bool])]
404
+ param(
405
+ [Parameter(Mandatory = $true)] [AllowNull()] [AllowEmptyString()] [string] $Text,
406
+ [Parameter(Mandatory = $true)] [long] $PrNumber
407
+ )
408
+
409
+ if ([string]::IsNullOrWhiteSpace($Text)) { return $false }
410
+ $payload = $null
411
+ try { $payload = $Text | ConvertFrom-Json } catch { return $false }
412
+ if ($null -eq $payload -or $payload -isnot [pscustomobject]) { return $false }
413
+ # Names are collected per property, because strict mode throws on .Name of an empty object.
414
+ $names = @($payload.PSObject.Properties | ForEach-Object { $_.Name })
415
+ if ($names -contains 'pr_gate' -and $payload.pr_gate -is [pscustomobject] -and @($payload.pr_gate.PSObject.Properties | ForEach-Object { $_.Name }) -contains 'pr_number') {
416
+ $recorded = [long] 0
417
+ if ([long]::TryParse([string] $payload.pr_gate.pr_number, [ref] $recorded) -and $recorded -eq $PrNumber) { return $true }
418
+ }
419
+ if ($names -notcontains 'standalone_merge_authorizations') { return $false }
420
+ foreach ($entry in @($payload.standalone_merge_authorizations)) {
421
+ if ($entry -isnot [pscustomobject] -or @($entry.PSObject.Properties | ForEach-Object { $_.Name }) -notcontains 'pr_number') { continue }
422
+ $value = $entry.pr_number
423
+ # Only a JSON integer counts; a string, fraction, zero, or negative never matches.
424
+ if (($value -is [int] -or $value -is [long]) -and $value -gt 0 -and [long] $value -eq $PrNumber) { return $true }
425
+ }
426
+ return $false
427
+ }
428
+
429
+ function Resolve-WorktreeItemTargetByPrNumber {
430
+ <#
431
+ .SYNOPSIS
432
+ Resolve the live worktree whose orchestrator checkpoint records a pull request number (issue #850).
433
+ .DESCRIPTION
434
+ Keeps each live root whose checkpoint records the number in pr_gate.pr_number or
435
+ in a standalone_merge_authorizations entry. Zero matches resolve NoTarget, one
436
+ resolves, and several are Ambiguous with no tie-break. A number of zero or less
437
+ is NoTarget. Reads only through the checkpoint-text seam.
438
+ .PARAMETER PrNumber
439
+ The pull request number the command names.
440
+ .PARAMETER SessionRoot
441
+ The calling process's path, used only to find the repository and label a result.
442
+ Defaults to the current location when blank.
443
+ #>
444
+ [CmdletBinding()]
445
+ [OutputType([pscustomobject])]
446
+ param(
447
+ [Parameter(Mandatory = $true)] [long] $PrNumber,
448
+ [Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $SessionRoot
449
+ )
450
+
451
+ $session = if ([string]::IsNullOrWhiteSpace($SessionRoot)) { (Get-Location).ProviderPath } else { $SessionRoot }
452
+ $noTarget = "pull request {0} is recorded in pr_gate.pr_number or a standalone_merge_authorizations entry of no live worktree's orchestrator checkpoint" -f $PrNumber
453
+ if ($PrNumber -le 0) {
454
+ return (New-WorktreeResolutionTargetResult -Status 'NoTarget' -SessionRoot $session -Detail $noTarget)
455
+ }
456
+ # Assigned before it is wrapped, for the reason recorded in the branch resolver.
457
+ $liveRoots = Get-WorktreeItemLiveRoot -SessionRoot $session
458
+ $matched = [System.Collections.Generic.List[string]]::new()
459
+ foreach ($root in @($liveRoots)) {
460
+ $text = Get-WorktreeItemCheckpointText -Path (Get-WorktreeItemCheckpointPath -WorktreeRoot $root)
461
+ if (Test-WorktreeItemCheckpointRecordsPr -Text $text -PrNumber $PrNumber) { $matched.Add($root) }
462
+ }
463
+ if ($matched.Count -eq 0) {
464
+ return (New-WorktreeResolutionTargetResult -Status 'NoTarget' -SessionRoot $session -Detail $noTarget)
465
+ }
466
+ if ($matched.Count -eq 1) {
467
+ return (ConvertTo-WorktreeItemResolvedResult -WorktreeRoot $matched[0] -SessionRoot $session -Detail (
468
+ "pull request {0} resolves to the live worktree whose orchestrator checkpoint records it" -f $PrNumber))
469
+ }
470
+ return (New-WorktreeResolutionTargetResult -Status 'Ambiguous' -SessionRoot $session -Candidate $matched.ToArray() -Detail (
471
+ "pull request {0} is recorded in the orchestrator checkpoints of {1} live worktrees; move the stale checkpoint to artifacts/orchestration/handoff/ so that one worktree records it" -f $PrNumber, $matched.Count))
472
+ }
473
+
398
474
  Export-ModuleMember -Function `
399
475
  Get-WorktreeItemCheckpointRelativePath, `
400
476
  Get-WorktreeItemCheckpointPath, `
@@ -404,4 +480,5 @@ Export-ModuleMember -Function `
404
480
  Get-WorktreeItemCheckpointIssue, `
405
481
  Get-WorktreeItemLiveRoot, `
406
482
  ConvertTo-WorktreeItemResolvedResult, `
407
- Resolve-WorktreeItemTarget
483
+ Resolve-WorktreeItemTarget, `
484
+ Resolve-WorktreeItemTargetByPrNumber
@@ -340,7 +340,7 @@ function Resolve-WorktreeParallelTarget {
340
340
  }
341
341
 
342
342
  # Private: compare two worktree paths, insensitive to separator style and trailing
343
- # slashes, and case-insensitive only for drive-letter paths.
343
+ # slashes, and case-insensitive for drive-letter and UNC (//) paths.
344
344
  function Test-WorktreeRunPathEqual {
345
345
  [CmdletBinding()]
346
346
  [OutputType([bool])]
@@ -352,8 +352,8 @@ function Test-WorktreeRunPathEqual {
352
352
  if ([string]::IsNullOrWhiteSpace($Left) -or [string]::IsNullOrWhiteSpace($Right)) { return $false }
353
353
  $a = ($Left.Trim() -replace '\\', '/').TrimEnd('/')
354
354
  $b = ($Right.Trim() -replace '\\', '/').TrimEnd('/')
355
- $isDrivePath = ($a -match '^[A-Za-z]:') -or ($b -match '^[A-Za-z]:')
356
- $comparison = if ($isDrivePath) { [System.StringComparison]::OrdinalIgnoreCase } else { [System.StringComparison]::Ordinal }
355
+ $isCaseInsensitivePath = ($a -match '^([A-Za-z]:|//)') -or ($b -match '^([A-Za-z]:|//)')
356
+ $comparison = if ($isCaseInsensitivePath) { [System.StringComparison]::OrdinalIgnoreCase } else { [System.StringComparison]::Ordinal }
357
357
  return [string]::Equals($a, $b, $comparison)
358
358
  }
359
359
 
@@ -2,7 +2,7 @@
2
2
  paths:
3
3
  - "**/*.ts"
4
4
  - "**/*.cs"
5
- description: Architecture boundary enforcement rules for the No-COM architecture.
5
+ description: Architecture boundary enforcement rules for a host-neutral layered architecture.
6
6
  ---
7
7
 
8
8
  # Architecture Boundaries
@@ -14,7 +14,7 @@ Architecture boundary enforcement is a uniform gate across all tiers (T1–T4).
14
14
  - **TypeScript:** `dependency-cruiser`. Configuration file pattern: `.dependency-cruiser.cjs`.
15
15
  - **.NET (when the backend exists):** `NetArchTest.Rules`. Test project naming pattern: `*.ArchitectureTests`.
16
16
 
17
- ## No-COM Architecture Rules (enforceable assertions)
17
+ ## Host-Neutral Architecture Rules (enforceable assertions)
18
18
 
19
19
  Production code in this repository must satisfy each of the following assertions. Each assertion is enforced by `dependency-cruiser` (TypeScript) or `NetArchTest.Rules` (.NET) where applicable; legacy import utilities, when added, must satisfy the same assertions.
20
20
 
@@ -37,9 +37,9 @@ Production code in this repository must satisfy each of the following assertions
37
37
 
38
38
  ## Layer Boundary Assertions (.NET, applies once the backend exists)
39
39
 
40
- - `TaskMaster.Domain` must have zero references to Outlook PIA, VSTO, or Office.js types.
41
- - `TaskMaster.Application` may depend on `TaskMaster.Domain` only.
42
- - Adapter projects may depend on `TaskMaster.Domain` and `TaskMaster.Application`; domain may not depend on adapters.
40
+ - `<Product>.Domain` must have zero references to Outlook PIA, VSTO, or Office.js types.
41
+ - `<Product>.Application` may depend on `<Product>.Domain` only.
42
+ - Adapter projects may depend on `<Product>.Domain` and `<Product>.Application`; domain may not depend on adapters.
43
43
 
44
44
  ## Enforcement Outcome
45
45
 
@@ -2,12 +2,12 @@
2
2
  paths:
3
3
  - "**/*.cs"
4
4
  - "**/*.csproj"
5
- description: C#-specific toolchain and coding standards (No-COM, xUnit).
5
+ description: C#-specific toolchain and coding standards (xUnit).
6
6
  ---
7
7
 
8
8
  # C# Code Standards
9
9
 
10
- This rule file summarizes the C#-specific policies for this repository. It targets the No-COM .NET foundation: xUnit, NSubstitute, FluentAssertions, `dotnet build`, the analyzer stack, `TimeProvider`, and uniform coverage thresholds.
10
+ This rule file summarizes the C#-specific policies for this repository. It targets a host-neutral .NET foundation: xUnit, NSubstitute, FluentAssertions, `dotnet build`, the analyzer stack, `TimeProvider`, and uniform coverage thresholds.
11
11
 
12
12
  ## Toolchain
13
13
 
@@ -26,7 +26,7 @@ Apply these priorities in order when designing or changing code:
26
26
 
27
27
  ## Module Rigor Tiers
28
28
 
29
- Module rigor tiers (T1–T4) and the uniform-versus-tier-dependent gate matrix are defined in `.claude/rules/quality-tiers.md`. Every project must be classified in `quality-tiers.yml` at repo root.
29
+ Module rigor tiers (T1–T4) and the uniform-versus-tier-dependent gate matrix are defined in `.claude/rules/quality-tiers.md` and apply only when `quality-tiers.yml` exists at the repository root; in that case every project must be classified in it. A repository without `quality-tiers.yml` has not adopted tiers, and the tier requirements do not apply.
30
30
 
31
31
  ## Mandatory Toolchain Loop
32
32
 
@@ -20,10 +20,11 @@ Every unit test must satisfy all five of these properties:
20
20
 
21
21
  ## Coverage Requirements
22
22
 
23
+ - Threshold precedence: when the repository's root `CLAUDE.md` states line or branch coverage thresholds, those thresholds govern. The 85% line and 75% branch figures are defaults that apply only when the root `CLAUDE.md` states none. This precedence applies to every restatement of these figures in other rule files, agents, and skills. Each metric falls back independently: when the root `CLAUDE.md` states only a line threshold or only a branch threshold, the stated threshold governs that metric and the default governs the other.
23
24
  - **Line coverage must remain >= 85% across all tiers (T1–T4).**
24
25
  - **Branch coverage must remain >= 75% across all tiers (T1–T4) for languages whose coverage tooling measures branch coverage.** PowerShell (Pester) and bash (kcov) are the exceptions: neither tool measures branch coverage in any output format, so only the line threshold applies to them and there is no branch-coverage gate. This is a threshold exemption only; PowerShell and bash production files remain in the coverage denominator under the Coverage Exclusion Policy below.
25
26
  - Code changes or refactors must not reduce coverage for the lines that were changed.
26
- - Tier-specific lower coverage thresholds are not used in this repository. See `.claude/rules/quality-tiers.md` for the full tier system.
27
+ - Tier-specific lower coverage thresholds are not used. See `.claude/rules/quality-tiers.md` for the full tier system, which applies only when `quality-tiers.yml` exists at the repository root.
27
28
  - Coverage is a supporting metric, not the sole quality gate. Untested critical behavior is not acceptable even if the overall percentage looks good.
28
29
  - Configure coverage tooling to exclude test files (e.g., `tests/`) so metrics reflect application code, not tests.
29
30
  - Type-only / interface-only modules with no executable behavior may be omitted from coverage measurement. Examples: Python `Protocol`-only modules consumed only under `TYPE_CHECKING`, TypeScript interface/type-only files, and C# interface-only files. Such modules legitimately report 0% executable coverage and may be excluded from measurement. This is a clarification only; it does not lower any coverage threshold.
@@ -86,7 +87,7 @@ Colocation — placing test files alongside production source files in `src/` or
86
87
 
87
88
  ## Test Categories
88
89
 
89
- The following test categories apply across the repository, with tier-dependent obligations per `.claude/rules/quality-tiers.md`:
90
+ The following test categories apply across the repository, with tier-dependent obligations per `.claude/rules/quality-tiers.md`; those tier-dependent obligations apply only when `quality-tiers.yml` exists at the repository root:
90
91
 
91
92
  - **Unit tests** — required for all tiers (T1–T4). Cover single units of behavior in isolation.
92
93
  - **Property-based tests** — required for T1 and T2 modules: at least one property test per pure function. Use `fast-check` (TypeScript) or `hypothesis` (Python) where applicable.