@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,146 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Adopted feature-folder probe for the orchestrator SubagentStop hook validate-orchestrator-output.ps1 (issue #992).
4
+
5
+ .DESCRIPTION
6
+ Dot-sourced by validate-orchestrator-output.ps1 through a guarded load whose catch records the
7
+ failure with Add-HookDependencyFailure, so a missing or broken copy of this file blocks the hook
8
+ instead of failing open. It defines Invoke-FeatureFolderGitExe, the single git seam, and
9
+ Get-OrchestratorOutputFeatureFolderDecision.
10
+
11
+ When an orchestrator-state checkpoint waives new_active_feature_folder through
12
+ issue_adoption.waived_tools, the validators accept a declared feature_folder_record but cannot
13
+ read the repository. This probe confirms that HEAD of the run worktree holds a tree at the
14
+ checkpoint feature-folder, so a staged-only, untracked, or absent folder blocks. It proves only
15
+ that a tree exists at that path at stop time; it does not prove which tool created the folder
16
+ or that its contents are correct.
17
+
18
+ The file imports nothing. Test-OrchestratorStateFeatureFolderPath comes from
19
+ OrchestratorStateFeatureFolderRecord.psm1, which the main hook imports through its own guarded
20
+ load. The file invokes no Python.
21
+ #>
22
+
23
+ $script:FeatureFolderProbeTool = 'new_active_feature_folder'
24
+
25
+ function Invoke-FeatureFolderGitExe {
26
+ <#
27
+ .SYNOPSIS
28
+ Run git with the given arguments. The single executable seam of the feature-folder probe.
29
+ .DESCRIPTION
30
+ Never throws: a git that cannot start, or an invoker that throws, returns ExitCode -1 so the
31
+ caller blocks instead of failing open. The default invoker merges standard error into Output;
32
+ success requires the exact output tree, so error text is never read as success.
33
+ .PARAMETER GitArgs
34
+ The git arguments.
35
+ .PARAMETER GitInvoker
36
+ The scriptblock that runs git; a unit test passes a test-local stand-in that sets
37
+ $global:LASTEXITCODE, so this body runs without starting a process.
38
+ .OUTPUTS
39
+ System.Collections.Hashtable with keys ExitCode (int) and Output (string, trimmed).
40
+ #>
41
+ [CmdletBinding()]
42
+ [OutputType([hashtable])]
43
+ param(
44
+ [Parameter(Mandatory = $true)]
45
+ [string[]] $GitArgs,
46
+
47
+ [Parameter(Mandatory = $false)]
48
+ [ValidateNotNull()]
49
+ [scriptblock] $GitInvoker = { git @args 2>&1 }
50
+ )
51
+
52
+ try {
53
+ $lines = @(& $GitInvoker @GitArgs)
54
+ $code = $LASTEXITCODE
55
+ }
56
+ catch {
57
+ return @{ ExitCode = -1; Output = '' }
58
+ }
59
+ if ($null -eq $code) { $code = -1 }
60
+ return @{ ExitCode = [int]$code; Output = ((@($lines | ForEach-Object { [string]$_ }) -join "`n").Trim()) }
61
+ }
62
+
63
+ function Test-FeatureFolderProbeWaived {
64
+ <#
65
+ .SYNOPSIS
66
+ Report whether the checkpoint's issue_adoption.waived_tools lists new_active_feature_folder.
67
+ .PARAMETER Checkpoint
68
+ The parsed checkpoint object. May be $null.
69
+ .OUTPUTS
70
+ System.Boolean
71
+ #>
72
+ [CmdletBinding()]
73
+ [OutputType([bool])]
74
+ param(
75
+ [Parameter(Mandatory = $true)]
76
+ [AllowNull()]
77
+ [object] $Checkpoint
78
+ )
79
+
80
+ if ($Checkpoint -isnot [System.Management.Automation.PSCustomObject]) { return $false }
81
+ $adoptionProperty = $Checkpoint.PSObject.Properties['issue_adoption']
82
+ if ($null -eq $adoptionProperty -or $adoptionProperty.Value -isnot [System.Management.Automation.PSCustomObject]) { return $false }
83
+ $waivedProperty = $adoptionProperty.Value.PSObject.Properties['waived_tools']
84
+ if ($null -eq $waivedProperty -or $waivedProperty.Value -isnot [System.Array]) { return $false }
85
+ return (@($waivedProperty.Value | Where-Object { $_ -is [string] }) -ccontains $script:FeatureFolderProbeTool)
86
+ }
87
+
88
+ function Get-OrchestratorOutputFeatureFolderDecision {
89
+ <#
90
+ .SYNOPSIS
91
+ Confirm that HEAD of the run worktree holds a tree at the adopted feature-folder.
92
+ .DESCRIPTION
93
+ Returns @{ Ok = $true; Message = $null } when the checkpoint does not waive
94
+ new_active_feature_folder. Otherwise the checkpoint feature-folder is re-checked against the
95
+ shared path pattern before any git call (a failing path never reaches git), and
96
+ git -C <WorktreeRoot> cat-file -t HEAD:<feature-folder> must exit 0 and print exactly tree.
97
+ Every other outcome (non-zero exit, -1, empty output, other output) blocks with a repairable
98
+ ROUTING_CONTRACT_BLOCKED message naming the path.
99
+ .PARAMETER Checkpoint
100
+ The parsed checkpoint object. May be $null.
101
+ .PARAMETER WorktreeRoot
102
+ The root of the worktree whose run stopped.
103
+ .PARAMETER GitInvoker
104
+ Optional. Forwarded to Invoke-FeatureFolderGitExe; omitted, the seam's default runs git.
105
+ .OUTPUTS
106
+ System.Collections.Hashtable with keys Ok, Message, and (on a block) Repairable.
107
+ #>
108
+ [CmdletBinding()]
109
+ [OutputType([hashtable])]
110
+ param(
111
+ [Parameter(Mandatory = $true)]
112
+ [AllowNull()]
113
+ [object] $Checkpoint,
114
+
115
+ [Parameter(Mandatory = $true)]
116
+ [string] $WorktreeRoot,
117
+
118
+ [Parameter(Mandatory = $false)]
119
+ [scriptblock] $GitInvoker
120
+ )
121
+
122
+ if (-not (Test-FeatureFolderProbeWaived -Checkpoint $Checkpoint)) {
123
+ return @{ Ok = $true; Message = $null }
124
+ }
125
+
126
+ $folderProperty = $Checkpoint.PSObject.Properties['feature-folder']
127
+ $folder = if ($null -ne $folderProperty) { $folderProperty.Value } else { $null }
128
+ $blocked = @{ Ok = $false; Repairable = $true; Message = ('ROUTING_CONTRACT_BLOCKED: Checkpoint feature-folder is not committed in HEAD: {0}.' -f [string]$folder) }
129
+ # Defense in depth: the validators already require the record path to match the pattern and to
130
+ # equal feature-folder, but a value that fails the pattern must never become a git argument.
131
+ if (-not (Test-OrchestratorStateFeatureFolderPath -Value $folder)) {
132
+ return $blocked
133
+ }
134
+
135
+ $gitArgs = [string[]]@('-C', $WorktreeRoot, 'cat-file', '-t', ('HEAD:' + [string]$folder))
136
+ $probe = if ($PSBoundParameters.ContainsKey('GitInvoker') -and $null -ne $GitInvoker) {
137
+ Invoke-FeatureFolderGitExe -GitArgs $gitArgs -GitInvoker $GitInvoker
138
+ }
139
+ else {
140
+ Invoke-FeatureFolderGitExe -GitArgs $gitArgs
141
+ }
142
+ if (($probe.ExitCode -eq 0) -and [string]::Equals([string]$probe.Output, 'tree', [System.StringComparison]::Ordinal)) {
143
+ return @{ Ok = $true; Message = $null }
144
+ }
145
+ return $blocked
146
+ }
@@ -0,0 +1,172 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Parallel mutation rejection helpers for validate-orchestrator-output.ps1 (issue #1012).
4
+
5
+ .DESCRIPTION
6
+ Dot-sourced by validate-orchestrator-output.ps1. A parallel skill that rejects a mutation before
7
+ any run checkpoint exists stops without writing state and ends its final output with the line
8
+ PARALLEL_MUTATION_REJECTED: <code>. These helpers parse that signal, scan the live worktrees for
9
+ parallel checkpoint text that would contradict the claim that no state was written, decide
10
+ whether the unresolved parallel stop may be allowed, and compose the hint appended to the block
11
+ message when it may not.
12
+
13
+ The signal grammar, the closed code set, and the hook behavior are defined once in the section
14
+ `## Mutation Rejection Signal (issue #1012)` of .claude/rules/parallel-orchestration.md.
15
+
16
+ Imports no module, invokes no Python, and starts no process. Relies on
17
+ Find-WorktreeRunIdentitySignal, Get-WorktreeItemLiveRoot, Get-WorktreeRunCheckpointText, and
18
+ Get-WorktreeRunCheckpointPath, which the hook imports before it dot-sources this file. Reads no
19
+ file except through Get-WorktreeRunCheckpointText.
20
+ #>
21
+
22
+ # The closed rejection code set, in rule order. It mirrors the table of
23
+ # `## Mutation Rejection Signal (issue #1012)` in .claude/rules/parallel-orchestration.md, which owns
24
+ # the set; a Pester parity row pins this array to that table.
25
+ $script:ParallelMutationRejectionCodes = @('kickoff_artifact_missing', 'run_not_started', 'items_in_flight', 'unknown_item')
26
+ $script:ParallelMutationRejectionPrefix = 'PARALLEL_MUTATION_REJECTED:'
27
+ $script:ParallelMutationRejectionPattern = '^PARALLEL_MUTATION_REJECTED: (?<code>[a-z_]+)$'
28
+ $script:ParallelMutationRejectionHeading = '## Mutation Rejection Signal (issue #1012)'
29
+ $script:ParallelMutationRejectionArtifactType = 'parallel-orchestrator-state'
30
+
31
+ function Get-ParallelMutationRejectionCode {
32
+ <#
33
+ .SYNOPSIS
34
+ Return the code of a valid final-line rejection signal, or $null.
35
+ .DESCRIPTION
36
+ Pure. Only the last non-blank line of the output is considered, after trailing whitespace
37
+ (including a carriage return) is trimmed. The line must match
38
+ ^PARALLEL_MUTATION_REJECTED: (?<code>[a-z_]+)$ case-sensitively, and the code must be an
39
+ ordinal member of the closed code set. Any other form, including formatting or trailing
40
+ text, returns $null.
41
+ .PARAMETER AgentOutput
42
+ The agent's final output text.
43
+ #>
44
+ [CmdletBinding()]
45
+ [OutputType([string])]
46
+ param(
47
+ [Parameter(Mandatory = $true)] [AllowNull()] [AllowEmptyString()] [string] $AgentOutput
48
+ )
49
+
50
+ $trimmed = ([string]$AgentOutput).TrimEnd()
51
+ if ($trimmed.Length -eq 0) { return $null }
52
+ $lastLine = $trimmed.Substring($trimmed.LastIndexOf("`n") + 1)
53
+ $match = [regex]::Match($lastLine, $script:ParallelMutationRejectionPattern)
54
+ if (-not $match.Success) { return $null }
55
+ $code = $match.Groups['code'].Value
56
+ foreach ($member in $script:ParallelMutationRejectionCodes) {
57
+ if ([string]::Equals($member, $code, [System.StringComparison]::Ordinal)) { return $member }
58
+ }
59
+ return $null
60
+ }
61
+
62
+ function Test-ParallelRunStateAbsent {
63
+ <#
64
+ .SYNOPSIS
65
+ Return $true when no live worktree holds parallel checkpoint text that contradicts a no-state stop.
66
+ .DESCRIPTION
67
+ For every live root, the text at the canonical parallel checkpoint path must be null or blank,
68
+ or parse as a JSON object with route_id 'parallel' and a non-blank string parallel_slug that
69
+ differs (ordinally) from the parallel_slug: value the output names, when it names one. Any
70
+ other non-blank text (unparseable, a non-object root, off-route, or without a slug) and a
71
+ checkpoint recording the named slug return $false.
72
+ .PARAMETER AgentOutput
73
+ The agent's final output text, scanned for a parallel_slug: literal.
74
+ .PARAMETER SessionRoot
75
+ The calling process's path, used only to find the repository.
76
+ #>
77
+ [CmdletBinding()]
78
+ [OutputType([bool])]
79
+ param(
80
+ [Parameter(Mandatory = $true)] [AllowNull()] [AllowEmptyString()] [string] $AgentOutput,
81
+ [Parameter(Mandatory = $true)] [string] $SessionRoot
82
+ )
83
+
84
+ $namedSlug = (Find-WorktreeRunIdentitySignal -Text ([string]$AgentOutput)).ParallelSlug
85
+ # The seam returns its array as one object, so it is assigned before it is iterated.
86
+ $liveRoots = Get-WorktreeItemLiveRoot -SessionRoot $SessionRoot
87
+ foreach ($root in $liveRoots) {
88
+ if ([string]::IsNullOrWhiteSpace($root)) { continue }
89
+ $text = Get-WorktreeRunCheckpointText -Path (Get-WorktreeRunCheckpointPath -Kind 'parallel' -WorktreeRoot $root)
90
+ if ([string]::IsNullOrWhiteSpace($text)) { continue }
91
+ try { $parsed = ConvertFrom-Json -InputObject $text -NoEnumerate -ErrorAction Stop } catch { return $false }
92
+ if ($parsed -isnot [System.Management.Automation.PSCustomObject]) { return $false }
93
+ $names = @($parsed.PSObject.Properties.Name)
94
+ if (-not ($names -ccontains 'route_id') -or ([string]$parsed.route_id -cne 'parallel')) { return $false }
95
+ if (-not ($names -ccontains 'parallel_slug')) { return $false }
96
+ $slug = $parsed.parallel_slug
97
+ if ($slug -isnot [string] -or [string]::IsNullOrWhiteSpace($slug)) { return $false }
98
+ if (-not [string]::IsNullOrWhiteSpace($namedSlug) -and ($slug -ceq $namedSlug)) { return $false }
99
+ }
100
+ return $true
101
+ }
102
+
103
+ function Get-OrchestratorOutputRejectionDecision {
104
+ <#
105
+ .SYNOPSIS
106
+ Return the allow decision for an unresolved parallel stop that carries a valid rejection signal, or $null.
107
+ .DESCRIPTION
108
+ Returns @{ Ok = $true; Message = $null } only when every gate holds: the artifact type is
109
+ parallel-orchestrator-state, the resolution status is NoTarget, the final line is a valid
110
+ rejection signal, and the state-absence scan passes. Otherwise returns $null, and the caller
111
+ applies its existing block.
112
+ .PARAMETER ArtifactType
113
+ The artifact type the hook validates.
114
+ .PARAMETER Resolution
115
+ The unresolved result of Resolve-OrchestratorOutputCheckpointPath.
116
+ .PARAMETER AgentOutput
117
+ The agent's final output text.
118
+ .PARAMETER SessionRoot
119
+ The calling process's path, used only to find the repository.
120
+ #>
121
+ [CmdletBinding()]
122
+ [OutputType([hashtable])]
123
+ param(
124
+ [Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $ArtifactType,
125
+ [Parameter(Mandatory = $true)] [AllowNull()] [object] $Resolution,
126
+ [Parameter(Mandatory = $true)] [AllowNull()] [AllowEmptyString()] [string] $AgentOutput,
127
+ [Parameter(Mandatory = $true)] [string] $SessionRoot
128
+ )
129
+
130
+ if ($ArtifactType -cne $script:ParallelMutationRejectionArtifactType) { return $null }
131
+ if ($null -eq $Resolution -or [string]$Resolution.Status -cne 'NoTarget') { return $null }
132
+ if ($null -eq (Get-ParallelMutationRejectionCode -AgentOutput $AgentOutput)) { return $null }
133
+ if (-not (Test-ParallelRunStateAbsent -AgentOutput $AgentOutput -SessionRoot $SessionRoot)) { return $null }
134
+ return @{ Ok = $true; Message = $null }
135
+ }
136
+
137
+ function Get-ParallelMutationRejectionHint {
138
+ <#
139
+ .SYNOPSIS
140
+ Return the text appended to an unresolved block message.
141
+ .DESCRIPTION
142
+ Pure. Returns an empty string unless the artifact type is parallel-orchestrator-state and the
143
+ status is NoTarget. Otherwise returns one newline-prefixed hint line naming the signal form
144
+ and the rule heading and, when the last non-blank line begins with the signal prefix but
145
+ carries no valid code, a second line listing the allowed codes.
146
+ .PARAMETER ArtifactType
147
+ The artifact type the hook validates.
148
+ .PARAMETER Status
149
+ The resolution status of the block.
150
+ .PARAMETER AgentOutput
151
+ The agent's final output text.
152
+ #>
153
+ [CmdletBinding()]
154
+ [OutputType([string])]
155
+ param(
156
+ [Parameter(Mandatory = $true)] [AllowEmptyString()] [string] $ArtifactType,
157
+ [Parameter(Mandatory = $true)] [AllowNull()] [AllowEmptyString()] [string] $Status,
158
+ [Parameter(Mandatory = $true)] [AllowNull()] [AllowEmptyString()] [string] $AgentOutput
159
+ )
160
+
161
+ if ($ArtifactType -cne $script:ParallelMutationRejectionArtifactType -or $Status -cne 'NoTarget') { return '' }
162
+ $hint = ("`norchestrator hook: a parallel skill that stopped without writing state ends its final output with the line 'PARALLEL_MUTATION_REJECTED: <code>' as the last line, with no formatting; see '{0}' in .claude/rules/parallel-orchestration.md." -f
163
+ $script:ParallelMutationRejectionHeading)
164
+ $trimmed = ([string]$AgentOutput).TrimEnd()
165
+ $lastLine = $trimmed.Substring($trimmed.LastIndexOf("`n") + 1)
166
+ if ($lastLine.StartsWith($script:ParallelMutationRejectionPrefix, [System.StringComparison]::Ordinal) -and
167
+ $null -eq (Get-ParallelMutationRejectionCode -AgentOutput $AgentOutput)) {
168
+ $hint += ("`norchestrator hook: the final line carries the {0} prefix with an invalid code; allowed codes: {1}." -f
169
+ $script:ParallelMutationRejectionPrefix, ($script:ParallelMutationRejectionCodes -join ', '))
170
+ }
171
+ return $hint
172
+ }
@@ -25,7 +25,9 @@
25
25
  ambiguous, or mismatched target blocks with ORCHESTRATOR_CHECKPOINT_UNRESOLVED:
26
26
  before any checkpoint is read. For epic-orchestrator-state, the Layer 2 wave-barrier
27
27
  ordering check (OrchestratorStateEpicWaveBarrier.psm1, issue #840) runs after the
28
- routing dispatch passes.
28
+ routing dispatch passes. For orchestrator-state, the adopted feature-folder probe
29
+ (validate-orchestrator-output-feature-folder.ps1, issue #992) runs after the routing
30
+ dispatch passes, and only when the checkpoint waives new_active_feature_folder.
29
31
 
30
32
  .NOTES
31
33
  Reads the SubagentStop envelope from stdin through Read-SubagentStopEnvelope
@@ -55,12 +57,17 @@ Set-StrictMode -Version Latest
55
57
 
56
58
  try { . (Join-Path $PSScriptRoot 'validate-orchestrator-output-resolution.ps1') } catch { Add-HookDependencyFailure -Name 'validate-orchestrator-output-resolution.ps1' -ErrorRecord $_ }
57
59
  try { . (Join-Path $PSScriptRoot 'validate-orchestrator-output-routing.ps1') } catch { Add-HookDependencyFailure -Name 'validate-orchestrator-output-routing.ps1' -ErrorRecord $_ }
60
+ try { . (Join-Path $PSScriptRoot 'validate-orchestrator-output-rejection.ps1') } catch { Add-HookDependencyFailure -Name 'validate-orchestrator-output-rejection.ps1' -ErrorRecord $_ }
58
61
  try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeItemResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'WorktreeItemResolution.psm1' -ErrorRecord $_ }
59
62
  try { Import-Module (Join-Path $PSScriptRoot '../lib/worktree-resolution/WorktreeRunResolution.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'WorktreeRunResolution.psm1' -ErrorRecord $_ }
60
63
  try { Import-Module (Join-Path $PSScriptRoot '../lib/orchestrator-state/OrchestratorStateEpicWaveBarrier.psm1') -Force -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'OrchestratorStateEpicWaveBarrier.psm1' -ErrorRecord $_ }
61
64
  try { Import-Module (Join-Path $PSScriptRoot '../lib/orchestrator-state/OrchestratorStateCompletion.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'OrchestratorStateCompletion.psm1' -ErrorRecord $_ }
62
65
  try { Import-Module (Join-Path $PSScriptRoot '../lib/orchestrator-state/OrchestratorStateUnconditional.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'OrchestratorStateUnconditional.psm1' -ErrorRecord $_ }
63
66
  try { Import-Module (Join-Path $PSScriptRoot '../lib/orchestrator-state/OrchestratorState.psm1') -Force -Global -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'OrchestratorState.psm1' -ErrorRecord $_ }
67
+ # Imported after the completion modules without -Force, so the instance they already loaded through
68
+ # the adoption module stays the one in use (issue #992).
69
+ try { Import-Module (Join-Path $PSScriptRoot '../lib/orchestrator-state/OrchestratorStateFeatureFolderRecord.psm1') -ErrorAction Stop } catch { Add-HookDependencyFailure -Name 'OrchestratorStateFeatureFolderRecord.psm1' -ErrorRecord $_ }
70
+ try { . (Join-Path $PSScriptRoot 'validate-orchestrator-output-feature-folder.ps1') } catch { Add-HookDependencyFailure -Name 'validate-orchestrator-output-feature-folder.ps1' -ErrorRecord $_ }
64
71
  try { . (Join-Path $PSScriptRoot 'subagentstop-envelope.ps1') } catch { Add-HookDependencyFailure -Name 'subagentstop-envelope.ps1' -ErrorRecord $_ }
65
72
  $ErrorActionPreference = 'Stop'
66
73
  $script:SubagentStopReportAndHaltLine = 'This condition is not repairable by the subagent. Report it to the operator and halt.'
@@ -194,7 +201,10 @@ function Invoke-OrchestratorOutputValidation {
194
201
  [string] $SessionRoot = (Get-Location).Path,
195
202
 
196
203
  [Parameter(Mandatory = $false)]
197
- [scriptblock] $RoutingInvoker
204
+ [scriptblock] $RoutingInvoker,
205
+
206
+ [Parameter(Mandatory = $false)]
207
+ [scriptblock] $FeatureFolderGitInvoker
198
208
  )
199
209
  $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent SubagentStop -ReasonPrefix 'ORCHESTRATOR_CHECKPOINT_UNRESOLVED:'
200
210
  if ($null -ne $dependencyDecision) { return $dependencyDecision }
@@ -205,6 +215,7 @@ function Invoke-OrchestratorOutputValidation {
205
215
  $agentOutput = $envelope.AssistantText
206
216
  $blockArguments = @{ AgentOutput = ([string]$agentOutput); CheckpointPath = $CheckpointPath; ArtifactType = $ArtifactType; SessionRoot = $SessionRoot }
207
217
  if ($PSBoundParameters.ContainsKey('RoutingInvoker')) { $blockArguments['RoutingInvoker'] = $RoutingInvoker }
218
+ if ($PSBoundParameters.ContainsKey('FeatureFolderGitInvoker')) { $blockArguments['FeatureFolderGitInvoker'] = $FeatureFolderGitInvoker }
208
219
  $decision = Get-OrchestratorOutputBlockDecision @blockArguments
209
220
  }
210
221
  if ($decision.Ok) { return @{ Ok = $true; Message = $null } }
@@ -225,6 +236,10 @@ function Get-OrchestratorOutputBlockDecision {
225
236
  the condition (message content, its checkpoint, or its runbook) and $false when it cannot
226
237
  (a registration argument, an internal evaluation failure, or a state it may not clear).
227
238
  The caller applies the re-entry policy to that flag.
239
+ An unresolved parallel-orchestrator-state checkpoint (status NoTarget) is allowed when the
240
+ output ends with a valid PARALLEL_MUTATION_REJECTED: <code> line and no live worktree holds
241
+ contradicting parallel checkpoint text (Get-OrchestratorOutputRejectionDecision, issue #1012);
242
+ otherwise the unresolved block carries the hint from Get-ParallelMutationRejectionHint.
228
243
  #>
229
244
  [CmdletBinding()]
230
245
  [OutputType([hashtable])]
@@ -235,7 +250,10 @@ function Get-OrchestratorOutputBlockDecision {
235
250
  [string] $SessionRoot = (Get-Location).Path,
236
251
 
237
252
  [Parameter(Mandatory = $false)]
238
- [scriptblock] $RoutingInvoker
253
+ [scriptblock] $RoutingInvoker,
254
+
255
+ [Parameter(Mandatory = $false)]
256
+ [scriptblock] $FeatureFolderGitInvoker
239
257
  )
240
258
 
241
259
  if ([string]::IsNullOrWhiteSpace($agentOutput)) {
@@ -251,9 +269,12 @@ function Get-OrchestratorOutputBlockDecision {
251
269
  return @{ Ok = $false; Repairable = $false; Message = ('ORCHESTRATOR_CHECKPOINT_UNRESOLVED: {0}: NoTarget (RESOLVER_FAILED): {1}' -f $ArtifactType, $_.Exception.Message) }
252
270
  }
253
271
  if (-not $resolution.Resolved) {
272
+ # Issue #1012: a parallel stop that wrote no state and ends with a valid rejection signal is allowed.
273
+ $rejectionDecision = Get-OrchestratorOutputRejectionDecision -ArtifactType $ArtifactType -Resolution $resolution -AgentOutput ([string]$agentOutput) -SessionRoot $SessionRoot
274
+ if ($null -ne $rejectionDecision) { return $rejectionDecision }
254
275
  $resolutionRepairable = ($resolution.Status -in @('NoTarget', 'Ambiguous')) -and ($ArtifactType -in @('epic-orchestrator-state', 'parallel-orchestrator-state'))
255
276
  return @{ Ok = $false; Repairable = $resolutionRepairable; Message = ('ORCHESTRATOR_CHECKPOINT_UNRESOLVED: {0}: {1} ({2}): {3}' -f
256
- $ArtifactType, $resolution.Status, $resolution.ReasonCode, $resolution.Detail) }
277
+ $ArtifactType, $resolution.Status, $resolution.ReasonCode, $resolution.Detail) + (Get-ParallelMutationRejectionHint -ArtifactType $ArtifactType -Status ([string]$resolution.Status) -AgentOutput ([string]$agentOutput)) }
257
278
  }
258
279
 
259
280
  $file = Get-CheckpointFileContent -Path $resolution.CheckpointPath
@@ -322,6 +343,15 @@ function Get-OrchestratorOutputBlockDecision {
322
343
  return @{ Ok = $false; Repairable = $true; Message = "ROUTING_CONTRACT_BLOCKED: $($routingResult.ErrorText)" }
323
344
  }
324
345
 
346
+ # Issue #992: a waived new_active_feature_folder must name a folder committed in HEAD of the run
347
+ # worktree. The validators only see the declared record, so the hook probes git once.
348
+ if ($ArtifactType -eq 'orchestrator-state') {
349
+ $folderArgs = @{ Checkpoint = $checkpoint; WorktreeRoot = [string]$resolution.WorktreeRoot }
350
+ if ($PSBoundParameters.ContainsKey('FeatureFolderGitInvoker') -and $null -ne $FeatureFolderGitInvoker) { $folderArgs['GitInvoker'] = $FeatureFolderGitInvoker }
351
+ $folderDecision = Get-OrchestratorOutputFeatureFolderDecision @folderArgs
352
+ if (-not $folderDecision.Ok) { return @{ Ok = $false; Repairable = $folderDecision.Repairable; Message = $folderDecision.Message } }
353
+ }
354
+
325
355
  # Layer 2 (issue #840): the epic checkpoint only, after the routing dispatch passes,
326
356
  # on the checkpoint text already read.
327
357
  if ($ArtifactType -eq 'epic-orchestrator-state') {
@@ -73,6 +73,7 @@ Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusValidation.p
73
73
  Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusConflict.psm1') -Force -ErrorAction Stop
74
74
  Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusScheduling.psm1') -Force -ErrorAction Stop
75
75
  Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusWriteIntent.psm1') -Force -ErrorAction Stop
76
+ Import-Module (Join-Path -Path $PSScriptRoot -ChildPath 'BlastRadiusCombination.psm1') -Force -ErrorAction Stop
76
77
 
77
78
  # Feature-folder handling. Every radius contains its own feature folder, and a
78
79
  # caller may pass either a bare folder name or an already-qualified path.
@@ -246,7 +247,8 @@ function Get-NormalizedDeclaredRadius {
246
247
 
247
248
  .OUTPUTS
248
249
  System.Collections.Hashtable. A new radius carrying the surviving paths,
249
- contracts re-filtered by the ASCII-letter rule, and modules and shared
250
+ contracts re-filtered by the ASCII-letter rule and the generic sheet-tab
251
+ rule of Test-GenericContractToken (issue #1006), and modules and shared
250
252
  surfaces re-resolved from the surviving paths. Throws when the radius
251
253
  source is observed: an observed radius records a diff listing rather than
252
254
  a plan-text harvest, so the plan-text acceptance rules do not apply to it
@@ -297,9 +299,12 @@ function Get-NormalizedDeclaredRadius {
297
299
  -MandateRead ([string[]]@(Get-ConfigMandateRead -Config $Config)))
298
300
  $concrete = [string[]]@(Get-ConcreteEntry -Entry $paths)
299
301
 
302
+ # Keep a recorded contract only when it carries an ASCII letter and is not a
303
+ # default spreadsheet sheet-tab name (issue #1006).
300
304
  $contract = [System.Collections.Generic.List[string]]::new()
301
305
  foreach ($identifier in @($normalized['contracts'])) {
302
- if ($script:ContractLetterPattern.IsMatch([string]$identifier)) {
306
+ if ($script:ContractLetterPattern.IsMatch([string]$identifier) -and
307
+ -not (Test-GenericContractToken -Token ([string]$identifier))) {
303
308
  $contract.Add([string]$identifier)
304
309
  }
305
310
  }
@@ -472,4 +477,5 @@ Export-ModuleMember -Function `
472
477
  Get-WriteIntentPlanPath, `
473
478
  Get-WriteIntentSpecContract, `
474
479
  Select-WriteIntentPathEntry, `
475
- Get-PlanPathForConfig
480
+ Get-PlanPathForConfig, `
481
+ Get-BlastRadiusCombination
@@ -0,0 +1,154 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Aggregate integration-cost cap over tolerated overlaps (issue #1013, D-2).
4
+
5
+ .DESCRIPTION
6
+ Destination-runtime PowerShell mirror of
7
+ scripts/dev_tools/_blast_radius_aggregate.py. The pairwise edge rule judges
8
+ each pair alone, so one item can accumulate many tolerated overlaps whose
9
+ summed cost exceeds what running it serially would cost. Get-AggregateCappedPair
10
+ caps each item's summed tolerated cost and returns the pairs to promote to
11
+ scheduling edges; Get-BlastRadiusConflictEdge applies the result.
12
+
13
+ Cap rule: total(i) is the summed cost of the remaining tolerated overlaps
14
+ that include item i. Item i is over its cap when
15
+ total(i) * 100 > band_duration(i) * tolerance_percent, evaluated in
16
+ integers; a missing band reads as default_band. While an item is over its
17
+ cap, the smallest-key such item promotes its overlap with the minimum key
18
+ (benefit ascending, cost descending, a ascending, b ascending).
19
+
20
+ Parity notes for maintainers:
21
+ - The Python module is the reference implementation; the committed
22
+ aggregate fixtures bind the two runtimes together.
23
+ - Every function is pure: no filesystem, subprocess, network, or clock
24
+ access, and no input is mutated. Integers only.
25
+ CONVENTION: this module fails fast at module scope and imports its siblings with -ErrorAction Stop.
26
+ #>
27
+
28
+ Set-StrictMode -Version Latest
29
+ $ErrorActionPreference = 'Stop'
30
+
31
+ # tolerance_percent is a percentage of the band duration.
32
+ $script:Percent = 100
33
+
34
+ # Resolve an item's band duration, reading a missing band as default_band.
35
+ function Get-AggregateBandDuration {
36
+ [CmdletBinding()]
37
+ [OutputType([long])]
38
+ param(
39
+ [AllowNull()]
40
+ [object] $Band,
41
+ [Parameter(Mandatory = $true)]
42
+ [hashtable] $Tolerance
43
+ )
44
+
45
+ $resolved = if ($null -eq $Band) { $Tolerance['default_band'] } else { $Band }
46
+ $duration = $Tolerance['band_durations']
47
+ if ($resolved -isnot [string] -or -not $duration.ContainsKey($resolved)) {
48
+ throw "band '$resolved' must be one of $(@($duration.Keys | Sort-Object) -join ', ')."
49
+ }
50
+ return [long]$duration[$resolved]
51
+ }
52
+
53
+ # Return the smallest item key whose tolerated total exceeds its cap, or $null.
54
+ function Get-FirstOverCapItem {
55
+ [CmdletBinding()]
56
+ [OutputType([long])]
57
+ param(
58
+ [Parameter(Mandatory = $true)]
59
+ [AllowEmptyCollection()]
60
+ [object[]] $Remaining,
61
+ [Parameter(Mandatory = $true)]
62
+ [hashtable] $BandByKey,
63
+ [Parameter(Mandatory = $true)]
64
+ [hashtable] $Tolerance
65
+ )
66
+
67
+ # Each overlap's cost counts toward both of its items.
68
+ $total = @{}
69
+ foreach ($overlap in $Remaining) {
70
+ foreach ($key in @($overlap['a'], $overlap['b'])) {
71
+ $current = if ($total.ContainsKey($key)) { $total[$key] } else { [long]0 }
72
+ $total[$key] = $current + $overlap['cost']
73
+ }
74
+ }
75
+ $percent = [long]$Tolerance['tolerance_percent']
76
+ foreach ($key in @($total.Keys | Sort-Object)) {
77
+ $band = if ($BandByKey.ContainsKey($key)) { $BandByKey[$key] } else { $null }
78
+ $cap = (Get-AggregateBandDuration -Band $band -Tolerance $Tolerance) * $percent
79
+ if ($total[$key] * $script:Percent -gt $cap) {
80
+ return $key
81
+ }
82
+ }
83
+ return $null
84
+ }
85
+
86
+ function Get-AggregateCappedPair {
87
+ <#
88
+ .SYNOPSIS
89
+ Return the tolerated pairs to promote so every item is within its cap.
90
+
91
+ .DESCRIPTION
92
+ Port of select_capped_pairs. Repeatedly takes the smallest-key item that
93
+ is over its cap, promotes its cheapest-to-serialize overlap, and
94
+ recomputes the totals, until no item is over its cap.
95
+
96
+ .PARAMETER ToleratedOverlap
97
+ The pairwise tolerated overlaps, in any order: records carrying a, b,
98
+ cost, and benefit.
99
+
100
+ .PARAMETER Band
101
+ Item key to complexity band; a key that is absent or maps to null reads
102
+ as default_band.
103
+
104
+ .PARAMETER Tolerance
105
+ A value returned by Get-ConfigConflictTolerance.
106
+
107
+ .OUTPUTS
108
+ System.Collections.Specialized.OrderedDictionary. The promoted pairs in
109
+ promotion order, each an ordered record with keys a and b, written to
110
+ the pipeline; nothing when no item is over its cap. Wrap the call in
111
+ @() to read the result as an array. Throws when a band is not a
112
+ configured band.
113
+ #>
114
+ [CmdletBinding()]
115
+ [OutputType([System.Collections.Specialized.OrderedDictionary])]
116
+ param(
117
+ [Parameter(Mandatory = $true)]
118
+ [AllowEmptyCollection()]
119
+ [object[]] $ToleratedOverlap,
120
+ [Parameter(Mandatory = $true)]
121
+ [hashtable] $Band,
122
+ [Parameter(Mandatory = $true)]
123
+ [hashtable] $Tolerance
124
+ )
125
+
126
+ # Copy every overlap and band key into Int64 records, so integer keys of any
127
+ # width compare equal and no input is mutated.
128
+ $bandByKey = @{}
129
+ foreach ($key in $Band.Keys) { $bandByKey[[long]$key] = $Band[$key] }
130
+ $copied = foreach ($overlap in $ToleratedOverlap) {
131
+ [ordered]@{ a = [long]$overlap['a']; b = [long]$overlap['b']; cost = [long]$overlap['cost']; benefit = [long]$overlap['benefit'] }
132
+ }
133
+ $remaining = [System.Collections.Generic.List[object]]::new()
134
+ foreach ($overlap in @($copied | Sort-Object -Property { $_['a'] }, { $_['b'] })) {
135
+ if ($null -ne $overlap) { $remaining.Add($overlap) }
136
+ }
137
+
138
+ $promoted = [System.Collections.Generic.List[object]]::new()
139
+ while ($true) {
140
+ $item = Get-FirstOverCapItem -Remaining @($remaining.ToArray()) -BandByKey $bandByKey -Tolerance $Tolerance
141
+ if ($null -eq $item) {
142
+ # Callers wrap the enumerated records with @() so an empty result is
143
+ # an empty array.
144
+ return $promoted.ToArray()
145
+ }
146
+ # Cheapest to serialize: least benefit, then most cost, then pair keys.
147
+ $cheapest = @($remaining | Where-Object { $_['a'] -eq $item -or $_['b'] -eq $item } |
148
+ Sort-Object -Property { $_['benefit'] }, { - $_['cost'] }, { $_['a'] }, { $_['b'] })[0]
149
+ [void]$remaining.Remove($cheapest)
150
+ $promoted.Add([ordered]@{ a = $cheapest['a']; b = $cheapest['b'] })
151
+ }
152
+ }
153
+
154
+ Export-ModuleMember -Function Get-AggregateCappedPair