@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,282 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Pre-tool-use hook that blocks a Write, Edit, or apply_patch leaving a covered file above 800 lines.
4
+
5
+ .DESCRIPTION
6
+ This script is invoked by the Codex PreToolUse hook under the ^(apply_patch|Edit|Write)$
7
+ matcher. It enforces the hard tier of the tiered file-size policy: 500 lines is
8
+ guidance, 700 lines is advisory, and above 800 lines a split is enforced regardless of
9
+ logical separability. The policy functions are the dot-sourced Codex twin
10
+ file-size-policy.ps1, which is held text-identical to the Claude module.
11
+
12
+ The stdin payload is parsed by ConvertFrom-CodexPreToolUsePayload and mapped to
13
+ file-edit records by ConvertTo-CodexFileEditInput. Per record:
14
+ - A path that is not covered, and a Delete, allow with no file read.
15
+ - Write and apply_patch Add use the record content.
16
+ - Edit resolves old_string to new_string in memory against the pre-edit file read
17
+ through the ReadFileContent seam; a missing or unreadable file, or an edit that
18
+ cannot be resolved, denies.
19
+ - apply_patch Update is reconstructed by a second ConvertTo-CodexFileEditInput call
20
+ with -ResolveUpdateContent and -GovernedPath set to the patched path; empty
21
+ reconstructed content denies.
22
+ - A rename evaluates the destination, and the source supplies the pre-edit size.
23
+ A result above 800 lines is denied unless the file already existed and does not grow.
24
+
25
+ Allowed payloads produce NO stdout and exit 0. A deny writes the PreToolUse JSON
26
+ envelope to stdout and exits 0. Empty, malformed, or tool_input-less stdin writes the
27
+ reason to stderr and exits 2.
28
+
29
+ .NOTES
30
+ Compatible with PowerShell 7+.
31
+ This script must not modify any state; it is a read-only validation gate.
32
+ #>
33
+ [CmdletBinding()]
34
+ param()
35
+ $script:HookDependencyGuardLoadFailed = $false; try { . (Join-Path $PSScriptRoot 'hook-dependency-guard.ps1') } catch { $script:HookDependencyGuardLoadFailed = $true }
36
+
37
+ # Shared Codex PreToolUse transport: stdin payload parsing and tool_input-to-file
38
+ # mapping for every tool name the ^(apply_patch|Edit|Write)$ matcher admits.
39
+ try { . (Join-Path $PSScriptRoot 'codex-pretooluse-file-mapping.ps1') } catch { Add-HookDependencyFailure -Name 'codex-pretooluse-file-mapping.ps1' -ErrorRecord $_ }
40
+ try { . (Join-Path $PSScriptRoot 'file-size-policy.ps1') } catch { Add-HookDependencyFailure -Name 'file-size-policy.ps1' -ErrorRecord $_ }
41
+
42
+ function Get-FileSizeLimitBlockDecision {
43
+ <#
44
+ .SYNOPSIS
45
+ Constructs a deny-decision ordered dictionary carrying the supplied reason.
46
+ .PARAMETER Reason
47
+ The deny reason; it starts with FILE_SIZE_LIMIT_BLOCKED:.
48
+ #>
49
+ [CmdletBinding()]
50
+ [OutputType([System.Collections.Specialized.OrderedDictionary])]
51
+ param(
52
+ [Parameter(Mandatory)]
53
+ [string] $Reason
54
+ )
55
+
56
+ return [ordered]@{
57
+ hookSpecificOutput = [ordered]@{
58
+ hookEventName = 'PreToolUse'
59
+ permissionDecision = 'deny'
60
+ permissionDecisionReason = $Reason
61
+ }
62
+ }
63
+ }
64
+
65
+ function Get-CodexFileSizeRecordValue {
66
+ <#
67
+ .SYNOPSIS
68
+ Returns a named property of a file-edit record, or $null when it is absent.
69
+ #>
70
+ [CmdletBinding()]
71
+ [OutputType([object])]
72
+ param(
73
+ [Parameter(Mandatory)]
74
+ [AllowNull()]
75
+ $Record,
76
+
77
+ [Parameter(Mandatory)]
78
+ [string] $Name
79
+ )
80
+
81
+ if ($null -eq $Record -or $Record.PSObject.Properties.Name -notcontains $Name) {
82
+ return $null
83
+ }
84
+ return $Record.$Name
85
+ }
86
+
87
+ function Get-CodexFileSizeReplaceAllFlag {
88
+ <#
89
+ .SYNOPSIS
90
+ Returns the boolean value of a record's replace_all property.
91
+ .DESCRIPTION
92
+ A boolean is returned as is; a string is true only when its trimmed value is
93
+ 'true' (case-insensitive); every other value is false.
94
+ #>
95
+ [CmdletBinding()]
96
+ [OutputType([bool])]
97
+ param(
98
+ [Parameter(Mandatory)]
99
+ [AllowNull()]
100
+ $Record
101
+ )
102
+
103
+ $value = Get-CodexFileSizeRecordValue -Record $Record -Name 'replace_all'
104
+ if ($value -is [bool]) {
105
+ return $value
106
+ }
107
+ if ($value -is [string]) {
108
+ return ($value.Trim() -ieq 'true')
109
+ }
110
+ return $false
111
+ }
112
+
113
+ function Get-CodexFileSizeUpdatedContent {
114
+ <#
115
+ .SYNOPSIS
116
+ Reconstructs the post-patch content of an apply_patch Update for one patched path.
117
+ .OUTPUTS
118
+ The reconstructed content, or an empty string when it cannot be reconstructed.
119
+ #>
120
+ [CmdletBinding()]
121
+ [OutputType([string])]
122
+ param(
123
+ [Parameter(Mandatory)]
124
+ $Payload,
125
+
126
+ [Parameter(Mandatory)]
127
+ [string] $SourcePath
128
+ )
129
+
130
+ $resolved = @(
131
+ ConvertTo-CodexFileEditInput -Payload $Payload -ResolveUpdateContent -GovernedPath $SourcePath |
132
+ Where-Object { $_.operation -eq 'Update' -and $_.source_path -eq $SourcePath }
133
+ )
134
+ if ($resolved.Count -eq 0) {
135
+ return ''
136
+ }
137
+ return [string]$resolved[0].content
138
+ }
139
+
140
+ function Invoke-CodexFileSizeLimitDecision {
141
+ <#
142
+ .SYNOPSIS
143
+ Returns the deny decision for one file-edit record, or $null when it is allowed.
144
+ .PARAMETER Record
145
+ One record from ConvertTo-CodexFileEditInput.
146
+ .PARAMETER Payload
147
+ The parsed payload, used to reconstruct an apply_patch Update.
148
+ .PARAMETER RepositoryRoot
149
+ The repository root used to resolve relative paths. Defaults to the current location.
150
+ .PARAMETER ReadFileContent
151
+ Seam that returns the text of a file, $null when the file does not exist, and
152
+ throws when it cannot be read. Tests supply in-memory content.
153
+ #>
154
+ [CmdletBinding()]
155
+ [OutputType([System.Collections.Specialized.OrderedDictionary])]
156
+ param(
157
+ [Parameter(Mandatory)]
158
+ $Record,
159
+
160
+ [Parameter(Mandatory)]
161
+ $Payload,
162
+
163
+ [string] $RepositoryRoot = (Get-Location).ProviderPath,
164
+
165
+ [scriptblock] $ReadFileContent = {
166
+ param([string] $Path)
167
+ if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) { return $null }
168
+ return [System.IO.File]::ReadAllText($Path)
169
+ }
170
+ )
171
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'FILE_SIZE_LIMIT_BLOCKED:'
172
+ if ($null -ne $dependencyDecision) { return $dependencyDecision }
173
+
174
+ $operation = [string](Get-CodexFileSizeRecordValue -Record $Record -Name 'operation')
175
+ $sourcePath = [string](Get-CodexFileSizeRecordValue -Record $Record -Name 'source_path')
176
+ $relativePath = ConvertTo-FileSizeRelativePath -Path ([string]$Record.file_path) -RepositoryRoot $RepositoryRoot
177
+ if ($operation -eq 'Delete' -or -not (Test-FileSizeCoveredPath -RelativePath $relativePath)) {
178
+ return $null
179
+ }
180
+
181
+ # The pre-edit size comes from the source path, which differs from the target only for a rename.
182
+ $sourceRelative = ConvertTo-FileSizeRelativePath -Path $sourcePath -RepositoryRoot $RepositoryRoot
183
+ $isRooted = ($sourcePath -match '^[\\/]') -or ($sourcePath -match '^[A-Za-z]:[\\/]')
184
+ $readPath = if ($isRooted -or $null -eq $sourceRelative) { $sourcePath } else { Join-Path $RepositoryRoot $sourceRelative }
185
+ $hardLimit = (Get-FileSizePolicyLimit).HardLimit
186
+
187
+ $resultCount = 0
188
+ if ($operation -eq 'Update') {
189
+ $updated = Get-CodexFileSizeUpdatedContent -Payload $Payload -SourcePath $sourcePath
190
+ if ([string]::IsNullOrEmpty($updated)) {
191
+ return Get-FileSizeLimitBlockDecision -Reason "FILE_SIZE_LIMIT_BLOCKED: the apply_patch Update to '$relativePath' could not be reconstructed to measure its size. The gate fails closed for a covered file."
192
+ }
193
+ $resultCount = Get-FileSizeLogicalLineCount -Content $updated
194
+ } elseif ($operation -ne 'Edit') {
195
+ $resultCount = Get-FileSizeLogicalLineCount -Content ([string](Get-CodexFileSizeRecordValue -Record $Record -Name 'content'))
196
+ }
197
+ if ($operation -ne 'Edit' -and $resultCount -le $hardLimit) {
198
+ return $null
199
+ }
200
+
201
+ try {
202
+ $preEditContent = & $ReadFileContent $readPath
203
+ } catch {
204
+ return Get-FileSizeLimitBlockDecision -Reason "FILE_SIZE_LIMIT_BLOCKED: '$relativePath' could not be read to measure its size ($($_.Exception.Message)). The gate fails closed for a covered file."
205
+ }
206
+ $preEditCount = $null
207
+ if ($null -ne $preEditContent) {
208
+ $preEditCount = Get-FileSizeLogicalLineCount -Content ([string]$preEditContent)
209
+ }
210
+
211
+ if ($operation -eq 'Edit') {
212
+ if ($null -eq $preEditContent) {
213
+ return Get-FileSizeLimitBlockDecision -Reason "FILE_SIZE_LIMIT_BLOCKED: '$relativePath' does not exist, so the Edit cannot be measured. The gate fails closed for a covered file."
214
+ }
215
+ $edit = Resolve-FileSizeEditContent -Content ([string]$preEditContent) `
216
+ -OldString ([string](Get-CodexFileSizeRecordValue -Record $Record -Name 'old_string')) `
217
+ -NewString ([string](Get-CodexFileSizeRecordValue -Record $Record -Name 'new_string')) `
218
+ -ReplaceAll (Get-CodexFileSizeReplaceAllFlag -Record $Record)
219
+ if ($null -ne $edit.Failure) {
220
+ return Get-FileSizeLimitBlockDecision -Reason "FILE_SIZE_LIMIT_BLOCKED: the Edit to '$relativePath' could not be resolved in memory ($($edit.Failure)). The gate fails closed for a covered file."
221
+ }
222
+ $resultCount = Get-FileSizeLogicalLineCount -Content $edit.Content
223
+ }
224
+
225
+ $decision = Get-FileSizeHookDecision -RelativePath $relativePath -ResultLineCount $resultCount -PreEditLineCount $preEditCount
226
+ if ($decision.Allowed) {
227
+ return $null
228
+ }
229
+ return Get-FileSizeLimitBlockDecision -Reason $decision.Reason
230
+ }
231
+
232
+ function Invoke-CodexFileSizeLimitEntryPoint {
233
+ <#
234
+ .SYNOPSIS
235
+ Reads one Codex PreToolUse payload and returns the process exit code.
236
+ .PARAMETER PayloadRaw
237
+ The raw stdin text. AllowEmptyString is required so empty input reaches the shared
238
+ parser and fails closed with exit 2.
239
+ .PARAMETER RepositoryRoot
240
+ The repository root passed to the per-record decision.
241
+ .PARAMETER ReadFileContent
242
+ Optional file-reader seam passed to the per-record decision.
243
+ #>
244
+ [CmdletBinding()]
245
+ [OutputType([int])]
246
+ param(
247
+ [Parameter(Mandatory)]
248
+ [AllowEmptyString()]
249
+ [string] $PayloadRaw,
250
+
251
+ [string] $RepositoryRoot = (Get-Location).ProviderPath,
252
+
253
+ [scriptblock] $ReadFileContent
254
+ )
255
+
256
+ try {
257
+ $payload = ConvertFrom-CodexPreToolUsePayload -PayloadRaw $PayloadRaw -HookName 'enforce-file-size-limit'
258
+ foreach ($record in @(ConvertTo-CodexFileEditInput -Payload $payload)) {
259
+ $decisionArgs = @{ Record = $record; Payload = $payload; RepositoryRoot = $RepositoryRoot }
260
+ if ($PSBoundParameters.ContainsKey('ReadFileContent')) { $decisionArgs['ReadFileContent'] = $ReadFileContent }
261
+ $decision = Invoke-CodexFileSizeLimitDecision @decisionArgs
262
+ if ($null -ne $decision) {
263
+ [Console]::Out.WriteLine(($decision | ConvertTo-Json -Compress -Depth 5))
264
+ return 0
265
+ }
266
+ }
267
+ return 0
268
+ } catch {
269
+ [Console]::Error.WriteLine([string]$_)
270
+ return 2
271
+ }
272
+ }
273
+
274
+ # Guard allows dot-sourcing in tests without executing the entrypoint.
275
+ if ($MyInvocation.InvocationName -eq '.') {
276
+ return
277
+ }
278
+ if ($script:HookDependencyGuardLoadFailed) { [Console]::Error.WriteLine('FILE_SIZE_LIMIT_BLOCKED: hook-dependency-guard.ps1 failed to load; the gate fails closed.'); exit 2 }
279
+ $dependencyDecision = Get-HookDependencyFailureDecision -HookEvent PreToolUse -ReasonPrefix 'FILE_SIZE_LIMIT_BLOCKED:'
280
+ if ($null -ne $dependencyDecision) { $dependencyDecision | ConvertTo-Json -Compress -Depth 5 | Write-Output; exit 0 }
281
+
282
+ exit (Invoke-CodexFileSizeLimitEntryPoint -PayloadRaw ([Console]::In.ReadToEnd()))
@@ -4,12 +4,20 @@
4
4
 
5
5
  .DESCRIPTION
6
6
  Dot-sourced by enforce-orchestration-preimplementation-gate.ps1. The Codex counterpart
7
- of the issue #663 Claude sibling, holding two groups of functions:
7
+ of the issue #663 Claude sibling, holding three groups of functions:
8
8
 
9
9
  - The two per-mode read seams of issue #554 (Get-EpicCheckpointContent and
10
10
  Get-ParallelCheckpointContent), relocated verbatim from the gate file so the gate
11
11
  stays inside the 500-line cap. Their names and behaviour are unchanged, so tests
12
12
  that mock or shadow them by name are unaffected.
13
+ - The target-resolution building blocks of issue #1010, byte-identical to the Claude
14
+ sibling: the worktree-list wrapper Get-OrchestrationGateWorktreeList (the only
15
+ listing seam), the recording invoker Invoke-OrchestrationGateWorktreeList, and the
16
+ command-operand parser Get-OrchestrationGateCommandOperandPath, plus the reason-code
17
+ pair restated from WorktreeResolution.psm1. They feed Resolve-OrchestrationGateTarget
18
+ and Read-OrchestrationGateCheckpoint, which read the single-feature checkpoint through
19
+ the Get-CheckpointContent seam (mandatory absolute Path, moved here from the gate)
20
+ beneath the worktree the file path, apply_patch markers, or command operands name.
13
21
  - The epic-scope decision for the command, apply_patch, and path legs. A call is epic
14
22
  scope when the effective worktree's HEAD (the -C selector worktree when present,
15
23
  otherwise the session root) equals the integration_branch of
@@ -29,13 +37,23 @@
29
37
  from the resolution sibling dot-sourced below. The per-segment target resolver comes
30
38
  from the targets file dot-sourced below (issue #738), which calls
31
39
  Read-CommandLineSegment, Get-CommandLineGlobalOption, and Get-CommandLineInvocation,
32
- loaded by the gate's dot-source of hook-command-invocation.ps1.
40
+ loaded by the gate's dot-source of hook-command-invocation.ps1. Resolve-HookTargetWorktree
41
+ and ConvertFrom-HookTargetWorktreePorcelain come from the guarded dot-source of the
42
+ resolver twin hook-target-worktree.ps1 (issue #1009).
33
43
  Mirrored byte-identically under extensions/drm-copilot/resources/codex-and-agents-customizations/.
34
44
  AUTHORITY: PowerShell-authoritative. The epic readiness predicate has no reference implementation in another language, and this hook starts no interpreter process (issue #707, D15).
35
45
  #>
36
46
 
37
47
  . (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-epic-resolution.ps1')
38
48
  . (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-targets.ps1')
49
+ try { . (Join-Path $PSScriptRoot 'hook-target-worktree.ps1') } catch { Add-HookDependencyFailure -Name 'hook-target-worktree.ps1' -ErrorRecord $_ }
50
+
51
+ # The target-resolution reason codes (issue #1010). Their source is
52
+ # Get-WorktreeResolutionAmbiguityReasonCode and Get-WorktreeResolutionNoTargetReasonCode
53
+ # in .claude/lib/worktree-resolution/WorktreeResolution.psm1; Codex hooks cannot import
54
+ # .claude/lib, so the two literals are restated once here and pinned equal by a test.
55
+ $script:OrchestrationGateAmbiguousReasonCode = 'TARGET_WORKTREE_AMBIGUOUS'
56
+ $script:OrchestrationGateNotDerivableReasonCode = 'TARGET_WORKTREE_NOT_DERIVABLE'
39
57
 
40
58
  # An epic manifest lives under the epics tree; the pattern is tested after backslash
41
59
  # normalisation so either separator spelling is accepted.
@@ -68,6 +86,225 @@ function Get-ParallelCheckpointContent {
68
86
  return Get-Content -Raw -LiteralPath $path
69
87
  }
70
88
 
89
+ # The single-feature read seam (issue #1010, moved from the gate file). It takes the
90
+ # absolute path composed beneath the resolved worktree root, so no read binds to the
91
+ # calling process's directory; an absent file returns an empty string.
92
+ function Get-CheckpointContent {
93
+ [CmdletBinding()]
94
+ [OutputType([string])]
95
+ param([Parameter(Mandatory)][ValidatePattern('^([A-Za-z]:[\\/]|/)')][string] $Path)
96
+
97
+ if (-not (Test-Path -LiteralPath $Path)) {
98
+ return ''
99
+ }
100
+ return Get-Content -Raw -LiteralPath $Path
101
+ }
102
+
103
+ function Get-OrchestrationGateWorktreeList {
104
+ <#
105
+ .SYNOPSIS
106
+ Returns the porcelain worktree listing for the session root (issue #1010 seam).
107
+ .DESCRIPTION
108
+ Runs the listing exactly as the default WorktreeListInvoker of
109
+ Resolve-HookTargetWorktree does and returns an empty string on a non-zero exit. It
110
+ is the only test seam for the listing.
111
+ .OUTPUTS
112
+ System.String
113
+ #>
114
+ [CmdletBinding()]
115
+ [OutputType([string])]
116
+ param([Parameter(Mandatory)][string] $SessionRoot)
117
+
118
+ $porcelain = & git -C $SessionRoot worktree list --porcelain 2>$null
119
+ if ($LASTEXITCODE -ne 0) { return '' }
120
+ return ($porcelain -join "`n")
121
+ }
122
+
123
+ function Invoke-OrchestrationGateWorktreeList {
124
+ <#
125
+ .SYNOPSIS
126
+ Recording WorktreeListInvoker: returns the listing and records a listing failure.
127
+ .DESCRIPTION
128
+ Sets $script:OrchestrationGateWorktreeListFailed when the wrapper throws (and then
129
+ rethrows) or when its text holds no worktree entry, so the gate denies instead of
130
+ accepting the resolver's session-root fallback (issue #1010, spec E1).
131
+ .OUTPUTS
132
+ System.String
133
+ #>
134
+ [CmdletBinding()]
135
+ [OutputType([string])]
136
+ param([Parameter(Mandatory)][string] $SessionRoot)
137
+
138
+ try {
139
+ $text = [string](Get-OrchestrationGateWorktreeList -SessionRoot $SessionRoot)
140
+ } catch {
141
+ $script:OrchestrationGateWorktreeListFailed = $true
142
+ throw
143
+ }
144
+ if (@(ConvertFrom-HookTargetWorktreePorcelain -Text $text).Count -eq 0) {
145
+ $script:OrchestrationGateWorktreeListFailed = $true
146
+ }
147
+ return $text
148
+ }
149
+
150
+ function Get-OrchestrationGateCommandOperandPath {
151
+ <#
152
+ .SYNOPSIS
153
+ Returns the worktree-selecting paths of every git add and git commit invocation.
154
+ .DESCRIPTION
155
+ Scans every Structural match of git add and git commit (every command segment and
156
+ wrapper payload). Each -C value in any git global-option position and each absolute
157
+ operand is returned, distinct and in first-seen order. Relative operands, a -C on a
158
+ git segment invoking neither add nor commit, and Indeterminate matches are ignored.
159
+ For a match whose record is not argument-injected, a subcommand-aware walk (issue
160
+ #1010, F2) also reads the tokens after the subcommand with a per-subcommand option
161
+ model, compared case-sensitively: a value option consumes the next token unless its
162
+ value is inline (--name=value) or attached (-mvalue); a standalone flag consumes
163
+ itself; '--' makes every later token an operand; a redirection and its target are
164
+ skipped; any other dash token, such as the cluster -am, stops the walk. Its literal
165
+ absolute tokens are returned, and a token the walk reads as an option value is not
166
+ returned as an operand.
167
+ .PARAMETER Command
168
+ The full command line.
169
+ .OUTPUTS
170
+ System.String[]
171
+ #>
172
+ [CmdletBinding()]
173
+ [OutputType([string[]])]
174
+ param([Parameter(Mandatory)][AllowEmptyString()][string] $Command)
175
+
176
+ $valueOptions = @{
177
+ commit = @('-m', '--message', '-F', '--file', '--author', '--date', '-C', '--reuse-message', '-c', '--reedit-message', '-t', '--template', '--fixup', '--squash', '--trailer', '--pathspec-from-file')
178
+ add = @('--pathspec-from-file', '--chmod')
179
+ }
180
+ $flagOptions = @{
181
+ commit = @('-a', '--all', '--amend', '--no-edit', '--no-verify', '-n', '-s', '--signoff', '-q', '--quiet', '-v', '--verbose', '--allow-empty', '-o', '--only', '-i', '--include', '--pathspec-file-nul')
182
+ add = @('-A', '--all', '-u', '--update', '-f', '--force', '-N', '--intent-to-add', '-n', '--dry-run', '-v', '--verbose', '--pathspec-file-nul')
183
+ }
184
+ $absolutePattern = '^([A-Za-z]:[\\/]|/)'
185
+ $paths = [System.Collections.Generic.List[string]]::new()
186
+ foreach ($subcommand in @('add', 'commit')) {
187
+ foreach ($match in @(Get-CommandLineInvocation -CommandText $Command -CommandWord 'git' -SubcommandPath @($subcommand))) {
188
+ if ($match.Status -ne 'Structural') { continue }
189
+ $walked = [System.Collections.Generic.List[string]]::new()
190
+ $optionValues = [System.Collections.Generic.List[string]]::new()
191
+ $tokens = if ($match.Segment.ArgumentInjected) { [string[]]@() } else { [string[]]@($match.Segment.Tokens) }
192
+ $afterSeparator = $false
193
+ for ($index = [int]$match.OperandIndex; $index -lt $tokens.Count; $index++) {
194
+ $token = $tokens[$index]
195
+ if (-not $afterSeparator -and $token -match '^(<|>|\d*>|&>)') {
196
+ if ($token -match '^(\d*[<>]{1,2}&?|&>{1,2})$') { $index++ }
197
+ continue
198
+ }
199
+ if ($afterSeparator -or -not $token.StartsWith('-')) { $walked.Add($token); continue }
200
+ if ($token -ceq '--') { $afterSeparator = $true; continue }
201
+ $name = if ($token.IndexOf('=') -gt 0) { $token.Substring(0, $token.IndexOf('=')) } else { $token }
202
+ if ($valueOptions[$subcommand] -ccontains $name) {
203
+ if ($name -ceq $token -and $index + 1 -lt $tokens.Count) { $index++; $optionValues.Add($tokens[$index]) }
204
+ continue
205
+ }
206
+ if ($token -match '^-[^-].' -and $valueOptions[$subcommand] -ccontains $token.Substring(0, 2)) { continue }
207
+ if ($flagOptions[$subcommand] -ccontains $token) { continue }
208
+ break
209
+ }
210
+ $candidates = @(@($match.GlobalOptions) | Where-Object { $_.Name -ceq '-C' -and $_.Value } | ForEach-Object { [string]$_.Value })
211
+ $candidates += @(@($match.Operands) | Where-Object { $_ -match $absolutePattern -and $optionValues -cnotcontains $_ })
212
+ $candidates += @($walked | Where-Object { $_ -match $absolutePattern -and (Test-CommandLineTokenLiteral -Token $_) })
213
+ foreach ($candidate in $candidates) {
214
+ if ($paths -notcontains $candidate) { $paths.Add($candidate) }
215
+ }
216
+ }
217
+ }
218
+ return [string[]]$paths.ToArray()
219
+ }
220
+
221
+ function Resolve-OrchestrationGateTarget {
222
+ <#
223
+ .SYNOPSIS
224
+ Resolves the worktree whose checkpoint governs a single-feature path or command leg (issue #1010).
225
+ .DESCRIPTION
226
+ Calls Resolve-HookTargetWorktree with the recording invoker: a file path is passed as
227
+ -FilePath, the marker paths of an apply_patch body as -FilePath (markers in two
228
+ worktrees resolve as ambiguous), and any other command's
229
+ Get-OrchestrationGateCommandOperandPath result as -CommandOperandPath. A failed or
230
+ empty listing gives NoTarget instead of the session-root fallback; Ambiguous gives
231
+ Ambiguous; a null root gives NoTarget; otherwise SessionRoot or OtherWorktree.
232
+ .OUTPUTS
233
+ System.Management.Automation.PSCustomObject with Status, WorktreeRoot, ReasonCode, and Detail.
234
+ #>
235
+ [CmdletBinding()]
236
+ [OutputType([pscustomobject])]
237
+ param(
238
+ [AllowNull()][AllowEmptyString()][string] $FilePath = '',
239
+ [AllowNull()][AllowEmptyString()][string] $Command = ''
240
+ )
241
+
242
+ $sessionRoot = (Get-Location).Path
243
+ $script:OrchestrationGateWorktreeListFailed = $false
244
+ $invoker = { param($SessionRoot) Invoke-OrchestrationGateWorktreeList -SessionRoot $SessionRoot }
245
+ $markerPaths = if ($FilePath) { @() } else { @(Get-OrchestrationPatchMarkerPath -PatchText ([string]$Command)) }
246
+ $resolved = if ($FilePath) {
247
+ Resolve-HookTargetWorktree -SessionRoot $sessionRoot -FilePath @($FilePath) -WorktreeListInvoker $invoker
248
+ } elseif ($markerPaths.Count -gt 0) {
249
+ Resolve-HookTargetWorktree -SessionRoot $sessionRoot -FilePath $markerPaths -WorktreeListInvoker $invoker
250
+ } else {
251
+ Resolve-HookTargetWorktree -SessionRoot $sessionRoot -CommandOperandPath @(Get-OrchestrationGateCommandOperandPath -Command ([string]$Command)) -WorktreeListInvoker $invoker
252
+ }
253
+ $detail = "resolver source $($resolved.Source): $($resolved.Detail)"
254
+ if ($script:OrchestrationGateWorktreeListFailed) {
255
+ return [pscustomobject]@{ Status = 'NoTarget'; WorktreeRoot = $null; ReasonCode = $script:OrchestrationGateNotDerivableReasonCode; Detail = "the worktree listing failed or named no worktree; $detail" }
256
+ }
257
+ if ($resolved.Ambiguous) {
258
+ return [pscustomobject]@{ Status = 'Ambiguous'; WorktreeRoot = $null; ReasonCode = $script:OrchestrationGateAmbiguousReasonCode; Detail = $detail }
259
+ }
260
+ if ([string]::IsNullOrEmpty([string]$resolved.WorktreeRoot)) {
261
+ return [pscustomobject]@{ Status = 'NoTarget'; WorktreeRoot = $null; ReasonCode = $script:OrchestrationGateNotDerivableReasonCode; Detail = $detail }
262
+ }
263
+ $isSession = [string]::Equals([string]$resolved.WorktreeRoot, (ConvertTo-HookTargetWorktreeNormalizedPath -Path $sessionRoot), [System.StringComparison]::OrdinalIgnoreCase)
264
+ $status = if ($isSession) { 'SessionRoot' } else { 'OtherWorktree' }
265
+ return [pscustomobject]@{ Status = $status; WorktreeRoot = [string]$resolved.WorktreeRoot; ReasonCode = $null; Detail = $detail }
266
+ }
267
+
268
+ function Read-OrchestrationGateCheckpoint {
269
+ <#
270
+ .SYNOPSIS
271
+ Reads the checkpoint beneath the resolved target worktree, or returns the deny reason.
272
+ .DESCRIPTION
273
+ Resolved is $false, with DenyReason set, when the target is NoTarget or Ambiguous.
274
+ Otherwise Raw holds the checkpoint text (empty when absent) and Path its absolute
275
+ path, composed beneath the resolved root with a forward slash.
276
+ .OUTPUTS
277
+ System.Management.Automation.PSCustomObject
278
+ #>
279
+ [CmdletBinding()]
280
+ [OutputType([pscustomobject])]
281
+ param(
282
+ [Parameter(Mandatory)][string] $Mode,
283
+ [AllowNull()][AllowEmptyString()][string] $FilePath = '',
284
+ [AllowNull()][AllowEmptyString()][string] $Command = ''
285
+ )
286
+
287
+ $target = Resolve-OrchestrationGateTarget -FilePath $FilePath -Command $Command
288
+ if ($target.Status -eq 'NoTarget' -or $target.Status -eq 'Ambiguous') {
289
+ return [pscustomobject]@{
290
+ Resolved = $false
291
+ Raw = ''
292
+ Path = $null
293
+ DenyReason = ("PREIMPLEMENTATION_GATE_BLOCKED: $($target.ReasonCode): the target worktree of this $Mode call " +
294
+ "could not be resolved: $($target.Detail). Implementation operations require an identifiable target " +
295
+ 'worktree whose checkpoint is ready.')
296
+ }
297
+ }
298
+
299
+ $path = ([string]$target.WorktreeRoot).TrimEnd('/') + '/artifacts/orchestration/orchestrator-state.json'
300
+ return [pscustomobject]@{
301
+ Resolved = $true
302
+ Raw = [string](Get-CheckpointContent -Path $path)
303
+ Path = $path
304
+ DenyReason = $null
305
+ }
306
+ }
307
+
71
308
  function Get-OrchestrationEpicScopeSelector {
72
309
  <#
73
310
  .SYNOPSIS
@@ -33,8 +33,6 @@ try { . (Join-Path $PSScriptRoot 'enforce-orchestration-preimplementation-gate-e
33
33
  # Shared command-line parser (issue #545): per-segment scan text and structural matching.
34
34
  try { . (Join-Path $PSScriptRoot 'hook-command-scanner.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-scanner.ps1' -ErrorRecord $_ }
35
35
  try { . (Join-Path $PSScriptRoot 'hook-command-invocation.ps1') } catch { Add-HookDependencyFailure -Name 'hook-command-invocation.ps1' -ErrorRecord $_ }
36
- # The readiness checkpoint this gate reads and names in its block message.
37
- $script:CheckpointPath = 'artifacts/orchestration/orchestrator-state.json'
38
36
 
39
37
  # Every orchestration checkpoint a planner or orchestrator surface writes. Writing one
40
38
  # of these is orchestration bookkeeping, not implementation, so the gate must not
@@ -270,7 +268,7 @@ function Test-OrchestrationReady {
270
268
  }
271
269
  $lifecycleReady = $false
272
270
  if ($Payload.PSObject.Properties.Name -contains 'lifecycle_ready') {
273
- $lifecycleReady = [bool]$Payload.lifecycle_ready
271
+ $lifecycleReady = ($Payload.lifecycle_ready -is [bool]) -and $Payload.lifecycle_ready
274
272
  }
275
273
 
276
274
  if (-not $issueNum -or -not $featureFolder -or -not $routeId -or -not $lifecycleReady) {
@@ -284,17 +282,6 @@ function Test-OrchestrationReady {
284
282
  )
285
283
  }
286
284
 
287
- function Get-CheckpointContent {
288
- [CmdletBinding()]
289
- [OutputType([string])]
290
- param()
291
-
292
- if (-not (Test-Path -LiteralPath $script:CheckpointPath)) {
293
- return ''
294
- }
295
- return Get-Content -Raw -LiteralPath $script:CheckpointPath
296
- }
297
-
298
285
  function Get-OrchestrationPreimplementationGateAllowDecision {
299
286
  [CmdletBinding()]
300
287
  [OutputType([System.Collections.Specialized.OrderedDictionary])]
@@ -445,8 +432,12 @@ function Invoke-OrchestrationPreimplementationGateDecision {
445
432
  Get-OrchestrationModeDenyReason -Mode $mode -Failure $failure)
446
433
  }
447
434
 
435
+ # Truthiness fall-through is kept: an empty -CheckpointRaw resolves like an unbound one.
436
+ # The checkpoint is read beneath the worktree the call targets (issue #1010).
448
437
  if (-not $CheckpointRaw) {
449
- $CheckpointRaw = Get-CheckpointContent
438
+ $read = Read-OrchestrationGateCheckpoint -Mode 'single-feature' -FilePath $filePath -Command $command
439
+ if (-not $read.Resolved) { return Get-OrchestrationPreimplementationGateBlockDecision -Reason $read.DenyReason }
440
+ $CheckpointRaw = $read.Raw
450
441
  }
451
442
  try {
452
443
  $checkpoint = ConvertFrom-CheckpointJson -Json $CheckpointRaw