@danmoisan/drm-copilot-mcp 1.0.26 → 1.0.27

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 (38) hide show
  1. package/out/mcp-server.js +542 -41
  2. package/package.json +1 -1
  3. package/resources/claude-customizations/.claude/hooks/enforce-epic-merge-gate.ps1 +109 -5
  4. package/resources/claude-customizations/.claude/hooks/enforce-mermaid-validation.ps1 +390 -0
  5. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadius.psm1 +105 -2
  6. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusConfig.psm1 +32 -52
  7. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusExtraction.psm1 +107 -99
  8. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusNormalization.psm1 +295 -0
  9. package/resources/claude-customizations/.claude/lib/blast-radius/BlastRadiusValidation.psm1 +9 -3
  10. package/resources/claude-customizations/.claude/lib/mermaid/MermaidGrammar.psm1 +491 -0
  11. package/resources/claude-customizations/.claude/lib/mermaid/MermaidLineScanner.psm1 +488 -0
  12. package/resources/claude-customizations/.claude/lib/mermaid/MermaidMarkdownFences.psm1 +298 -0
  13. package/resources/claude-customizations/.claude/lib/mermaid/MermaidValidation.psm1 +496 -0
  14. package/resources/claude-customizations/.claude/rules/mermaid.md +142 -0
  15. package/resources/claude-customizations/.claude/rules/parallel-orchestration.md +61 -1
  16. package/resources/claude-customizations/.claude/rules/plan-acceptance-gates.md +116 -0
  17. package/resources/claude-customizations/.claude/settings.json +5 -0
  18. package/resources/claude-customizations/.claude/skills/atomic-plan-contract/SKILL.md +15 -0
  19. package/resources/claude-customizations/.claude/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
  20. package/resources/claude-customizations/.claude/skills/feature-promotion-lifecycle/SKILL.md +6 -0
  21. package/resources/claude-customizations/.claude/skills/mermaid-diagram/SKILL.md +184 -0
  22. package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/c4.md +50 -0
  23. package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/class.md +63 -0
  24. package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/er.md +56 -0
  25. package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/flowchart.md +68 -0
  26. package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/gantt.md +51 -0
  27. package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/other-types.md +82 -0
  28. package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/pie.md +32 -0
  29. package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/sequence.md +63 -0
  30. package/resources/claude-customizations/.claude/skills/mermaid-diagram/references/state.md +49 -0
  31. package/resources/claude-customizations/.claude/skills/parallel-orchestrate/SKILL.md +8 -7
  32. package/resources/claude-customizations/.claude/skills/parallel-plan/SKILL.md +24 -4
  33. package/resources/claude-customizations/config/blast-radius.json +8 -0
  34. package/resources/claude-customizations/pack-manifests/core.json +19 -1
  35. package/resources/codex-and-agents-customizations/.agents/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
  36. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  37. package/resources/customizations/.github/skills/evidence-and-timestamp-conventions/SKILL.md +13 -0
  38. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +16 -1
@@ -0,0 +1,298 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Markdown fenced-block tracker and opt-out marker detector for the Mermaid gate.
4
+
5
+ .DESCRIPTION
6
+ Extracts ```` ```mermaid ```` blocks from Markdown text without parsing
7
+ CommonMark. The rule set is deliberately small and each rule exists for a
8
+ stated reason:
9
+
10
+ - An opening fence is a run of three or more backticks or three or more
11
+ tildes, indented up to three spaces, optionally prefixed by blockquote
12
+ markers, whose info string's first word is `mermaid` (case-insensitive).
13
+ - A closing fence uses the same fence character, is at least as long as the
14
+ opening run, carries no info string, and sits at the same blockquote
15
+ depth.
16
+ - A fence stack is maintained so a `mermaid` fence nested inside an outer
17
+ open fence is reported as nested. Documentation showing example Mermaid is
18
+ not a diagram, so the validator must skip it (fail-open item 6).
19
+ - An unclosed fence is tolerated: its collected body is still reported, so a
20
+ diagram at the end of a truncated document is not silently dropped.
21
+ - Body lines of a fence opened inside a blockquote are stripped of their
22
+ `> ` prefix, so a blockquoted diagram validates as its unquoted twin.
23
+ - Tilde fences may contain backtick runs and vice versa, which the
24
+ same-character close rule handles without special cases.
25
+
26
+ The opt-out marker is `<!-- mermaid-validator: ignore -->` on the line
27
+ immediately preceding the opening fence, with no intervening line. Its scope
28
+ is exactly that one block; a later block needs its own marker. The marker
29
+ exists so that documentation deliberately quoting invalid Mermaid is never
30
+ blocked, which would be worse than having no gate at all.
31
+
32
+ Pinned to Mermaid 11.17.0 through MermaidGrammar.psm1. Every function is pure:
33
+ no filesystem, subprocess, network, or wall-clock access, and no input is
34
+ mutated.
35
+ #>
36
+
37
+ Set-StrictMode -Version Latest
38
+
39
+ # The marker text must be exactly `mermaid-validator: ignore` and is
40
+ # case-sensitive. Whitespace is permitted around the line, around the comment
41
+ # delimiters, and a blockquote prefix is tolerated so the marker works inside a
42
+ # quoted passage.
43
+ $script:OptOutMarkerPattern = '^(?:\s{0,3}>\s?)*\s*<!--\s*mermaid-validator: ignore\s*-->\s*$'
44
+
45
+ # Fence line shape: optional blockquote prefixes, up to three spaces of
46
+ # indentation, then the fence run, then the info string.
47
+ $script:FenceLinePattern = '^(?<quote>(?:\s{0,3}>\s?)*)(?<indent>\s{0,3})(?<fence>`{3,}|~{3,})(?<info>.*)$'
48
+
49
+ function Split-MermaidTextLine {
50
+ <#
51
+ .SYNOPSIS
52
+ Splits text into lines, normalizing CRLF, CR, and LF endings.
53
+ .DESCRIPTION
54
+ Line-ending normalization happens once, here, so every downstream rule
55
+ sees the same line array and a CRLF document produces a byte-identical
56
+ verdict to its LF twin.
57
+ #>
58
+ [CmdletBinding()]
59
+ [OutputType([string[]])]
60
+ param(
61
+ [AllowEmptyString()]
62
+ [AllowNull()]
63
+ [string] $Text
64
+ )
65
+
66
+ if ([string]::IsNullOrEmpty($Text)) {
67
+ return [string[]]@()
68
+ }
69
+
70
+ return [string[]]($Text -split '\r\n|\n|\r')
71
+ }
72
+
73
+ function Test-MermaidOptOutMarker {
74
+ <#
75
+ .SYNOPSIS
76
+ Returns $true when a line is the documented Mermaid validator opt-out marker.
77
+ #>
78
+ [CmdletBinding()]
79
+ [OutputType([bool])]
80
+ param(
81
+ [AllowEmptyString()]
82
+ [AllowNull()]
83
+ [string] $Line
84
+ )
85
+
86
+ if ([string]::IsNullOrWhiteSpace($Line)) {
87
+ return $false
88
+ }
89
+
90
+ return [bool]($Line -cmatch $script:OptOutMarkerPattern)
91
+ }
92
+
93
+ function Get-MermaidFenceLine {
94
+ <#
95
+ .SYNOPSIS
96
+ Parses a candidate Markdown fence line.
97
+ .DESCRIPTION
98
+ Returns $null when the line is not a fence line. Otherwise returns an
99
+ ordered dictionary with FenceCharacter, FenceLength, QuoteDepth, Info, and
100
+ IsMermaid (the info string's first word is `mermaid`, case-insensitive).
101
+ #>
102
+ [CmdletBinding()]
103
+ [OutputType([System.Collections.Specialized.OrderedDictionary])]
104
+ param(
105
+ [AllowEmptyString()]
106
+ [AllowNull()]
107
+ [string] $Line
108
+ )
109
+
110
+ if ([string]::IsNullOrEmpty($Line)) {
111
+ return $null
112
+ }
113
+
114
+ $match = [regex]::Match($Line, $script:FenceLinePattern)
115
+ if (-not $match.Success) {
116
+ return $null
117
+ }
118
+
119
+ $fence = $match.Groups['fence'].Value
120
+ $info = $match.Groups['info'].Value.Trim()
121
+ $quoteDepth = ([regex]::Matches($match.Groups['quote'].Value, '>')).Count
122
+
123
+ $firstWord = ''
124
+ if (-not [string]::IsNullOrWhiteSpace($info)) {
125
+ $firstWord = ($info -split '[\s{,]+', 2)[0]
126
+ }
127
+
128
+ return [ordered]@{
129
+ FenceCharacter = [string]$fence[0]
130
+ FenceLength = $fence.Length
131
+ QuoteDepth = $quoteDepth
132
+ Info = $info
133
+ IsMermaid = [bool]($firstWord -imatch '^mermaid$')
134
+ }
135
+ }
136
+
137
+ function Get-MermaidUnquotedLine {
138
+ <#
139
+ .SYNOPSIS
140
+ Strips up to QuoteDepth blockquote markers from the start of a body line.
141
+ .DESCRIPTION
142
+ A fence opened inside a blockquote carries a `> ` prefix on every body
143
+ line. Leaving the prefix in place would make the first body line start
144
+ with `>`, which the validator would read as a non-keyword first line and
145
+ reject. Stripping it is what makes a blockquoted diagram validate the same
146
+ as its unquoted twin.
147
+ #>
148
+ [CmdletBinding()]
149
+ [OutputType([string])]
150
+ param(
151
+ [AllowEmptyString()]
152
+ [AllowNull()]
153
+ [string] $Line,
154
+
155
+ [Parameter(Mandatory)]
156
+ [int] $QuoteDepth
157
+ )
158
+
159
+ if ($QuoteDepth -le 0 -or [string]::IsNullOrEmpty($Line)) {
160
+ return $Line
161
+ }
162
+
163
+ $result = $Line
164
+ for ($count = 0; $count -lt $QuoteDepth; $count++) {
165
+ $stripped = $result -replace '^\s{0,3}>\s?', ''
166
+ if ($stripped -eq $result) {
167
+ break
168
+ }
169
+ $result = $stripped
170
+ }
171
+
172
+ return $result
173
+ }
174
+
175
+ function Test-MermaidFenceClose {
176
+ <#
177
+ .SYNOPSIS
178
+ Returns $true when a parsed fence line closes the supplied open fence.
179
+ #>
180
+ [CmdletBinding()]
181
+ [OutputType([bool])]
182
+ param(
183
+ [Parameter(Mandatory)]
184
+ [System.Collections.Specialized.OrderedDictionary] $Fence,
185
+
186
+ [Parameter(Mandatory)]
187
+ [System.Collections.Specialized.OrderedDictionary] $OpenFence
188
+ )
189
+
190
+ if ($Fence.FenceCharacter -ne $OpenFence.FenceCharacter) {
191
+ return $false
192
+ }
193
+ if ($Fence.FenceLength -lt $OpenFence.FenceLength) {
194
+ return $false
195
+ }
196
+ if ($Fence.QuoteDepth -ne $OpenFence.QuoteDepth) {
197
+ return $false
198
+ }
199
+
200
+ return [string]::IsNullOrEmpty($Fence.Info)
201
+ }
202
+
203
+ function Get-MermaidFenceBlock {
204
+ <#
205
+ .SYNOPSIS
206
+ Extracts every Mermaid fenced block from Markdown text.
207
+ .DESCRIPTION
208
+ Returns an array of ordered dictionaries, one per ```` ```mermaid ````
209
+ block, each with:
210
+ Content the block body, joined with newlines
211
+ StartLine 1-based line number of the opening fence
212
+ BodyStartLine 1-based line number of the first body line
213
+ IsNested the fence opened while another fence was already open
214
+ IsOptedOut the immediately preceding line carried the opt-out marker
215
+ IsClosed a matching closing fence was found
216
+ A document with no Mermaid fence returns an empty array.
217
+ .PARAMETER Content
218
+ The full Markdown text.
219
+ #>
220
+ [CmdletBinding()]
221
+ [OutputType([object[]])]
222
+ param(
223
+ [AllowEmptyString()]
224
+ [AllowNull()]
225
+ [string] $Content
226
+ )
227
+
228
+ $blocks = [System.Collections.Generic.List[object]]::new()
229
+ $lines = @(Split-MermaidTextLine -Text $Content)
230
+ if ($lines.Count -eq 0) {
231
+ return [object[]]@()
232
+ }
233
+
234
+ $stack = [System.Collections.Generic.List[object]]::new()
235
+
236
+ for ($index = 0; $index -lt $lines.Count; $index++) {
237
+ $line = $lines[$index]
238
+ $fence = Get-MermaidFenceLine -Line $line
239
+
240
+ if ($null -ne $fence) {
241
+ if ($stack.Count -gt 0 -and (Test-MermaidFenceClose -Fence $fence -OpenFence $stack[$stack.Count - 1].Fence)) {
242
+ $entry = $stack[$stack.Count - 1]
243
+ $stack.RemoveAt($stack.Count - 1)
244
+ if ($entry.Fence.IsMermaid) {
245
+ $entry.Block.Content = ($entry.Body -join "`n")
246
+ $entry.Block.IsClosed = $true
247
+ $blocks.Add($entry.Block)
248
+ }
249
+ continue
250
+ }
251
+
252
+ $marker = $false
253
+ if ($index -gt 0) {
254
+ $marker = Test-MermaidOptOutMarker -Line $lines[$index - 1]
255
+ }
256
+
257
+ $stack.Add([ordered]@{
258
+ Fence = $fence
259
+ Body = [System.Collections.Generic.List[string]]::new()
260
+ Block = [ordered]@{
261
+ Content = ''
262
+ StartLine = $index + 1
263
+ BodyStartLine = $index + 2
264
+ IsNested = ($stack.Count -gt 0)
265
+ IsOptedOut = $marker
266
+ IsClosed = $false
267
+ }
268
+ })
269
+ continue
270
+ }
271
+
272
+ if ($stack.Count -gt 0) {
273
+ $top = $stack[$stack.Count - 1]
274
+ $stack[$stack.Count - 1].Body.Add((Get-MermaidUnquotedLine -Line $line -QuoteDepth $top.Fence.QuoteDepth))
275
+ }
276
+ }
277
+
278
+ # Unclosed-fence tolerance: report whatever body was collected so a diagram at
279
+ # the end of a truncated document is not silently dropped.
280
+ foreach ($entry in $stack) {
281
+ if ($entry.Fence.IsMermaid) {
282
+ $entry.Block.Content = ($entry.Body -join "`n")
283
+ $blocks.Add($entry.Block)
284
+ }
285
+ }
286
+
287
+ # Unclosed blocks are appended after the closed ones, so sort back into
288
+ # document order to keep the caller's line-number reporting monotonic.
289
+ return [object[]]@($blocks.ToArray() | Sort-Object -Property { $_.StartLine })
290
+ }
291
+
292
+ Export-ModuleMember -Function `
293
+ Split-MermaidTextLine, `
294
+ Test-MermaidOptOutMarker, `
295
+ Get-MermaidFenceLine, `
296
+ Get-MermaidUnquotedLine, `
297
+ Test-MermaidFenceClose, `
298
+ Get-MermaidFenceBlock