@danmoisan/drm-copilot-mcp 1.1.18 → 1.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/out/mcp-server.js +989 -662
  2. package/package.json +3 -2
  3. package/resources/claude-customizations/.claude/agents/atomic-executor.md +11 -0
  4. package/resources/claude-customizations/.claude/agents/atomic-planner.md +10 -0
  5. package/resources/claude-customizations/.claude/agents/epic-orchestrator.md +12 -4
  6. package/resources/claude-customizations/.claude/agents/epic-planner.md +5 -4
  7. package/resources/claude-customizations/.claude/agents/feature-review.md +6 -4
  8. package/resources/claude-customizations/.claude/agents/orchestrator.md +5 -4
  9. package/resources/claude-customizations/.claude/agents/parallel-orchestrator.md +31 -13
  10. package/resources/claude-customizations/.claude/agents/parallel-planner.md +9 -6
  11. package/resources/claude-customizations/.claude/agents/pr-author.md +15 -2
  12. package/resources/claude-customizations/.claude/agents/prd-feature.md +1 -1
  13. package/resources/claude-customizations/.claude/hooks/check-powershell-test-purity.ps1 +7 -1
  14. package/resources/claude-customizations/.claude/hooks/check-python-test-purity.ps1 +7 -1
  15. package/resources/claude-customizations/.claude/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
  16. package/resources/claude-customizations/.claude/hooks/enforce-completion-consistency.ps1 +111 -46
  17. package/resources/claude-customizations/.claude/hooks/enforce-completion-helpers.ps1 +105 -0
  18. package/resources/claude-customizations/.claude/hooks/enforce-discovery-artifact-gate.ps1 +8 -1
  19. package/resources/claude-customizations/.claude/hooks/enforce-epic-invocation-origin.ps1 +7 -1
  20. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate-resolution.ps1 +116 -59
  21. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +55 -23
  22. package/resources/claude-customizations/.claude/hooks/enforce-epic-wave-barrier.ps1 +74 -75
  23. package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate-resolution.ps1 +127 -35
  24. package/resources/claude-customizations/.claude/hooks/enforce-epic-worktree-removal-gate.ps1 +61 -57
  25. package/resources/claude-customizations/.claude/hooks/enforce-evidence-locations.ps1 +7 -1
  26. package/resources/claude-customizations/.claude/hooks/enforce-feature-folder-order.ps1 +129 -39
  27. package/resources/claude-customizations/.claude/hooks/enforce-mermaid-validation.ps1 +7 -1
  28. package/resources/claude-customizations/.claude/hooks/enforce-model-routing-receipt.ps1 +9 -3
  29. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +39 -51
  30. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
  31. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
  32. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
  33. package/resources/claude-customizations/.claude/hooks/enforce-orchestration-preimplementation-gate.ps1 +17 -12
  34. package/resources/claude-customizations/.claude/hooks/enforce-parallel-abandon-gate.ps1 +9 -3
  35. package/resources/claude-customizations/.claude/hooks/enforce-parallel-cohort-barrier.ps1 +65 -50
  36. package/resources/claude-customizations/.claude/hooks/enforce-parallel-drift-gate.ps1 +49 -42
  37. package/resources/claude-customizations/.claude/hooks/enforce-parallel-worktree-removal-gate.ps1 +54 -72
  38. package/resources/claude-customizations/.claude/hooks/enforce-powershell-batch-budget.ps1 +8 -2
  39. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-command-allowlist.ps1 +279 -0
  40. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill-helpers.ps1 +129 -75
  41. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.artifact-root.ps1 +233 -0
  42. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.docs-only.ps1 +224 -0
  43. package/resources/claude-customizations/.claude/hooks/enforce-pr-author-skill.ps1 +69 -24
  44. package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner-helpers.ps1 +29 -18
  45. package/resources/claude-customizations/.claude/hooks/enforce-prd-feature-before-planner.ps1 +10 -4
  46. package/resources/claude-customizations/.claude/hooks/enforce-promotion-mcp-only.ps1 +14 -5
  47. package/resources/claude-customizations/.claude/hooks/enforce-python-batch-budget.ps1 +8 -2
  48. package/resources/claude-customizations/.claude/hooks/feature-folder-resolution.ps1 +373 -0
  49. package/resources/claude-customizations/.claude/hooks/feature-review-coverage-thresholds.ps1 +85 -0
  50. package/resources/claude-customizations/.claude/hooks/hook-command-heredoc.ps1 +119 -0
  51. package/resources/claude-customizations/.claude/hooks/hook-command-invocation-operands.ps1 +198 -0
  52. package/resources/claude-customizations/.claude/hooks/hook-command-invocation.ps1 +254 -255
  53. package/resources/claude-customizations/.claude/hooks/hook-command-payload-powershell.ps1 +201 -0
  54. package/resources/claude-customizations/.claude/hooks/hook-command-payload.ps1 +484 -0
  55. package/resources/claude-customizations/.claude/hooks/hook-command-scanner.ps1 +27 -110
  56. package/resources/claude-customizations/.claude/hooks/hook-dependency-guard.ps1 +114 -0
  57. package/resources/claude-customizations/.claude/hooks/hook-docs-only-diff.ps1 +493 -0
  58. package/resources/claude-customizations/.claude/hooks/subagentstop-envelope.ps1 +192 -0
  59. package/resources/claude-customizations/.claude/hooks/validate-bash.ps1 +9 -3
  60. package/resources/claude-customizations/.claude/hooks/validate-discovery-artifact-gate.ps1 +40 -42
  61. package/resources/claude-customizations/.claude/hooks/validate-executor-output.ps1 +66 -38
  62. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-metrics.ps1 +180 -0
  63. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage-rules.ps1 +195 -0
  64. package/resources/claude-customizations/.claude/hooks/validate-feature-review-coverage.ps1 +141 -395
  65. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-resolution.ps1 +311 -0
  66. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output-routing.ps1 +170 -0
  67. package/resources/claude-customizations/.claude/hooks/validate-orchestrator-output.ps1 +115 -190
  68. package/resources/claude-customizations/.claude/hooks/validate-planner-output.ps1 +64 -32
  69. package/resources/claude-customizations/.claude/hooks/validate-pr-author-output.ps1 +39 -44
  70. package/resources/claude-customizations/.claude/hooks/validate-prd-feature-output.ps1 +43 -14
  71. package/resources/claude-customizations/.claude/hooks/validate-required-artifact-output.ps1 +66 -36
  72. package/resources/claude-customizations/.claude/hooks/validate-task-researcher-output.ps1 +31 -34
  73. package/resources/claude-customizations/.claude/lib/bash/mutate-parallel-run.sh +191 -0
  74. package/resources/claude-customizations/.claude/lib/bash/parallel-cohorts.sh +13 -3
  75. package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-cli.sh +152 -0
  76. package/resources/claude-customizations/.claude/lib/bash/parallel-mutation-ops.sh +193 -0
  77. package/resources/claude-customizations/.claude/lib/bash/parallel-mutation.sh +322 -0
  78. package/resources/claude-customizations/.claude/lib/bash/remove-parallel-item.sh +146 -0
  79. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +23 -33
  80. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusTokenShape.psm1 +86 -6
  81. package/resources/claude-customizations/.claude/lib/ci-gate/Invoke-CiGateParser.ps1 +91 -19
  82. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateEpicWaveBarrier.psm1 +346 -0
  83. package/resources/claude-customizations/.claude/lib/orchestrator-state/OrchestratorStateIssueAdoption.psm1 +24 -3
  84. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeItemResolution.psm1 +79 -2
  85. package/resources/claude-customizations/.claude/lib/worktree-resolution/WorktreeRunResolution.psm1 +3 -3
  86. package/resources/claude-customizations/.claude/rules/architecture-boundaries.md +5 -5
  87. package/resources/claude-customizations/.claude/rules/csharp.md +2 -2
  88. package/resources/claude-customizations/.claude/rules/general-code-change.md +1 -1
  89. package/resources/claude-customizations/.claude/rules/general-unit-test.md +3 -2
  90. package/resources/claude-customizations/.claude/rules/orchestrator-state.md +37 -4
  91. package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +50 -5
  92. package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +47 -8
  93. package/resources/claude-customizations/.claude/rules/quality-tiers.md +11 -7
  94. package/resources/claude-customizations/.claude/rules/shell.md +10 -8
  95. package/resources/claude-customizations/.claude/rules/typescript.md +1 -1
  96. package/resources/claude-customizations/.claude/settings.json +3 -4
  97. package/resources/claude-customizations/.claude/skills/acceptance-criteria-tracking/SKILL.md +1 -1
  98. package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +5 -1
  99. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_detached_lib.sh +1 -1
  100. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh +2 -0
  101. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_scan_helper.sh +2 -0
  102. package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +33 -6
  103. package/resources/claude-customizations/.claude/skills/epic-plan/SKILL.md +1 -1
  104. package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +10 -1
  105. package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +1 -1
  106. package/resources/claude-customizations/.claude/skills/feature-review-workflow/SKILL.md +4 -3
  107. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +14 -6
  108. package/resources/claude-customizations/.claude/skills/parallel-add/SKILL.md +52 -14
  109. package/resources/claude-customizations/.claude/skills/parallel-close/SKILL.md +22 -9
  110. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +79 -16
  111. package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +63 -7
  112. package/resources/claude-customizations/.claude/skills/parallel-remove/SKILL.md +35 -12
  113. package/resources/claude-customizations/.claude/skills/pr-author/SKILL.md +3 -1
  114. package/resources/claude-customizations/.claude/skills/quota-throttling/SKILL.md +1 -1
  115. package/resources/claude-customizations/.claude/skills/remediation-handoff-atomic-planner/SKILL.md +2 -2
  116. package/resources/claude-customizations/pack-manifests/core.json +23 -0
  117. package/resources/codex-and-agents-customizations/.agents/skills/acceptance-criteria-tracking/SKILL.md +1 -1
  118. package/resources/codex-and-agents-customizations/.agents/skills/architecture-boundaries/SKILL.md +5 -5
  119. package/resources/codex-and-agents-customizations/.agents/skills/atomic-executor/SKILL.md +11 -0
  120. package/resources/codex-and-agents-customizations/.agents/skills/atomic-plan-contract/SKILL.md +4 -0
  121. package/resources/codex-and-agents-customizations/.agents/skills/atomic-planner/SKILL.md +10 -0
  122. package/resources/codex-and-agents-customizations/.agents/skills/csharp/SKILL.md +2 -2
  123. package/resources/codex-and-agents-customizations/.agents/skills/csharp-qa-gate/SKILL.md +2 -2
  124. package/resources/codex-and-agents-customizations/.agents/skills/epic-orchestrate/SKILL.md +8 -0
  125. package/resources/codex-and-agents-customizations/.agents/skills/epic-plan/SKILL.md +17 -1
  126. package/resources/codex-and-agents-customizations/.agents/skills/epic-run/SKILL.md +2 -1
  127. package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +10 -1
  128. package/resources/codex-and-agents-customizations/.agents/skills/feature-review-workflow/SKILL.md +13 -5
  129. package/resources/codex-and-agents-customizations/.agents/skills/general-code-change/SKILL.md +1 -1
  130. package/resources/codex-and-agents-customizations/.agents/skills/general-unit-test/SKILL.md +3 -2
  131. package/resources/codex-and-agents-customizations/.agents/skills/orchestrate/SKILL.md +15 -6
  132. package/resources/codex-and-agents-customizations/.agents/skills/orchestrator-workflow/SKILL.md +1 -1
  133. package/resources/codex-and-agents-customizations/.agents/skills/quality-tiers/SKILL.md +11 -7
  134. package/resources/codex-and-agents-customizations/.agents/skills/translate-claude-to-codex/SKILL.md +1 -1
  135. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp/SKILL.md +2 -2
  136. package/resources/codex-and-agents-customizations/.agents-variants/csharp-legacy/skills/csharp-qa-gate/SKILL.md +2 -2
  137. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c1.toml +11 -0
  138. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c2.toml +11 -0
  139. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3-elevated.toml +11 -0
  140. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c3.toml +11 -0
  141. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor-c4.toml +11 -0
  142. package/resources/codex-and-agents-customizations/.codex/agents/atomic-executor.toml +11 -0
  143. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c1.toml +10 -0
  144. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c2.toml +10 -0
  145. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3-elevated.toml +10 -0
  146. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c3.toml +10 -0
  147. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner-c4.toml +10 -0
  148. package/resources/codex-and-agents-customizations/.codex/agents/atomic-planner.toml +10 -0
  149. package/resources/codex-and-agents-customizations/.codex/agents/epic-orchestrator.toml +2 -1
  150. package/resources/codex-and-agents-customizations/.codex/agents/feature-review.toml +6 -6
  151. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c1.toml +2 -2
  152. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c2.toml +2 -2
  153. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3-elevated.toml +2 -2
  154. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c3.toml +2 -2
  155. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator-c4.toml +2 -2
  156. package/resources/codex-and-agents-customizations/.codex/agents/orchestrator.toml +2 -2
  157. package/resources/codex-and-agents-customizations/.codex/codex-web-setup.sh +318 -273
  158. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  159. package/resources/codex-and-agents-customizations/.codex/hooks/check-powershell-test-purity.ps1 +7 -1
  160. package/resources/codex-and-agents-customizations/.codex/hooks/check-python-test-purity.ps1 +7 -1
  161. package/resources/codex-and-agents-customizations/.codex/hooks/codex-epic-child-launch-attestation.ps1 +1 -1
  162. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-checkpoint-monotonic.ps1 +7 -1
  163. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-codex-model-routing.ps1 +8 -2
  164. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-consistency.ps1 +97 -44
  165. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-completion-helpers.ps1 +105 -0
  166. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-child-worktree-binding.ps1 +7 -1
  167. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-merge-gate.ps1 +37 -5
  168. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-planning-only.ps1 +6 -0
  169. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-root-invocation.ps1 +7 -1
  170. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-wave-barrier.ps1 +7 -1
  171. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-epic-worktree-removal-gate.ps1 +54 -41
  172. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-evidence-locations.ps1 +7 -1
  173. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-epic-scope.ps1 +35 -14
  174. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-helpers.ps1 +31 -58
  175. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-modes.ps1 +63 -47
  176. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate-targets.ps1 +433 -0
  177. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-orchestration-preimplementation-gate.ps1 +24 -11
  178. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-powershell-batch-budget.ps1 +8 -2
  179. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-promotion-mcp-only.ps1 +13 -4
  180. package/resources/codex-and-agents-customizations/.codex/hooks/enforce-python-batch-budget.ps1 +8 -2
  181. package/resources/codex-and-agents-customizations/.codex/hooks/feature-folder-resolution.ps1 +373 -0
  182. package/resources/codex-and-agents-customizations/.codex/hooks/feature-review-coverage-thresholds.ps1 +85 -0
  183. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-heredoc.ps1 +119 -0
  184. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation-operands.ps1 +198 -0
  185. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-invocation.ps1 +254 -255
  186. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload-powershell.ps1 +201 -0
  187. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-payload.ps1 +484 -0
  188. package/resources/codex-and-agents-customizations/.codex/hooks/hook-command-scanner.ps1 +27 -110
  189. package/resources/codex-and-agents-customizations/.codex/hooks/hook-dependency-guard.ps1 +114 -0
  190. package/resources/codex-and-agents-customizations/.codex/hooks/hook-docs-only-diff.ps1 +493 -0
  191. package/resources/codex-and-agents-customizations/.codex/hooks/validate-bash.ps1 +8 -2
  192. package/resources/codex-and-agents-customizations/.codex/hooks/validate-codex-subagent-routing.ps1 +7 -1
  193. package/resources/codex-and-agents-customizations/.codex/hooks/validate-feature-review-coverage.ps1 +24 -8
  194. package/resources/codex-and-agents-customizations/pack-manifests/core.json +9 -0
  195. package/resources/customizations/.github/agents/csharp-typed-engineer.agent.md +2 -2
  196. package/resources/customizations/.github/instructions/csharp-code-change.instructions.md +4 -4
  197. package/resources/customizations/.github/instructions/csharp-unit-test.instructions.md +2 -2
  198. package/resources/customizations/.github/skills/acceptance-criteria-tracking/SKILL.md +1 -1
  199. package/resources/customizations/.github/skills/atomic-plan-contract/SKILL.md +4 -0
  200. package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +10 -1
  201. package/resources/customizations/.github/skills/feature-review-workflow/SKILL.md +1 -1
  202. package/resources/powershell/PoshQC/PoshQC.Coverage.psm1 +314 -0
  203. package/resources/powershell/PoshQC/PoshQC.Testing.psm1 +25 -28
  204. package/resources/powershell/PoshQC/PoshQC.psm1 +1 -0
  205. package/resources/powershell/PoshQC/README.md +8 -2
  206. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +2 -319
@@ -44,11 +44,17 @@
44
44
  exactly the two members that matter most.
45
45
  - Substring search uses [System.StringComparison]::Ordinal so the result
46
46
  is culture-independent and matches Python's byte-wise 'in' operator.
47
- - Both predicates are total on every string, including the empty string, a
48
- token consisting only of a marker, and a bare bracket pair. Neither
49
- throws for any input, because the classifier that calls them runs over
50
- every inline-code span in a document and a throw would abort an entire
51
- derivation over one stray span.
47
+ - Every predicate is total on every string, including the empty string, a
48
+ token consisting only of a marker, a bare bracket pair, and a lone dot.
49
+ None throws for any input, because the classifier that calls them runs
50
+ over every inline-code span in a document and a throw would abort an
51
+ entire derivation over one stray span.
52
+ - Test-FileShapedComponent (issue #797) ports is_file_shaped_component.
53
+ Its extension pattern text is identical to FILE_EXTENSION_PATTERN_TEXT
54
+ and its known-name set equals KNOWN_FILE_NAMES; a Pester test reads both
55
+ from the Python source and pins them equal. A non-ASCII extension is
56
+ rejected before lower-casing (issue #903); ToLowerInvariant then matches
57
+ Python's str.lower on ASCII input, and known-name membership is ordinal.
52
58
  CONVENTION: this module fails fast at module scope and imports its siblings with -ErrorAction Stop.
53
59
  #>
54
60
 
@@ -84,6 +90,30 @@ $script:PlaceholderMarker = [string[]]@(
84
90
  $script:FeatureCorpusPrefix = 'docs/features/'
85
91
  $script:FeatureFolderSegmentIndex = 1
86
92
 
93
+ # File-shape extension pattern (issue #797). A final component names a file when
94
+ # the text after its last dot, lower-cased, is an ASCII letter followed by ASCII
95
+ # letters or digits. The pattern text is identical to FILE_EXTENSION_PATTERN_TEXT
96
+ # in the Python reference; \A and \z anchor the whole string without admitting a
97
+ # trailing newline, which matches Python's re.fullmatch. The regex is built with
98
+ # no options, so matching is case-sensitive and the explicit ASCII classes match
99
+ # exactly the inputs the Python pattern matches.
100
+ $script:FileExtensionPatternText = '[a-z][a-z0-9]*'
101
+ $script:FileExtensionPattern = [regex]::new('\A' + $script:FileExtensionPatternText + '\z')
102
+ $script:NonAsciiPattern = [regex]::new('[^\x00-\x7F]')
103
+
104
+ # Known extensionless file names and dotfiles (issue #797). Membership is exact
105
+ # and ordinal, matching Python's frozenset membership. The set is closed and is
106
+ # pinned equal to KNOWN_FILE_NAMES in the Python reference by a Pester parity
107
+ # test that reads the Python source, so edit both files together.
108
+ $script:KnownFileName = [System.Collections.Generic.HashSet[string]]::new(
109
+ [string[]] @(
110
+ 'Dockerfile', 'Makefile', 'LICENSE', 'CODEOWNERS', 'NOTICE', '.gitignore',
111
+ '.gitattributes', '.gitkeep', '.gitmodules', '.vscodeignore', '.npmignore',
112
+ '.npmrc', '.nvmrc', '.editorconfig', '.prettierrc', '.prettierignore',
113
+ '.eslintignore', '.shellcheckrc'
114
+ ),
115
+ [StringComparer]::Ordinal)
116
+
87
117
  function Test-PlaceholderMarker {
88
118
  <#
89
119
  .SYNOPSIS
@@ -184,6 +214,56 @@ function Test-MultipleFeatureFolderSpan {
184
214
  return $false
185
215
  }
186
216
 
217
+ function Test-FileShapedComponent {
218
+ <#
219
+ .SYNOPSIS
220
+ Report whether a final path component names a file (issue #797).
221
+
222
+ .DESCRIPTION
223
+ Port of is_file_shaped_component. The classifier formerly admitted a
224
+ wildcard-free token only when its extension appeared in a fixed
225
+ allowlist, so files a plan writes with an unlisted extension, dotfiles,
226
+ and extensionless names were dropped from the derived radius. This
227
+ predicate replaces the allowlist with a structural rule that still
228
+ rejects the directory-shaped tokens of issue #489: a component with no
229
+ dot, a dot-leading component outside the known-name set, a digit-led
230
+ tail, and a trailing dot all report false.
231
+
232
+ .PARAMETER Component
233
+ The final path component, after any :<line> suffix has been stripped.
234
+ The empty string is accepted and reports false.
235
+
236
+ .OUTPUTS
237
+ System.Boolean. True when the component is an ordinal member of the
238
+ known-name set, or when it has a non-empty stem before its last dot and
239
+ the lower-cased text after that dot fully matches the extension pattern;
240
+ otherwise false.
241
+ #>
242
+ [CmdletBinding()]
243
+ [OutputType([bool])]
244
+ param(
245
+ [Parameter(Mandatory = $true)]
246
+ [AllowEmptyString()]
247
+ [string] $Component
248
+ )
249
+
250
+ if ($script:KnownFileName.Contains($Component)) {
251
+ return $true
252
+ }
253
+
254
+ # LastIndexOf returns -1 when there is no dot and 0 when the dot leads the
255
+ # component; both leave no stem, so neither names a file by this rule.
256
+ $dotIndex = $Component.LastIndexOf('.')
257
+ if ($dotIndex -le 0) {
258
+ return $false
259
+ }
260
+
261
+ $extension = $Component.Substring($dotIndex + 1)
262
+ if ($script:NonAsciiPattern.IsMatch($extension)) { return $false }
263
+ return $script:FileExtensionPattern.IsMatch($extension.ToLowerInvariant())
264
+ }
265
+
187
266
  Export-ModuleMember -Function `
188
267
  Test-PlaceholderMarker, `
189
- Test-MultipleFeatureFolderSpan
268
+ Test-MultipleFeatureFolderSpan, `
269
+ Test-FileShapedComponent
@@ -5,7 +5,7 @@
5
5
 
6
6
  .DESCRIPTION
7
7
  Consumes the JSON array emitted by
8
- `gh pr checks --required --json bucket,name,state,link,workflow` and produces
8
+ `gh pr checks --json bucket,name,state,link,workflow` and produces
9
9
  the `ci_gate` object the orchestrator writes to its checkpoint. The object
10
10
  carries the five contract fields: head_sha, pr_pipeline_run_id,
11
11
  pr_pipeline_run_url, conclusion, and verified_at.
@@ -17,25 +17,33 @@
17
17
  the logic is deterministically testable.
18
18
 
19
19
  Conclusion derivation (per the documented bucket mapping):
20
- - Any required check with bucket 'fail' or 'cancel' -> conclusion 'failure'
21
- - Else any required check with bucket 'pending' -> conclusion 'pending'
20
+ - Any check with bucket 'fail' or 'cancel' -> conclusion 'failure'
21
+ - Else any check with bucket 'pending' -> conclusion 'pending'
22
22
  - Else (all checks 'pass' or 'skipping', or empty set) -> conclusion 'success'
23
- An empty required-check set is treated as 'success' (vacuously satisfied: no
24
- required check can fail or be in progress). An unrecognized bucket value is a
23
+ An empty check set is treated as 'success' (vacuously satisfied: no
24
+ check can fail or be in progress). An unrecognized bucket value is a
25
25
  fail-fast error so the parser never silently passes an enum it does not
26
26
  understand.
27
27
 
28
+ Epic-child guard (-RequireWorkflow): when -RequireWorkflow names a workflow
29
+ (S9 passes 'CI' when the checkpoint epic_mode is true), the empty-set rule
30
+ above does not apply. Failure and pending precedence is unchanged over every
31
+ observed check; the conclusion is 'success' only when at least one observed
32
+ check whose workflow property equals the name (case-sensitive) has bucket
33
+ 'pass', and 'pending' otherwise. An empty or null check set therefore yields
34
+ 'pending'. The default value ('') keeps the behavior described above.
35
+
28
36
  The verified_at timestamp is produced through an injectable clock delegate
29
37
  (-NowProvider) so tests can assert an exact deterministic value without
30
38
  reading the wall clock.
31
39
 
32
40
  .PARAMETER ChecksJson
33
- The JSON array string emitted by `gh pr checks --required --json ...`. Each
41
+ The JSON array string emitted by `gh pr checks --json ...`. Each
34
42
  element is expected to expose at least a `bucket` property. Accepts pipeline
35
43
  / stdin input so the orchestrator can pipe the `gh` output directly.
36
44
 
37
45
  .PARAMETER HeadSha
38
- The PR head SHA the required checks were observed against. Recorded verbatim
46
+ The PR head SHA the queried checks were observed against. Recorded verbatim
39
47
  as ci_gate.head_sha.
40
48
 
41
49
  .PARAMETER PrPipelineRunId
@@ -51,15 +59,26 @@
51
59
  ci_gate.verified_at. Defaults to a UTC Get-Date formatted as ISO-8601. Tests
52
60
  inject a fixed delegate to make verified_at deterministic.
53
61
 
62
+ .PARAMETER RequireWorkflow
63
+ Optional workflow name (default ''). When non-empty, the conclusion is
64
+ 'success' only after at least one check whose `workflow` property equals
65
+ this value (case-sensitive) has bucket 'pass'; an empty or null check set
66
+ yields 'pending'. S9 passes 'CI' for an epic-child PR. A whitespace-only
67
+ value is rejected with an error.
68
+
54
69
  .PARAMETER AsJson
55
70
  When set, emits the ci_gate object as a JSON string instead of a PowerShell
56
71
  object. The default (object) output is convenient for in-process callers; the
57
72
  JSON output is convenient for checkpoint serialization.
58
73
 
59
74
  .EXAMPLE
60
- gh pr checks --required --json bucket,name,state,link,workflow |
75
+ gh pr checks --json bucket,name,state,link,workflow |
61
76
  ./.claude/lib/ci-gate/Invoke-CiGateParser.ps1 -HeadSha $sha
62
77
 
78
+ .EXAMPLE
79
+ gh pr checks --json bucket,name,state,link,workflow |
80
+ ./.claude/lib/ci-gate/Invoke-CiGateParser.ps1 -HeadSha $sha -RequireWorkflow CI
81
+
63
82
  .OUTPUTS
64
83
  A PSCustomObject (or JSON string when -AsJson is set) with properties
65
84
  head_sha, pr_pipeline_run_id, pr_pipeline_run_url, conclusion, verified_at.
@@ -84,6 +103,9 @@ param(
84
103
  [ValidateNotNull()]
85
104
  [ScriptBlock]$NowProvider = { (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') },
86
105
 
106
+ [Parameter(Mandatory = $false)]
107
+ [string]$RequireWorkflow = '',
108
+
87
109
  [Parameter(Mandatory = $false)]
88
110
  [switch]$AsJson
89
111
  )
@@ -96,7 +118,7 @@ begin {
96
118
  function Get-CiGateConclusion {
97
119
  <#
98
120
  .SYNOPSIS
99
- Pure derivation of ci_gate.conclusion from a parsed required-check set.
121
+ Pure derivation of ci_gate.conclusion from a parsed check set.
100
122
 
101
123
  .DESCRIPTION
102
124
  Implements the documented bucket precedence with no I/O and no external
@@ -109,9 +131,20 @@ begin {
109
131
  bucket value outside the known enum throws a fail-fast error naming the
110
132
  unrecognized value, preventing a silent pass on an unknown state.
111
133
 
134
+ With -RequireWorkflow set, one rule follows the pending rule: when no
135
+ check whose `workflow` property equals the name (case-sensitive) has
136
+ bucket 'pass', the result is 'pending'. An empty or null set then yields
137
+ 'pending' instead of 'success'.
138
+
112
139
  .PARAMETER Checks
113
- The parsed required-check collection (each element exposing a `bucket`
114
- property). May be $null or empty, which yields 'success'.
140
+ The parsed check collection (each element exposing a `bucket`
141
+ property). May be $null or empty, which yields 'success' unless
142
+ -RequireWorkflow is set.
143
+
144
+ .PARAMETER RequireWorkflow
145
+ Optional workflow name; '' (default) disables the guard. A
146
+ whitespace-only value throws. An element without a `workflow` property
147
+ never matches.
115
148
 
116
149
  .OUTPUTS
117
150
  One of the strings 'success', 'failure', or 'pending'.
@@ -124,12 +157,27 @@ begin {
124
157
  param(
125
158
  [Parameter(Mandatory = $false)]
126
159
  [AllowNull()]
127
- [object[]]$Checks
160
+ [object[]]$Checks,
161
+
162
+ [Parameter(Mandatory = $false)]
163
+ [string]$RequireWorkflow = ''
128
164
  )
129
165
 
130
- # Empty or null required-check set is vacuously satisfied: there is no check
131
- # that can fail or be in progress, so the gate concludes 'success'.
166
+ # A non-empty, whitespace-only workflow name is invalid input. Reject it
167
+ # rather than silently disabling the guard and restoring vacuous success.
168
+ if ($RequireWorkflow.Length -gt 0 -and [string]::IsNullOrWhiteSpace($RequireWorkflow)) {
169
+ throw "Invoke-CiGateParser: -RequireWorkflow must be '' or a workflow name; a whitespace-only value is not accepted."
170
+ }
171
+
172
+ $requireWorkflowGuard = $RequireWorkflow.Length -gt 0
173
+
174
+ # Empty or null check set. Without the guard it is vacuously satisfied (no
175
+ # check can fail or be in progress); with the guard no passing check from
176
+ # the named workflow was observed, so the gate stays 'pending'.
132
177
  if ($null -eq $Checks -or $Checks.Count -eq 0) {
178
+ if ($requireWorkflowGuard) {
179
+ return 'pending'
180
+ }
133
181
  return 'success'
134
182
  }
135
183
 
@@ -137,7 +185,10 @@ begin {
137
185
  # decision until after confirming nothing failed (failure outranks pending).
138
186
  $anyPending = $false
139
187
 
140
- # Inspect each required check once, classifying by its bucket value. Failure
188
+ # Track whether a passing check from the named workflow was observed.
189
+ $requiredWorkflowPassed = $false
190
+
191
+ # Inspect each check once, classifying by its bucket value. Failure
141
192
  # short-circuits immediately because it is the highest-precedence outcome.
142
193
  foreach ($check in $Checks) {
143
194
  # A check element must expose a bucket; absence is an undefined state and
@@ -152,10 +203,19 @@ begin {
152
203
  # change semantics because failure short-circuits via return; pending is
153
204
  # only recorded (not returned) so a later failure can still take priority.
154
205
  switch ($bucket) {
155
- 'fail' { return 'failure' } # a failed required check is terminal-non-success
156
- 'cancel' { return 'failure' } # a cancelled required check is treated conservatively as failure
206
+ 'fail' { return 'failure' } # a failed check is terminal-non-success
207
+ 'cancel' { return 'failure' } # a cancelled check is treated conservatively as failure
157
208
  'pending' { $anyPending = $true } # in-progress; defer until failures are ruled out
158
- 'pass' { } # passing check contributes to success; no state change
209
+ 'pass' {
210
+ # Under the guard, record a pass from the named workflow. The
211
+ # property test keeps an element without `workflow` from
212
+ # throwing under Set-StrictMode; such an element never matches.
213
+ if ($requireWorkflowGuard -and
214
+ ($check.PSObject.Properties.Name -contains 'workflow') -and
215
+ ([string]$check.workflow -ceq $RequireWorkflow)) {
216
+ $requiredWorkflowPassed = $true
217
+ }
218
+ }
159
219
  'skipping' { } # skipped check is non-blocking; neither failure nor pending
160
220
  default {
161
221
  # Unknown bucket: fail fast and name the value so the unsupported
@@ -171,6 +231,12 @@ begin {
171
231
  return 'pending'
172
232
  }
173
233
 
234
+ # With the guard, nothing failed or is pending, but success also requires
235
+ # at least one passing check from the named workflow.
236
+ if ($requireWorkflowGuard -and -not $requiredWorkflowPassed) {
237
+ return 'pending'
238
+ }
239
+
174
240
  return 'success'
175
241
  }
176
242
 
@@ -241,6 +307,8 @@ begin {
241
307
  See script-level parameter of the same name.
242
308
  .PARAMETER NowProvider
243
309
  See script-level parameter of the same name.
310
+ .PARAMETER RequireWorkflow
311
+ See script-level parameter of the same name.
244
312
  .PARAMETER AsJson
245
313
  See script-level parameter of the same name.
246
314
 
@@ -269,6 +337,9 @@ begin {
269
337
  [ValidateNotNull()]
270
338
  [ScriptBlock]$NowProvider = { (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') },
271
339
 
340
+ [Parameter(Mandatory = $false)]
341
+ [string]$RequireWorkflow = '',
342
+
272
343
  [Parameter(Mandatory = $false)]
273
344
  [switch]$AsJson
274
345
  )
@@ -288,7 +359,7 @@ begin {
288
359
  # downstream Count/foreach logic uniform for the empty, single, and many cases.
289
360
  $checks = @($parsed)
290
361
 
291
- $conclusion = Get-CiGateConclusion -Checks $checks
362
+ $conclusion = Get-CiGateConclusion -Checks $checks -RequireWorkflow $RequireWorkflow
292
363
 
293
364
  # Resolve the timestamp through the injected delegate so tests can pin an
294
365
  # exact value; the default delegate reads UTC wall-clock time.
@@ -324,6 +395,7 @@ process {
324
395
  -PrPipelineRunId $PrPipelineRunId `
325
396
  -PrPipelineRunUrl $PrPipelineRunUrl `
326
397
  -NowProvider $NowProvider `
398
+ -RequireWorkflow $RequireWorkflow `
327
399
  -AsJson:$AsJson
328
400
  }
329
401
  }