@danmoisan/drm-copilot-mcp 1.1.22 → 1.1.24

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 (261) hide show
  1. package/out/mcp-server.js +18758 -12030
  2. package/package.json +1 -1
  3. package/resources/claude-customizations/.claude/agent-memory/orchestrator/MEMORY.md +1 -1
  4. package/resources/claude-customizations/.claude/agent-memory/orchestrator/feedback_test_files_count_against_500_cap.md +4 -4
  5. package/resources/claude-customizations/.claude/agents/csharp-typed-engineer.md +1 -1
  6. package/resources/claude-customizations/.claude/agents/discovery-capability-sentinel.md +34 -0
  7. package/resources/claude-customizations/.claude/agents/feature-review.md +8 -0
  8. package/resources/claude-customizations/.claude/agents/legacy-parity-analyst.md +101 -43
  9. package/resources/claude-customizations/.claude/agents/migration-coverage-reviewer.md +107 -43
  10. package/resources/claude-customizations/.claude/agents/orchestrator.md +1 -1
  11. package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +60 -6
  12. package/resources/claude-customizations/.claude/agents/parallel-planner.md +21 -1
  13. package/resources/claude-customizations/.claude/agents/powershell-typed-engineer.md +1 -1
  14. package/resources/claude-customizations/.claude/agents/pr-author.md +48 -7
  15. package/resources/claude-customizations/.claude/agents/python-typed-engineer.md +1 -1
  16. package/resources/claude-customizations/.claude/agents/requirements-reconciler.md +117 -42
  17. package/resources/claude-customizations/.claude/agents/runtime-characterization-analyst.md +103 -43
  18. package/resources/claude-customizations/.claude/hooks/discovery-capability-probe.ps1 +102 -0
  19. package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +69 -194
  20. package/resources/claude-customizations/.claude/hooks/enforce-discovery-planning-gate.ps1 +87 -0
  21. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-green-ci.ps1 +325 -0
  22. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +29 -7
  23. package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate-resolution.ps1 +23 -10
  24. package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +29 -21
  25. package/resources/claude-customizations/.claude/hooks/enforce-file-size-limit.ps1 +244 -0
  26. package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +51 -0
  27. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +168 -48
  28. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +1 -1
  29. package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +22 -11
  30. package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +59 -20
  31. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-command-allowlist.ps1 +51 -4
  32. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +72 -11
  33. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.current-branch.ps1 +149 -0
  34. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.epic-base-branch.ps1 +4 -2
  35. package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +59 -20
  36. package/resources/claude-customizations/.claude/hooks/record-discovery-agent-start.ps1 +132 -0
  37. package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +56 -212
  38. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-feature-folder.ps1 +146 -0
  39. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-rejection.ps1 +172 -0
  40. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +34 -4
  41. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadius.psm1 +9 -3
  42. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusAggregate.psm1 +154 -0
  43. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusCombination.psm1 +228 -0
  44. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +1 -0
  45. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusNormalization.psm1 +4 -2
  46. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusScheduling.psm1 +63 -16
  47. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusTokenShape.psm1 +56 -1
  48. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusWriteIntent.psm1 +4 -1
  49. package/resources/claude-customizations/.claude/lib/cleanup-manifest/CleanupWorktreeManifest.psm1 +33 -6
  50. package/resources/claude-customizations/.claude/lib/codex-routing/CodexDeployment.psm1 +5 -1
  51. package/resources/claude-customizations/.claude/lib/codex-routing/CodexDiscoveryRouting.psm1 +161 -0
  52. package/resources/claude-customizations/.claude/lib/codex-routing/CodexTopology.psm1 +25 -2
  53. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryAuthority.psd1 +90 -0
  54. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryAuthority.psm1 +493 -0
  55. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryAuthorization.psm1 +479 -0
  56. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryCapability.psm1 +468 -0
  57. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryEncoding.psm1 +156 -0
  58. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryManifest.psm1 +384 -0
  59. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryObservation.psm1 +217 -0
  60. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryPayload.psm1 +276 -0
  61. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryPlanning.psm1 +336 -0
  62. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryRootGrant.psm1 +164 -0
  63. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryStart.psm1 +440 -0
  64. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryStartRecord.psm1 +296 -0
  65. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryStop.psm1 +336 -0
  66. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryToolRouting.psm1 +228 -0
  67. package/resources/claude-customizations/.claude/lib/discovery-validation/DiscoveryValidation.psm1 +188 -341
  68. package/resources/claude-customizations/.claude/lib/file-size-policy/FileSizePolicy.psm1 +434 -0
  69. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateFeatureFolderRecord.psm1 +166 -0
  70. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +8 -3
  71. package/resources/claude-customizations/.claude/lib/worktree-resolution/HookTargetWorktree.psm1 +391 -0
  72. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunRecordPath.psm1 +185 -0
  73. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunResolution.psm1 +11 -21
  74. package/resources/claude-customizations/.claude/rules/general-code-change.md +4 -1
  75. package/resources/claude-customizations/.claude/rules/orchestrator-state.md +29 -5
  76. package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +152 -20
  77. package/resources/claude-customizations/.claude/rules/powershell.md +1 -1
  78. package/resources/claude-customizations/.claude/rules/shell.md +1 -1
  79. package/resources/claude-customizations/.claude/settings.json +36 -3
  80. package/resources/claude-customizations/.claude/skills/adjudicate-unspecified-behavior/SKILL.md +135 -0
  81. package/resources/claude-customizations/.claude/skills/characterize-runtime-behavior/SKILL.md +134 -0
  82. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +2 -2
  83. package/resources/claude-customizations/.claude/skills/discovery-behavior-reconciliation/SKILL.md +28 -47
  84. package/resources/claude-customizations/.claude/skills/discovery-coverage-ledger/SKILL.md +32 -48
  85. package/resources/claude-customizations/.claude/skills/discovery-parity-matrix/SKILL.md +28 -45
  86. package/resources/claude-customizations/.claude/skills/discovery-repo-inventory/SKILL.md +28 -62
  87. package/resources/claude-customizations/.claude/skills/discovery-runtime-characterization/SKILL.md +28 -45
  88. package/resources/claude-customizations/.claude/skills/discovery-validate-artifacts/SKILL.md +28 -61
  89. package/resources/claude-customizations/.claude/skills/discovery-workflow/SKILL.md +55 -139
  90. package/resources/claude-customizations/.claude/skills/execution-environment/SKILL.md +25 -10
  91. package/resources/claude-customizations/.claude/skills/extract-feature-contract/SKILL.md +133 -0
  92. package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +1 -0
  93. package/resources/claude-customizations/.claude/skills/generate-acceptance-scenarios/SKILL.md +132 -0
  94. package/resources/claude-customizations/.claude/skills/initialize-discovery-workspace/SKILL.md +131 -0
  95. package/resources/claude-customizations/.claude/skills/inventory-legacy-system/SKILL.md +131 -0
  96. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +15 -7
  97. package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +25 -2
  98. package/resources/claude-customizations/.claude/skills/parallel-close/SKILL.md +11 -1
  99. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +124 -14
  100. package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +72 -7
  101. package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +15 -0
  102. package/resources/claude-customizations/.claude/skills/parallel-run/SKILL.md +6 -0
  103. package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +56 -9
  104. package/resources/claude-customizations/.claude/skills/reconcile-parity-matrix/SKILL.md +131 -0
  105. package/resources/claude-customizations/.claude/skills/review-discovery-coverage/SKILL.md +129 -0
  106. package/resources/claude-customizations/.claude/skills/validate-discovery-artifacts/SKILL.md +127 -0
  107. package/resources/claude-customizations/.claude-variants/csharp-legacy/agents/csharp-typed-engineer.md +1 -1
  108. package/resources/claude-customizations/config/blast-radius.json +6 -5
  109. package/resources/claude-customizations/config/orchestration-routing.json +61 -1
  110. package/resources/claude-customizations/pack-manifests/core.json +40 -1
  111. package/resources/codex-and-agents-customizations/.agents/skills/adjudicate-unspecified-behavior/SKILL.md +135 -0
  112. package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +7 -0
  113. package/resources/codex-and-agents-customizations/.agents/skills/characterize-runtime-behavior/SKILL.md +134 -0
  114. package/resources/codex-and-agents-customizations/.agents/skills/discovery-behavior-reconciliation/SKILL.md +46 -0
  115. package/resources/codex-and-agents-customizations/.agents/skills/discovery-coverage-ledger/SKILL.md +50 -0
  116. package/resources/codex-and-agents-customizations/.agents/skills/discovery-parity-matrix/SKILL.md +46 -0
  117. package/resources/codex-and-agents-customizations/.agents/skills/discovery-repo-inventory/SKILL.md +46 -0
  118. package/resources/codex-and-agents-customizations/.agents/skills/discovery-runtime-characterization/SKILL.md +46 -0
  119. package/resources/codex-and-agents-customizations/.agents/skills/discovery-validate-artifacts/SKILL.md +46 -0
  120. package/resources/codex-and-agents-customizations/.agents/skills/discovery-workflow/SKILL.md +62 -0
  121. package/resources/codex-and-agents-customizations/.agents/skills/execution-environment/SKILL.md +25 -10
  122. package/resources/codex-and-agents-customizations/.agents/skills/extract-feature-contract/SKILL.md +133 -0
  123. package/resources/codex-and-agents-customizations/.agents/skills/feature-promotion-lifecycle/SKILL.md +1 -1
  124. package/resources/codex-and-agents-customizations/.agents/skills/feature-review/SKILL.md +8 -0
  125. package/resources/codex-and-agents-customizations/.agents/skills/general-code-change/SKILL.md +4 -1
  126. package/resources/codex-and-agents-customizations/.agents/skills/generate-acceptance-scenarios/SKILL.md +132 -0
  127. package/resources/codex-and-agents-customizations/.agents/skills/initialize-discovery-workspace/SKILL.md +131 -0
  128. package/resources/codex-and-agents-customizations/.agents/skills/inventory-legacy-system/SKILL.md +131 -0
  129. package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +8 -0
  130. package/resources/codex-and-agents-customizations/.agents/skills/powershell/SKILL.md +1 -1
  131. package/resources/codex-and-agents-customizations/.agents/skills/reconcile-parity-matrix/SKILL.md +131 -0
  132. package/resources/codex-and-agents-customizations/.agents/skills/review-discovery-coverage/SKILL.md +129 -0
  133. package/resources/codex-and-agents-customizations/.agents/skills/validate-discovery-artifacts/SKILL.md +127 -0
  134. package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c1.toml +1 -1
  135. package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c2.toml +1 -1
  136. package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c3-elevated.toml +1 -1
  137. package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c3.toml +1 -1
  138. package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer-c4.toml +1 -1
  139. package/resources/codex-and-agents-customizations/.codex/agents/csharp-typed-engineer.toml +1 -1
  140. package/resources/codex-and-agents-customizations/.codex/agents/discovery-capability-sentinel.toml +51 -0
  141. package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +8 -0
  142. package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c1.toml +148 -0
  143. package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c2.toml +148 -0
  144. package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c3-elevated.toml +148 -0
  145. package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c3.toml +148 -0
  146. package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst-c4.toml +148 -0
  147. package/resources/codex-and-agents-customizations/.codex/agents/legacy-parity-analyst.toml +148 -0
  148. package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c1.toml +154 -0
  149. package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c2.toml +154 -0
  150. package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c3-elevated.toml +154 -0
  151. package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c3.toml +154 -0
  152. package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer-c4.toml +154 -0
  153. package/resources/codex-and-agents-customizations/.codex/agents/migration-coverage-reviewer.toml +154 -0
  154. package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c1.toml +1 -1
  155. package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c2.toml +1 -1
  156. package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c3-elevated.toml +1 -1
  157. package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c3.toml +1 -1
  158. package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer-c4.toml +1 -1
  159. package/resources/codex-and-agents-customizations/.codex/agents/powershell-typed-engineer.toml +1 -1
  160. package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c1.toml +1 -1
  161. package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c2.toml +1 -1
  162. package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3-elevated.toml +1 -1
  163. package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c3.toml +1 -1
  164. package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer-c4.toml +1 -1
  165. package/resources/codex-and-agents-customizations/.codex/agents/python-typed-engineer.toml +1 -1
  166. package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c1.toml +164 -0
  167. package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c2.toml +164 -0
  168. package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c3-elevated.toml +164 -0
  169. package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c3.toml +164 -0
  170. package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler-c4.toml +164 -0
  171. package/resources/codex-and-agents-customizations/.codex/agents/requirements-reconciler.toml +164 -0
  172. package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c1.toml +150 -0
  173. package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c2.toml +150 -0
  174. package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c3-elevated.toml +150 -0
  175. package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c3.toml +150 -0
  176. package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst-c4.toml +150 -0
  177. package/resources/codex-and-agents-customizations/.codex/agents/runtime-characterization-analyst.toml +150 -0
  178. package/resources/codex-and-agents-customizations/.codex/config.toml +39 -3
  179. package/resources/codex-and-agents-customizations/.codex/hooks/codex-agent-profile-attestation.ps1 +22 -0
  180. package/resources/codex-and-agents-customizations/.codex/hooks/discovery-capability-probe.ps1 +97 -0
  181. package/resources/codex-and-agents-customizations/.codex/hooks/discovery-start-attestation.ps1 +171 -0
  182. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1 +4 -1
  183. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-discovery-artifact-gate.ps1 +187 -0
  184. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-discovery-planning-gate.ps1 +149 -0
  185. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-file-size-limit.ps1 +282 -0
  186. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +239 -2
  187. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +6 -15
  188. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +54 -15
  189. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +54 -15
  190. package/resources/codex-and-agents-customizations/.codex/hooks/file-size-policy.ps1 +421 -0
  191. package/resources/codex-and-agents-customizations/.codex/hooks/hook-target-worktree.ps1 +369 -0
  192. package/resources/codex-and-agents-customizations/.codex/hooks/record-subagent-routing-attestation.ps1 +8 -0
  193. package/resources/codex-and-agents-customizations/.codex/hooks/validate-codex-subagent-routing.ps1 +22 -1
  194. package/resources/codex-and-agents-customizations/.codex/hooks/validate-discovery-agent-output.ps1 +178 -0
  195. package/resources/codex-and-agents-customizations/.codex/scripts/Resolve-CodexTopology.ps1 +11 -1
  196. package/resources/codex-and-agents-customizations/.codex-variants/csharp-legacy/agents/csharp-typed-engineer.toml +1 -1
  197. package/resources/codex-and-agents-customizations/AGENTS.md +4 -1
  198. package/resources/codex-and-agents-customizations/pack-manifests/core.json +65 -1
  199. package/resources/config/orchestration-routing.json +61 -1
  200. package/resources/customizations/.github/agents/commentary-remediation.agent.md +1 -1
  201. package/resources/customizations/.github/agents/discovery-capability-sentinel.agent.md +34 -0
  202. package/resources/customizations/.github/agents/legacy-parity-analyst.agent.md +122 -0
  203. package/resources/customizations/.github/agents/migration-coverage-reviewer.agent.md +128 -0
  204. package/resources/customizations/.github/agents/python-execution-only-typed.agent.md +1 -1
  205. package/resources/customizations/.github/agents/python-typed-engineer.agent.md +1 -1
  206. package/resources/customizations/.github/agents/requirements-reconciler.agent.md +138 -0
  207. package/resources/customizations/.github/agents/runtime-characterization-analyst.agent.md +124 -0
  208. package/resources/customizations/.github/hooks/discovery-agent-start.ps1 +139 -0
  209. package/resources/customizations/.github/hooks/discovery-agent-stop.ps1 +123 -0
  210. package/resources/customizations/.github/hooks/discovery-capability-probe.ps1 +98 -0
  211. package/resources/customizations/.github/hooks/discovery-planning.ps1 +91 -0
  212. package/resources/customizations/.github/hooks/discovery-pre-tool.ps1 +123 -0
  213. package/resources/customizations/.github/hooks/discovery.json +35 -0
  214. package/resources/customizations/.github/instructions/general-code-change.instructions.md +5 -2
  215. package/resources/customizations/.github/instructions/mermaid.instructions.md +85 -0
  216. package/resources/customizations/.github/instructions/powershell-code-change.instructions.md +1 -1
  217. package/resources/customizations/.github/prompts/execute-hard-lock.prompt.md +105 -0
  218. package/resources/customizations/.github/prompts/remediate-comments.prompt.md +1 -1
  219. package/resources/customizations/.github/skills/adjudicate-unspecified-behavior/SKILL.md +135 -0
  220. package/resources/customizations/.github/skills/characterize-runtime-behavior/SKILL.md +134 -0
  221. package/resources/customizations/.github/skills/discovery-behavior-reconciliation/SKILL.md +46 -0
  222. package/resources/customizations/.github/skills/discovery-coverage-ledger/SKILL.md +50 -0
  223. package/resources/customizations/.github/skills/discovery-parity-matrix/SKILL.md +46 -0
  224. package/resources/customizations/.github/skills/discovery-repo-inventory/SKILL.md +46 -0
  225. package/resources/customizations/.github/skills/discovery-runtime-characterization/SKILL.md +46 -0
  226. package/resources/customizations/.github/skills/discovery-validate-artifacts/SKILL.md +46 -0
  227. package/resources/customizations/.github/skills/discovery-workflow/SKILL.md +62 -0
  228. package/resources/customizations/.github/skills/execution-environment/SKILL.md +25 -10
  229. package/resources/customizations/.github/skills/extract-feature-contract/SKILL.md +133 -0
  230. package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +8 -0
  231. package/resources/customizations/.github/skills/generate-acceptance-scenarios/SKILL.md +132 -0
  232. package/resources/customizations/.github/skills/initialize-discovery-workspace/SKILL.md +131 -0
  233. package/resources/customizations/.github/skills/inventory-legacy-system/SKILL.md +131 -0
  234. package/resources/customizations/.github/skills/reconcile-parity-matrix/SKILL.md +131 -0
  235. package/resources/customizations/.github/skills/review-discovery-coverage/SKILL.md +129 -0
  236. package/resources/customizations/.github/skills/validate-discovery-artifacts/SKILL.md +127 -0
  237. package/resources/lib/codex-routing/CodexDeployment.psm1 +5 -1
  238. package/resources/lib/codex-routing/CodexDiscoveryRouting.psm1 +161 -0
  239. package/resources/lib/codex-routing/CodexTopology.psm1 +25 -2
  240. package/resources/lib/discovery-validation/DiscoveryAuthority.psd1 +90 -0
  241. package/resources/lib/discovery-validation/DiscoveryAuthority.psm1 +493 -0
  242. package/resources/lib/discovery-validation/DiscoveryAuthorization.psm1 +479 -0
  243. package/resources/lib/discovery-validation/DiscoveryCapability.psm1 +468 -0
  244. package/resources/lib/discovery-validation/DiscoveryEncoding.psm1 +156 -0
  245. package/resources/lib/discovery-validation/DiscoveryManifest.psm1 +384 -0
  246. package/resources/lib/discovery-validation/DiscoveryObservation.psm1 +217 -0
  247. package/resources/lib/discovery-validation/DiscoveryPayload.psm1 +276 -0
  248. package/resources/lib/discovery-validation/DiscoveryPlanning.psm1 +336 -0
  249. package/resources/lib/discovery-validation/DiscoveryRootGrant.psm1 +164 -0
  250. package/resources/lib/discovery-validation/DiscoveryStart.psm1 +440 -0
  251. package/resources/lib/discovery-validation/DiscoveryStartRecord.psm1 +296 -0
  252. package/resources/lib/discovery-validation/DiscoveryStop.psm1 +336 -0
  253. package/resources/lib/discovery-validation/DiscoveryToolRouting.psm1 +228 -0
  254. package/resources/powershell/PoshQC/PoshQC.Parallel.psm1 +452 -0
  255. package/resources/powershell/PoshQC/PoshQC.Shard.psm1 +106 -8
  256. package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +12 -0
  257. package/resources/powershell/PoshQC/PoshQC.psd1 +6 -1
  258. package/resources/powershell/PoshQC/PoshQC.psm1 +7 -1
  259. package/resources/powershell/PoshQC/README.md +20 -1
  260. package/resources/templates/policy_audit/code-review.yyyy-MM-ddTHH-mm.md +4 -4
  261. package/resources/templates/policy_audit/policy-audit.yyyy-MM-ddTHH-mm.md +4 -4
@@ -0,0 +1,228 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Planning-time issue combination over the scheduling pair data (issue #1013).
4
+
5
+ .DESCRIPTION
6
+ Destination-runtime PowerShell mirror of
7
+ scripts/dev_tools/_blast_radius_combination.py (spec D-5). Finds the pairs
8
+ of work items whose integration cost is high enough that delivering them as
9
+ one item costs less than merging them, and groups them into combinations.
10
+
11
+ Rules:
12
+ 1. Disabled when conflict_tolerance is absent or tolerance_percent is 0.
13
+ 2. Get-BlastRadiusPairDecision supplies each conflicting pair's reasons,
14
+ cost (including the D-7 contract term), and benefit; edges and
15
+ tolerated pairs are both evaluated.
16
+ 3. A pair is a candidate when its full reasons contain
17
+ contract_dependency or it has a same-file overlap: an overlapping entry
18
+ pair, after the mergeable exclusion, of two equal concrete entries that
19
+ do not match append_only_paths.
20
+ 4. A candidate qualifies when
21
+ cost * 100 >= benefit * combination_threshold_percent.
22
+ 5. Qualifying pairs are grouped into connected components (union-find);
23
+ each becomes one combination with ascending members, primary equal to
24
+ the smallest member, pairs sorted by (a, b), and estimated_savings equal
25
+ to the sum of its pair costs.
26
+
27
+ Parity notes for maintainers:
28
+ - The Python module is the reference implementation; the committed
29
+ combination fixtures bind the two runtimes together.
30
+ - Every function is pure: no filesystem, subprocess, network, or clock
31
+ access, and no input is mutated.
32
+ CONVENTION: this module fails fast at module scope and imports its siblings with -ErrorAction Stop.
33
+ #>
34
+
35
+ Set-StrictMode -Version Latest
36
+ $ErrorActionPreference = 'Stop'
37
+
38
+ Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusGlob.psm1') -Force -ErrorAction Stop
39
+ Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusConflict.psm1') -Force -ErrorAction Stop
40
+ Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusValidation.psm1') -Force -ErrorAction Stop
41
+ Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusScheduling.psm1') -Force -ErrorAction Stop
42
+
43
+ # The threshold is a percentage of the pair benefit.
44
+ $script:Percent = 100
45
+ $script:ContractDependency = 'contract_dependency'
46
+
47
+ # Port of has_same_file_overlap: two equal, non-mergeable, non-append-only
48
+ # concrete entries among the overlapping pairs the relation enumerates.
49
+ function Test-SameFileOverlap {
50
+ [CmdletBinding()]
51
+ [OutputType([bool])]
52
+ param(
53
+ [Parameter(Mandatory = $true)]
54
+ [AllowNull()]
55
+ [object] $RadiusA,
56
+ [Parameter(Mandatory = $true)]
57
+ [AllowNull()]
58
+ [object] $RadiusB,
59
+ [Parameter(Mandatory = $true)]
60
+ [AllowNull()]
61
+ [object] $Config,
62
+ [Parameter(Mandatory = $true)]
63
+ [hashtable] $Tolerance
64
+ )
65
+
66
+ $left = ConvertTo-NormalizedBlastRadius -Radius $RadiusA
67
+ $right = ConvertTo-NormalizedBlastRadius -Radius $RadiusB
68
+ $mergeable = [string[]]@(Get-ConfigMergeablePath -Config $Config)
69
+ $pathsA = @(Get-NonMergeablePathEntry -Entry ([string[]]@($left['paths'])) -MergeablePath $mergeable)
70
+ $pathsB = @(Get-NonMergeablePathEntry -Entry ([string[]]@($right['paths'])) -MergeablePath $mergeable)
71
+ $appendOnly = [string[]]@($Tolerance['append_only_paths'])
72
+ foreach ($pair in @(Get-OverlappingPathPair -PathA $pathsA -PathB $pathsB)) {
73
+ $entry = [string]$pair['EntryA']
74
+ $isEqual = [string]::Equals($entry, [string]$pair['EntryB'], [System.StringComparison]::Ordinal)
75
+ if ($isEqual -and -not (Test-GlobEntry -Entry $entry) -and -not (Test-MergeablePath -Entry $entry -MergeablePath $appendOnly)) {
76
+ return $true
77
+ }
78
+ }
79
+ return $false
80
+ }
81
+
82
+ # Validate item keys (distinct integers) and return records sorted by key.
83
+ function Get-CombinationOrderedItem {
84
+ [CmdletBinding()]
85
+ [OutputType([System.Object[]])]
86
+ param(
87
+ [Parameter(Mandatory = $true)]
88
+ [AllowEmptyCollection()]
89
+ [object[]] $Item
90
+ )
91
+
92
+ $seen = [System.Collections.Generic.HashSet[long]]::new()
93
+ $record = foreach ($entry in $Item) {
94
+ $key = [long]$entry['key']
95
+ if (-not $seen.Add($key)) {
96
+ throw "combination item keys must be distinct: $key."
97
+ }
98
+ $band = if ($entry.Contains('band')) { $entry['band'] } else { $null }
99
+ @{ key = $key; radius = $entry['radius']; band = $band }
100
+ }
101
+ return @(@($record) | Where-Object { $null -ne $_ } | Sort-Object -Property { $_['key'] })
102
+ }
103
+
104
+ # Return the union-find root of Key, registering Key as its own root when new.
105
+ # Parent is the component's working map, owned by Get-CombinationComponent.
106
+ function Get-UnionFindRoot {
107
+ [CmdletBinding()]
108
+ [OutputType([long])]
109
+ param(
110
+ [Parameter(Mandatory = $true)]
111
+ [hashtable] $Parent,
112
+ [Parameter(Mandatory = $true)]
113
+ [long] $Key
114
+ )
115
+
116
+ if (-not $Parent.ContainsKey($Key)) { $Parent[$Key] = $Key }
117
+ $root = $Key
118
+ while ($Parent[$root] -ne $root) { $root = $Parent[$root] }
119
+ return $root
120
+ }
121
+
122
+ # Group qualifying pairs into connected components with union-find.
123
+ function Get-CombinationComponent {
124
+ [CmdletBinding()]
125
+ [OutputType([System.Object[]])]
126
+ param(
127
+ [Parameter(Mandatory = $true)]
128
+ [AllowEmptyCollection()]
129
+ [object[]] $Pair
130
+ )
131
+
132
+ $parent = @{}
133
+ foreach ($entry in $Pair) {
134
+ $rootA = Get-UnionFindRoot -Parent $parent -Key $entry['a']
135
+ $rootB = Get-UnionFindRoot -Parent $parent -Key $entry['b']
136
+ if ($rootA -ne $rootB) {
137
+ $parent[[System.Math]::Max($rootA, $rootB)] = [System.Math]::Min($rootA, $rootB)
138
+ }
139
+ }
140
+
141
+ $grouped = @{}
142
+ foreach ($entry in $Pair) {
143
+ $root = Get-UnionFindRoot -Parent $parent -Key $entry['a']
144
+ if (-not $grouped.ContainsKey($root)) { $grouped[$root] = [System.Collections.Generic.List[object]]::new() }
145
+ $grouped[$root].Add($entry)
146
+ }
147
+ $combination = foreach ($root in @($grouped.Keys | Sort-Object)) {
148
+ $component = @($grouped[$root].ToArray() | Sort-Object -Property { $_['a'] }, { $_['b'] })
149
+ [long[]]$member = @($component | ForEach-Object { $_['a']; $_['b'] } | Sort-Object -Unique)
150
+ [long]$savings = 0
151
+ foreach ($entry in $component) { $savings += $entry['cost'] }
152
+ [ordered]@{ members = $member; primary = $member[0]; pairs = $component; estimated_savings = $savings }
153
+ }
154
+ return @($combination)
155
+ }
156
+
157
+ function Get-BlastRadiusCombination {
158
+ <#
159
+ .SYNOPSIS
160
+ Find the qualifying pairs of a set of items and group them.
161
+
162
+ .DESCRIPTION
163
+ Port of find_combinations. Visits every unordered pair once in ascending
164
+ key order and applies D-5 rules 1 to 5.
165
+
166
+ .PARAMETER Item
167
+ The run's items: records carrying key (an integer issue number), radius,
168
+ and an optional band.
169
+
170
+ .PARAMETER Config
171
+ Parsed truth table.
172
+
173
+ .PARAMETER Relation
174
+ The detection relation passed to every pair decision; pass
175
+ ${function:Test-BlastRadiusConflict}.
176
+
177
+ .OUTPUTS
178
+ System.Collections.Hashtable. Keys pairs (ordered records a, b, cost,
179
+ benefit, sorted by (a, b)) and combinations (ordered records members,
180
+ primary, pairs, estimated_savings, sorted by primary). Both are empty
181
+ when combination is disabled.
182
+ #>
183
+ [CmdletBinding()]
184
+ [OutputType([hashtable])]
185
+ param(
186
+ [Parameter(Mandatory = $true)]
187
+ [AllowEmptyCollection()]
188
+ [object[]] $Item,
189
+ [Parameter(Mandatory = $true)]
190
+ [AllowNull()]
191
+ [object] $Config,
192
+ [scriptblock] $Relation
193
+ )
194
+
195
+ if ($null -eq $Relation) {
196
+ throw '-Relation is required: pass ${function:Test-BlastRadiusConflict} from the facade module BlastRadius.psm1.'
197
+ }
198
+ $tolerance = Get-ConfigConflictTolerance -Config $Config
199
+ $ordered = @(Get-CombinationOrderedItem -Item $Item)
200
+ # The absent key reads as the strict tolerance, whose percent is 0.
201
+ if ([long]$tolerance['tolerance_percent'] -eq 0) {
202
+ return @{ pairs = @(); combinations = @() }
203
+ }
204
+
205
+ $threshold = [long]$tolerance['combination_threshold_percent']
206
+ $qualifying = [System.Collections.Generic.List[object]]::new()
207
+ for ($first = 0; $first -lt $ordered.Count; $first++) {
208
+ for ($second = $first + 1; $second -lt $ordered.Count; $second++) {
209
+ $a = $ordered[$first]
210
+ $b = $ordered[$second]
211
+ $decision = Get-BlastRadiusPairDecision -RadiusA $a['radius'] -RadiusB $b['radius'] -Config $Config -BandA $a['band'] -BandB $b['band'] -Relation $Relation
212
+ if (-not $decision['conflict']) { continue }
213
+ # The full reasons are read, because contract_dependency is never first.
214
+ $isCandidate = @($decision['reasons']) -ccontains $script:ContractDependency
215
+ if (-not $isCandidate) {
216
+ $isCandidate = Test-SameFileOverlap -RadiusA $a['radius'] -RadiusB $b['radius'] -Config $Config -Tolerance $tolerance
217
+ }
218
+ if ($isCandidate -and ($decision['cost'] * $script:Percent -ge $decision['benefit'] * $threshold)) {
219
+ $qualifying.Add([ordered]@{ a = $a['key']; b = $b['key']; cost = [long]$decision['cost']; benefit = [long]$decision['benefit'] })
220
+ }
221
+ }
222
+ }
223
+
224
+ $pair = @($qualifying.ToArray())
225
+ return @{ pairs = $pair; combinations = @(Get-CombinationComponent -Pair $pair) }
226
+ }
227
+
228
+ Export-ModuleMember -Function Get-BlastRadiusCombination
@@ -459,6 +459,7 @@ Export-ModuleMember -Function `
459
459
  Test-PlaceholderMarker, `
460
460
  Test-MultipleFeatureFolderSpan, `
461
461
  Test-FileShapedComponent, `
462
+ Test-GenericContractToken, `
462
463
  Get-PathTokenKind, `
463
464
  Get-PathFromLine, `
464
465
  Get-PlanPaths
@@ -120,10 +120,12 @@ function Get-ContractIdentifier {
120
120
  # Inside a qualifying section an inline-code token without a separator is
121
121
  # a contract identifier; a token with one is a path reference and is
122
122
  # recorded at the paths level instead. A token carrying no ASCII letter
123
- # is notation, not an identifier, and is dropped (issue #489).
123
+ # is notation, not an identifier, and is dropped (issue #489), as is a
124
+ # default spreadsheet sheet-tab name such as Sheet1 (issue #1006).
124
125
  foreach ($token in @(Get-InlineCodeToken -Line $line)) {
125
126
  if ($token.IndexOf('/') -lt 0 -and
126
- $script:ContractLetterPattern.IsMatch($token)) {
127
+ $script:ContractLetterPattern.IsMatch($token) -and
128
+ -not (Test-GenericContractToken -Token $token)) {
127
129
  $identifier.Add($token)
128
130
  }
129
131
  }
@@ -38,6 +38,7 @@ Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusGlob.psm1')
38
38
  Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusConfig.psm1') -Force -ErrorAction Stop
39
39
  Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusConflict.psm1') -Force -ErrorAction Stop
40
40
  Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusValidation.psm1') -Force -ErrorAction Stop
41
+ Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusAggregate.psm1') -Force -ErrorAction Stop
41
42
 
42
43
  # Truth-table key and the label every reader error carries.
43
44
  $script:ToleranceKey = 'conflict_tolerance'
@@ -46,9 +47,15 @@ $script:ToleranceLabel = 'config["conflict_tolerance"]'
46
47
  # Member names of the key and of its two nested maps. Each must be carried
47
48
  # exactly, so a misspelled name fails fast instead of reading as absent.
48
49
  $script:MemberName = @('tolerance_percent', 'weights', 'band_durations', 'default_band', 'append_only_paths')
49
- $script:WeightName = @('same_file', 'possible_overlap', 'append_only', 'module')
50
+ $script:WeightName = @('same_file', 'possible_overlap', 'append_only', 'module', 'contract')
50
51
  $script:BandName = @('C1', 'C2', 'C3', 'C4')
51
52
 
53
+ # The one optional member (issue #1013): the issue-combination threshold, read
54
+ # as this default when absent. Pinned to COMBINATION_THRESHOLD_DEFAULT in the
55
+ # Python reference by a Pester parity row.
56
+ $script:CombinationThresholdName = 'combination_threshold_percent'
57
+ $script:CombinationThresholdDefault = 400
58
+
52
59
  # Reason kinds that make a conflict an edge at every tolerance: a shared surface
53
60
  # or a contract dependency cannot be reconciled by a merge step.
54
61
  $script:HardReasonKind = @('shared_surface_overlap', 'contract_dependency')
@@ -140,15 +147,18 @@ function Get-ConfigConflictTolerance {
140
147
  .DESCRIPTION
141
148
  Port of config_conflict_tolerance. An absent or null key returns the
142
149
  strict semantics: tolerance 0, every weight 1, every band duration 1,
143
- default_band C1, and no append-only paths.
150
+ default_band C1, no append-only paths, and the default combination
151
+ threshold. combination_threshold_percent is optional: when present it
152
+ must be an integer of at least 0, and when absent it reads as 400.
144
153
 
145
154
  .PARAMETER Config
146
155
  Parsed config/blast-radius.json.
147
156
 
148
157
  .OUTPUTS
149
158
  System.Collections.Hashtable. Keys tolerance_percent, weights,
150
- band_durations, default_band, and append_only_paths. Every error message
151
- names the conflict_tolerance key.
159
+ band_durations, default_band, append_only_paths, and
160
+ combination_threshold_percent. Every error message names the
161
+ conflict_tolerance key.
152
162
  #>
153
163
  [CmdletBinding()]
154
164
  [OutputType([hashtable])]
@@ -165,22 +175,32 @@ function Get-ConfigConflictTolerance {
165
175
  foreach ($entry in $script:WeightName) { $unit[$entry] = [long]1 }
166
176
  $band = @{}
167
177
  foreach ($entry in $script:BandName) { $band[$entry] = [long]1 }
168
- return @{ tolerance_percent = [long]0; weights = $unit; band_durations = $band; default_band = $script:BandName[0]; append_only_paths = [string[]]@() }
178
+ return @{ tolerance_percent = [long]0; weights = $unit; band_durations = $band; default_band = $script:BandName[0]; append_only_paths = [string[]]@(); combination_threshold_percent = [long]$script:CombinationThresholdDefault }
169
179
  }
170
180
 
171
181
  $member = Get-RequiredMapping -Value $value -FieldName $script:ToleranceLabel
172
- Assert-ExactMemberName -Mapping $member -Name $script:MemberName -FieldName $script:ToleranceLabel
182
+ # The optional member joins the exact name set only when it is present, so
183
+ # every other unknown name is still rejected.
184
+ $hasThreshold = $member.ContainsKey($script:CombinationThresholdName)
185
+ $names = if ($hasThreshold) { @($script:MemberName) + $script:CombinationThresholdName } else { $script:MemberName }
186
+ Assert-ExactMemberName -Mapping $member -Name $names -FieldName $script:ToleranceLabel
173
187
  $defaultBand = $member['default_band']
174
188
  if ($defaultBand -isnot [string] -or $script:BandName -cnotcontains $defaultBand) {
175
189
  throw "$script:ToleranceLabel[""default_band""] must be one of $($script:BandName -join ', ')."
176
190
  }
177
191
 
192
+ $threshold = [long]$script:CombinationThresholdDefault
193
+ if ($hasThreshold) {
194
+ $threshold = Get-RequiredInteger -Value $member[$script:CombinationThresholdName] -FieldName "$script:ToleranceLabel[""$script:CombinationThresholdName""]" -Minimum 0
195
+ }
196
+
178
197
  return @{
179
- tolerance_percent = Get-RequiredInteger -Value $member['tolerance_percent'] -FieldName "$script:ToleranceLabel[""tolerance_percent""]" -Minimum 0
180
- weights = Get-RequiredIntegerMap -Value $member['weights'] -Name $script:WeightName -Member 'weights'
181
- band_durations = Get-RequiredIntegerMap -Value $member['band_durations'] -Name $script:BandName -Member 'band_durations'
182
- default_band = [string]$defaultBand
183
- append_only_paths = [string[]]@(Get-RequiredStringList -Value $member['append_only_paths'] -FieldName "$script:ToleranceLabel[""append_only_paths""]")
198
+ tolerance_percent = Get-RequiredInteger -Value $member['tolerance_percent'] -FieldName "$script:ToleranceLabel[""tolerance_percent""]" -Minimum 0
199
+ weights = Get-RequiredIntegerMap -Value $member['weights'] -Name $script:WeightName -Member 'weights'
200
+ band_durations = Get-RequiredIntegerMap -Value $member['band_durations'] -Name $script:BandName -Member 'band_durations'
201
+ default_band = [string]$defaultBand
202
+ append_only_paths = [string[]]@(Get-RequiredStringList -Value $member['append_only_paths'] -FieldName "$script:ToleranceLabel[""append_only_paths""]")
203
+ combination_threshold_percent = $threshold
184
204
  }
185
205
  }
186
206
 
@@ -221,7 +241,10 @@ function Get-BlastRadiusPairCost {
221
241
  .DESCRIPTION
222
242
  Port of pair_cost. Sums the weight of every overlapping path pair left
223
243
  after the mergeable exclusion, then adds the module weight times the
224
- number of shared modules. Mergeable paths therefore contribute 0.
244
+ number of shared modules and the contract weight times the number of
245
+ distinct shared contract identifiers (the ordinal intersection the
246
+ relation reads for contract_dependency, each identifier counted once).
247
+ Mergeable paths therefore contribute 0.
225
248
 
226
249
  .PARAMETER RadiusA
227
250
  First radius record.
@@ -269,7 +292,10 @@ function Get-BlastRadiusPairCost {
269
292
  $cost += Get-PathPairWeight -EntryA $pair['EntryA'] -EntryB $pair['EntryB'] -Tolerance $Tolerance
270
293
  }
271
294
  $sharedModule = @(@($left['modules']) | Where-Object { @($right['modules']) -ccontains $_ })
272
- return $cost + ([long]$Tolerance['weights']['module'] * $sharedModule.Count)
295
+ # Distinct shared contract identifiers, compared ordinally like the relation.
296
+ $sharedContract = [System.Collections.Generic.HashSet[string]]::new([string[]]@($left['contracts']), [StringComparer]::Ordinal)
297
+ $sharedContract.IntersectWith([string[]]@($right['contracts']))
298
+ return $cost + ([long]$Tolerance['weights']['module'] * $sharedModule.Count) + ([long]$Tolerance['weights']['contract'] * $sharedContract.Count)
273
299
  }
274
300
 
275
301
  function Get-BlastRadiusPairBenefit {
@@ -423,7 +449,9 @@ function Get-BlastRadiusConflictEdge {
423
449
  Port of schedule_conflict_edges. Visits every unordered pair once in
424
450
  ascending key order. A pair whose decision is an edge is recorded as an
425
451
  edge; a conflict within tolerance is recorded as a tolerated overlap; a
426
- pair that does not conflict appears in neither list.
452
+ pair that does not conflict appears in neither list. The aggregate cap
453
+ of BlastRadiusAggregate.psm1 (issue #1013) then promotes tolerated
454
+ overlaps until every item is within its cap.
427
455
 
428
456
  .PARAMETER Item
429
457
  The run's items: records carrying key (an integer issue number), radius,
@@ -454,7 +482,7 @@ function Get-BlastRadiusConflictEdge {
454
482
  )
455
483
 
456
484
  if ($null -eq $Relation) { throw $script:RelationRequired }
457
- [void](Get-ConfigConflictTolerance -Config $Config)
485
+ $tolerance = Get-ConfigConflictTolerance -Config $Config
458
486
  $ordered = @(Get-OrderedSchedulingItem -Item $Item)
459
487
 
460
488
  $edge = [System.Collections.Generic.List[object]]::new()
@@ -472,7 +500,26 @@ function Get-BlastRadiusConflictEdge {
472
500
  }
473
501
  }
474
502
 
475
- return @{ edges = @($edge.ToArray()); tolerated_overlaps = @($tolerated.ToArray()) }
503
+ # Aggregate cap post-pass (issue #1013, D-2): promote each cap-selected
504
+ # tolerated overlap to a non-hard edge carrying its first reason, then
505
+ # re-sort both lists by (a, b). At tolerance 0 nothing is tolerated.
506
+ $band = @{}
507
+ foreach ($entry in $ordered) { $band[$entry['key']] = $entry['band'] }
508
+ $promoted = [System.Collections.Generic.HashSet[string]]::new()
509
+ foreach ($pair in @(Get-AggregateCappedPair -ToleratedOverlap @($tolerated.ToArray()) -Band $band -Tolerance $tolerance)) {
510
+ [void]$promoted.Add(('{0}-{1}' -f $pair['a'], $pair['b']))
511
+ }
512
+ $kept = [System.Collections.Generic.List[object]]::new()
513
+ foreach ($overlap in $tolerated) {
514
+ if ($promoted.Contains(('{0}-{1}' -f $overlap['a'], $overlap['b']))) {
515
+ $edge.Add([ordered]@{ a = $overlap['a']; b = $overlap['b']; reason = @($overlap['reasons'])[0]; hard = $false; cost = $overlap['cost']; benefit = $overlap['benefit'] })
516
+ } else {
517
+ $kept.Add($overlap)
518
+ }
519
+ }
520
+ $sortedEdge = @($edge.ToArray() | Sort-Object -Property { $_['a'] }, { $_['b'] })
521
+
522
+ return @{ edges = $sortedEdge; tolerated_overlaps = @($kept.ToArray()) }
476
523
  }
477
524
 
478
525
  Export-ModuleMember -Function `
@@ -55,6 +55,12 @@
55
55
  from the Python source and pins them equal. A non-ASCII extension is
56
56
  rejected before lower-casing (issue #903); ToLowerInvariant then matches
57
57
  Python's str.lower on ASCII input, and known-name membership is ordinal.
58
+ - Test-GenericContractToken (issue #1006) ports is_generic_contract_token.
59
+ Its stem array equals GENERIC_CONTRACT_STEMS; a Pester parity test reads
60
+ the Python constant from the source and pins $script:GenericContractStem
61
+ equal to it. A token is first checked ordinally to be ASCII, because a
62
+ .NET case-insensitive match folds the Kelvin sign and the long s to
63
+ ASCII letters while Python re.ASCII does not (the issue #903 precedent).
58
64
  CONVENTION: this module fails fast at module scope and imports its siblings with -ErrorAction Stop.
59
65
  #>
60
66
 
@@ -114,6 +120,20 @@ $script:KnownFileName = [System.Collections.Generic.HashSet[string]]::new(
114
120
  ),
115
121
  [StringComparer]::Ordinal)
116
122
 
123
+ # Default spreadsheet sheet-tab stems (issue #1006). A spreadsheet application
124
+ # names a new worksheet or chart sheet with one of these stems followed by a
125
+ # number, so a spec that mentions Sheet1 names a worksheet, not a contract. The
126
+ # array is closed and is pinned equal to GENERIC_CONTRACT_STEMS in the Python
127
+ # reference by a Pester parity test, so edit both files together. The pattern is
128
+ # anchored with \A and \z to match Python's re.fullmatch, and the ASCII pattern
129
+ # is applied first with -cmatch so the comparison is ordinal.
130
+ $script:GenericContractStem = [string[]]@('Sheet', 'Chart')
131
+ $script:GenericContractPattern = [regex]::new(
132
+ '\A(?:' + ($script:GenericContractStem -join '|') + ')[0-9]+\z',
133
+ [System.Text.RegularExpressions.RegexOptions]::IgnoreCase -bor
134
+ [System.Text.RegularExpressions.RegexOptions]::CultureInvariant)
135
+ $script:AsciiOnlyPattern = '\A[\x00-\x7F]*\z'
136
+
117
137
  function Test-PlaceholderMarker {
118
138
  <#
119
139
  .SYNOPSIS
@@ -263,7 +283,42 @@ function Test-FileShapedComponent {
263
283
  return $script:FileExtensionPattern.IsMatch($extension.ToLowerInvariant())
264
284
  }
265
285
 
286
+ function Test-GenericContractToken {
287
+ <#
288
+ .SYNOPSIS
289
+ Report whether a contract token is a default sheet-tab name (issue #1006).
290
+
291
+ .DESCRIPTION
292
+ Port of is_generic_contract_token. Two unrelated work items whose specs
293
+ both named the worksheet Sheet1 in an interface section were given a
294
+ hard contract_dependency edge, because the contract harvest accepts any
295
+ separator-free token carrying a letter. A default sheet-tab name
296
+ identifies no exported symbol, schema, or CLI identifier, so every
297
+ contract-filtering site rejects it with this predicate.
298
+
299
+ .PARAMETER Token
300
+ One candidate contract identifier. The empty string is accepted and
301
+ reports false.
302
+
303
+ .OUTPUTS
304
+ System.Boolean. True only when the token is ASCII and fully matches a
305
+ stem of $script:GenericContractStem followed by one or more ASCII
306
+ digits, compared case-insensitively; otherwise false.
307
+ #>
308
+ [CmdletBinding()]
309
+ [OutputType([bool])]
310
+ param(
311
+ [Parameter(Mandatory = $true)]
312
+ [AllowEmptyString()]
313
+ [string] $Token
314
+ )
315
+
316
+ if ($Token -cnotmatch $script:AsciiOnlyPattern) { return $false }
317
+ return $script:GenericContractPattern.IsMatch($Token)
318
+ }
319
+
266
320
  Export-ModuleMember -Function `
267
321
  Test-PlaceholderMarker, `
268
322
  Test-MultipleFeatureFolderSpan, `
269
- Test-FileShapedComponent
323
+ Test-FileShapedComponent, `
324
+ Test-GenericContractToken
@@ -343,9 +343,12 @@ function Get-WriteIntentSpecContract {
343
343
  continue
344
344
  }
345
345
 
346
+ # A default spreadsheet sheet-tab name such as Sheet1 is not a contract
347
+ # (issue #1006).
346
348
  foreach ($token in @(Get-SingleWordToken -Line $line)) {
347
349
  if ($token.IndexOf('/') -lt 0 -and $token.IndexOf('*') -lt 0 -and
348
- $token.IndexOf('?') -lt 0 -and $script:ContractLetterPattern.IsMatch($token)) {
350
+ $token.IndexOf('?') -lt 0 -and $script:ContractLetterPattern.IsMatch($token) -and
351
+ -not (Test-GenericContractToken -Token $token)) {
349
352
  $identifier.Add($token)
350
353
  }
351
354
  }
@@ -24,8 +24,8 @@
24
24
  throwing.
25
25
 
26
26
  .NOTES
27
- Compatible with PowerShell 7+. No external module dependencies, no subprocess,
28
- and no network. The single filesystem read and the single wall-clock read each
27
+ Compatible with PowerShell 7+. Imports only the in-repository sibling
28
+ WorktreeRunRecordPath.psm1 (issue #995); no subprocess and no network. The single filesystem read and the single wall-clock read each
29
29
  sit behind an injectable seam so tests drive them without writing a temporary
30
30
  file. Mirrored byte-identically under
31
31
  extensions/drm-copilot/resources/claude-customizations/.
@@ -35,6 +35,9 @@
35
35
  Set-StrictMode -Version Latest
36
36
  $ErrorActionPreference = 'Stop'
37
37
 
38
+ # The shared recorded-path matcher (issue #995), used by the checkpoint-coverage test.
39
+ Import-Module (Join-Path $PSScriptRoot '../worktree-resolution/WorktreeRunRecordPath.psm1') -ErrorAction Stop
40
+
38
41
  # Repo-relative location of the sanctioned-removal manifest. Kept as a script-scope
39
42
  # constant so the read seam is the only function that names the path.
40
43
  $script:CleanupWorktreeManifestPath = 'artifacts/orchestration/cleanup-worktrees-manifest.json'
@@ -355,6 +358,14 @@ function Test-CleanupManifestCheckpointCoversPath {
355
358
  the gate's existing deny. Reusing the gates' merge_status predicate here
356
359
  would reopen the one path by which the manifest could widen what the gates
357
360
  protect.
361
+
362
+ Case rule: a record covers the target when the shared matcher holds on the
363
+ inputs as given, or holds on the same inputs lower-cased with the invariant
364
+ culture. This keeps the exclusion at parity with
365
+ Find-CleanupWorktreeManifestRemovalRecord, which ignores case for every path,
366
+ so a record that differs from the target only by case still blocks the
367
+ manifest branch. The shared matcher itself stays ordinal for single-slash
368
+ POSIX paths because the gates' allow lookups must remain fail-closed.
358
369
  .PARAMETER Checkpoint
359
370
  Parsed checkpoint object, or $null when absent or unreadable.
360
371
  .PARAMETER RecordArrayName
@@ -362,6 +373,10 @@ function Test-CleanupManifestCheckpointCoversPath {
362
373
  for the parallel checkpoint.
363
374
  .PARAMETER WorktreePath
364
375
  The removal target extracted from the command text.
376
+ .PARAMETER BaseRoot
377
+ Optional. The roots a relative recorded worktree_path is joined to: the main
378
+ checkout root and the root that holds the checkpoint (issue #995). With none, a
379
+ relative record covers nothing and a rooted record compares as before.
365
380
  .OUTPUTS
366
381
  System.Boolean
367
382
  #>
@@ -377,7 +392,11 @@ function Test-CleanupManifestCheckpointCoversPath {
377
392
 
378
393
  [AllowNull()]
379
394
  [AllowEmptyString()]
380
- [string] $WorktreePath
395
+ [string] $WorktreePath,
396
+
397
+ [AllowNull()]
398
+ [AllowEmptyCollection()]
399
+ [string[]] $BaseRoot = @()
381
400
  )
382
401
 
383
402
  if ($null -eq $Checkpoint -or [string]::IsNullOrWhiteSpace($WorktreePath)) {
@@ -388,8 +407,10 @@ function Test-CleanupManifestCheckpointCoversPath {
388
407
  return $false
389
408
  }
390
409
 
391
- $normalizedTarget = ConvertTo-CleanupWorktreeManifestNormalizedPath -Path $WorktreePath
410
+ $lowerBaseRoot = [string[]] @(@($BaseRoot) | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | ForEach-Object { $_.ToLowerInvariant() })
392
411
 
412
+ # Every record is compared through the shared matcher, so a relative record covers
413
+ # the absolute target it names under a base root, and an unsafe one covers nothing.
393
414
  foreach ($record in @($Checkpoint.PSObject.Properties[$RecordArrayName].Value)) {
394
415
  if ($null -eq $record) {
395
416
  continue
@@ -398,8 +419,14 @@ function Test-CleanupManifestCheckpointCoversPath {
398
419
  if ($recordProperties -notcontains 'worktree_path') {
399
420
  continue
400
421
  }
401
- $normalizedRecordPath = ConvertTo-CleanupWorktreeManifestNormalizedPath -Path ([string]$record.worktree_path)
402
- if ($normalizedRecordPath -eq $normalizedTarget) {
422
+ $recordedPath = [string]$record.worktree_path
423
+ if (Test-WorktreeRunRecordedPathMatchesTarget -RecordedPath $recordedPath -TargetPath $WorktreePath -BaseRoot $BaseRoot) {
424
+ return $true
425
+ }
426
+ # Case-insensitive parity with Find-CleanupWorktreeManifestRemovalRecord: the same
427
+ # inputs lower-cased with the invariant culture, so the exclusion is never narrower
428
+ # than the manifest lookup it guards.
429
+ if (Test-WorktreeRunRecordedPathMatchesTarget -RecordedPath $recordedPath.ToLowerInvariant() -TargetPath $WorktreePath.ToLowerInvariant() -BaseRoot $lowerBaseRoot) {
403
430
  return $true
404
431
  }
405
432
  }
@@ -75,7 +75,11 @@ $script:GENERATED_AGENT_FAMILIES = @(
75
75
  'python-typed-engineer',
76
76
  'powershell-typed-engineer',
77
77
  'csharp-typed-engineer',
78
- 'typescript-engineer'
78
+ 'typescript-engineer',
79
+ 'legacy-parity-analyst',
80
+ 'runtime-characterization-analyst',
81
+ 'requirements-reconciler',
82
+ 'migration-coverage-reviewer'
79
83
  )
80
84
  $script:LOGICAL_AGENT_ALIASES = @{ 'feature-review' = 'feature-reviewer' }
81
85