pi-maestro-flow 0.2.0

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 (179) hide show
  1. package/README.md +124 -0
  2. package/agents/aggregator.md +27 -0
  3. package/agents/cli-explore-agent.md +188 -0
  4. package/agents/cross-role-reviewer.md +171 -0
  5. package/agents/delegate.md +19 -0
  6. package/agents/explorer.md +23 -0
  7. package/agents/impeccable-agent.md +99 -0
  8. package/agents/ralph-executor.md +81 -0
  9. package/agents/reference.md +24 -0
  10. package/agents/role-design-author.md +220 -0
  11. package/agents/team-supervisor.md +143 -0
  12. package/agents/team-worker.md +237 -0
  13. package/agents/ui-design-agent.md +270 -0
  14. package/agents/workflow-analyzer.md +116 -0
  15. package/agents/workflow-codebase-mapper.md +77 -0
  16. package/agents/workflow-collab-planner.md +147 -0
  17. package/agents/workflow-debugger.md +104 -0
  18. package/agents/workflow-executor.md +133 -0
  19. package/agents/workflow-external-researcher.md +86 -0
  20. package/agents/workflow-integration-checker.md +83 -0
  21. package/agents/workflow-nyquist-auditor.md +85 -0
  22. package/agents/workflow-phase-researcher.md +85 -0
  23. package/agents/workflow-plan-checker.md +100 -0
  24. package/agents/workflow-planner.md +200 -0
  25. package/agents/workflow-project-researcher.md +74 -0
  26. package/agents/workflow-research-synthesizer.md +70 -0
  27. package/agents/workflow-reviewer.md +82 -0
  28. package/agents/workflow-roadmapper.md +81 -0
  29. package/agents/workflow-verifier.md +120 -0
  30. package/package.json +58 -0
  31. package/skills/codify-to-knowhow/SKILL.md +167 -0
  32. package/skills/delegation-check/SKILL.md +297 -0
  33. package/skills/domain-add/SKILL.md +75 -0
  34. package/skills/insight-challenge/SKILL.md +226 -0
  35. package/skills/learn-decompose/SKILL.md +124 -0
  36. package/skills/learn-follow/SKILL.md +163 -0
  37. package/skills/learn-investigate/SKILL.md +160 -0
  38. package/skills/learn-second-opinion/SKILL.md +128 -0
  39. package/skills/maestro/SKILL.md +239 -0
  40. package/skills/maestro-amend/SKILL.md +169 -0
  41. package/skills/maestro-analyze/SKILL.md +173 -0
  42. package/skills/maestro-blueprint/SKILL.md +159 -0
  43. package/skills/maestro-brainstorm/SKILL.md +193 -0
  44. package/skills/maestro-collab/SKILL.md +181 -0
  45. package/skills/maestro-companion/SKILL.md +536 -0
  46. package/skills/maestro-composer/SKILL.md +192 -0
  47. package/skills/maestro-execute/SKILL.md +193 -0
  48. package/skills/maestro-fork/SKILL.md +104 -0
  49. package/skills/maestro-grill/SKILL.md +151 -0
  50. package/skills/maestro-guard/SKILL.md +124 -0
  51. package/skills/maestro-help/SKILL.md +328 -0
  52. package/skills/maestro-impeccable/SKILL.md +302 -0
  53. package/skills/maestro-init/SKILL.md +151 -0
  54. package/skills/maestro-merge/SKILL.md +90 -0
  55. package/skills/maestro-milestone-audit/SKILL.md +117 -0
  56. package/skills/maestro-milestone-complete/SKILL.md +133 -0
  57. package/skills/maestro-milestone-release/SKILL.md +131 -0
  58. package/skills/maestro-next/SKILL.md +269 -0
  59. package/skills/maestro-overlay/SKILL.md +203 -0
  60. package/skills/maestro-plan/SKILL.md +194 -0
  61. package/skills/maestro-player/SKILL.md +184 -0
  62. package/skills/maestro-quick/SKILL.md +117 -0
  63. package/skills/maestro-ralph/SKILL.md +905 -0
  64. package/skills/maestro-ralph-cli/SKILL.md +976 -0
  65. package/skills/maestro-ralph-cli-execute/SKILL.md +229 -0
  66. package/skills/maestro-ralph-execute/SKILL.md +409 -0
  67. package/skills/maestro-ralph-v2/SKILL.md +1198 -0
  68. package/skills/maestro-roadmap/SKILL.md +157 -0
  69. package/skills/maestro-swarm-workflow/SKILL.md +272 -0
  70. package/skills/maestro-tools-execute/SKILL.md +143 -0
  71. package/skills/maestro-tools-register/SKILL.md +192 -0
  72. package/skills/maestro-ui-codify/SKILL.md +127 -0
  73. package/skills/maestro-universal-workflow/SKILL.md +622 -0
  74. package/skills/maestro-update/SKILL.md +156 -0
  75. package/skills/manage-codebase-rebuild/SKILL.md +111 -0
  76. package/skills/manage-drift-realign/SKILL.md +159 -0
  77. package/skills/manage-harvest/SKILL.md +121 -0
  78. package/skills/manage-issue/SKILL.md +88 -0
  79. package/skills/manage-issue-discover/SKILL.md +104 -0
  80. package/skills/manage-kg-extractors/SKILL.md +147 -0
  81. package/skills/manage-knowhow/SKILL.md +102 -0
  82. package/skills/manage-knowhow-capture/SKILL.md +109 -0
  83. package/skills/manage-knowledge-audit/SKILL.md +147 -0
  84. package/skills/manage-status/SKILL.md +80 -0
  85. package/skills/manage-wiki/SKILL.md +104 -0
  86. package/skills/odyssey-debug/SKILL.md +344 -0
  87. package/skills/odyssey-improve/SKILL.md +423 -0
  88. package/skills/odyssey-planex/SKILL.md +542 -0
  89. package/skills/odyssey-review-test-fix/SKILL.md +392 -0
  90. package/skills/odyssey-ui/SKILL.md +388 -0
  91. package/skills/prompt-generator/SKILL.md +470 -0
  92. package/skills/quality-auto-test/SKILL.md +168 -0
  93. package/skills/quality-debug/SKILL.md +176 -0
  94. package/skills/quality-refactor/SKILL.md +108 -0
  95. package/skills/quality-retrospective/SKILL.md +134 -0
  96. package/skills/quality-review/SKILL.md +169 -0
  97. package/skills/quality-sync/SKILL.md +90 -0
  98. package/skills/quality-test/SKILL.md +183 -0
  99. package/skills/scholar-anti-ai-writing/SKILL.md +173 -0
  100. package/skills/scholar-anti-ai-writing/references/patterns-chinese.md +242 -0
  101. package/skills/scholar-anti-ai-writing/references/patterns-english.md +242 -0
  102. package/skills/scholar-citation-verify/SKILL.md +166 -0
  103. package/skills/scholar-citation-verify/references/api-usage.md +372 -0
  104. package/skills/scholar-citation-verify/references/common-errors.md +384 -0
  105. package/skills/scholar-citation-verify/references/verification-rules.md +399 -0
  106. package/skills/scholar-experiment/SKILL.md +321 -0
  107. package/skills/scholar-ideation/SKILL.md +288 -0
  108. package/skills/scholar-latex-organizer/SKILL.md +186 -0
  109. package/skills/scholar-publish/SKILL.md +220 -0
  110. package/skills/scholar-rebuttal-pro/README.md +313 -0
  111. package/skills/scholar-rebuttal-pro/SKILL.md +511 -0
  112. package/skills/scholar-review/SKILL.md +227 -0
  113. package/skills/scholar-thesis-docx/README.md +111 -0
  114. package/skills/scholar-thesis-docx/README_EN.md +108 -0
  115. package/skills/scholar-thesis-docx/SKILL.md +212 -0
  116. package/skills/scholar-thesis-docx/references/failure-patterns-and-quality-gates.md +178 -0
  117. package/skills/scholar-thesis-docx/references/figure-and-code-rules.md +33 -0
  118. package/skills/scholar-thesis-docx/references/paper-format-workflow.md +68 -0
  119. package/skills/scholar-thesis-docx/references/script-usage.md +157 -0
  120. package/skills/scholar-thesis-docx/scripts/audit_docx_ooxml.py +429 -0
  121. package/skills/scholar-thesis-docx/scripts/check_word_com.ps1 +50 -0
  122. package/skills/scholar-thesis-docx/scripts/export_word_pdf.ps1 +62 -0
  123. package/skills/scholar-thesis-docx/scripts/normalize_word_styles.ps1 +498 -0
  124. package/skills/scholar-thesis-docx/scripts/render_mermaid_figure.ps1 +148 -0
  125. package/skills/scholar-writing/SKILL.md +296 -0
  126. package/skills/security-audit/SKILL.md +244 -0
  127. package/skills/skill-generator/SKILL.md +472 -0
  128. package/skills/skill-iter-tune/SKILL.md +382 -0
  129. package/skills/skill-simplify/SKILL.md +63 -0
  130. package/skills/skill-tuning/SKILL.md +174 -0
  131. package/skills/spec-add/SKILL.md +105 -0
  132. package/skills/spec-load/SKILL.md +98 -0
  133. package/skills/spec-remove/SKILL.md +74 -0
  134. package/skills/spec-setup/SKILL.md +75 -0
  135. package/skills/team-adversarial-swarm/SKILL.md +233 -0
  136. package/skills/team-adversarial-swarm/scripts/__pycache__/pheromone.cpython-313.pyc +0 -0
  137. package/skills/team-adversarial-swarm/scripts/__pycache__/scoring.cpython-313.pyc +0 -0
  138. package/skills/team-adversarial-swarm/scripts/aco.py +473 -0
  139. package/skills/team-adversarial-swarm/scripts/pheromone.py +144 -0
  140. package/skills/team-adversarial-swarm/scripts/scoring.py +92 -0
  141. package/skills/team-adversarial-swarm/scripts/test_aco.py +475 -0
  142. package/skills/team-arch-opt/SKILL.md +158 -0
  143. package/skills/team-brainstorm/SKILL.md +171 -0
  144. package/skills/team-coordinate/SKILL.md +266 -0
  145. package/skills/team-designer/SKILL.md +160 -0
  146. package/skills/team-executor/SKILL.md +189 -0
  147. package/skills/team-frontend/SKILL.md +136 -0
  148. package/skills/team-frontend-debug/SKILL.md +198 -0
  149. package/skills/team-interactive-craft/SKILL.md +141 -0
  150. package/skills/team-issue/SKILL.md +171 -0
  151. package/skills/team-lifecycle-v4/SKILL.md +209 -0
  152. package/skills/team-motion-design/SKILL.md +142 -0
  153. package/skills/team-perf-opt/SKILL.md +175 -0
  154. package/skills/team-planex/SKILL.md +137 -0
  155. package/skills/team-quality-assurance/SKILL.md +147 -0
  156. package/skills/team-review/SKILL.md +147 -0
  157. package/skills/team-roadmap-dev/SKILL.md +169 -0
  158. package/skills/team-swarm/SKILL.md +178 -0
  159. package/skills/team-swarm/scripts/aco.py +473 -0
  160. package/skills/team-swarm/scripts/pheromone.py +144 -0
  161. package/skills/team-swarm/scripts/scoring.py +92 -0
  162. package/skills/team-swarm/scripts/test_aco.py +475 -0
  163. package/skills/team-tech-debt/SKILL.md +128 -0
  164. package/skills/team-testing/SKILL.md +143 -0
  165. package/skills/team-ui-polish/SKILL.md +141 -0
  166. package/skills/team-uidesign/SKILL.md +144 -0
  167. package/skills/team-ultra-analyze/SKILL.md +173 -0
  168. package/skills/team-ux-improve/SKILL.md +151 -0
  169. package/skills/team-visual-a11y/SKILL.md +156 -0
  170. package/skills/workflow-skill-designer/SKILL.md +496 -0
  171. package/src/extension/index.ts +222 -0
  172. package/src/extension/schemas.ts +131 -0
  173. package/src/providers/cli-tools-loader.ts +74 -0
  174. package/src/providers/provider-registry.ts +130 -0
  175. package/src/tools/delegate.ts +85 -0
  176. package/src/tools/explore.ts +134 -0
  177. package/src/tools/moa.ts +213 -0
  178. package/src/tools/status.ts +99 -0
  179. package/src/tools/wait.ts +166 -0
@@ -0,0 +1,498 @@
1
+ param(
2
+ [Parameter(Mandatory = $true)]
3
+ [string]$InputPath,
4
+
5
+ [string]$OutputPath,
6
+
7
+ [string]$ConfigPath,
8
+
9
+ [switch]$AuditOnly,
10
+
11
+ [switch]$InPlace,
12
+
13
+ [switch]$Visible
14
+ )
15
+
16
+ Set-StrictMode -Version Latest
17
+ $ErrorActionPreference = "Stop"
18
+
19
+ function Get-DefaultConfig {
20
+ return @{
21
+ styles = @{
22
+ Body = @{
23
+ TargetStyleName = "Body Text"
24
+ BuiltinId = -1
25
+ FontName = "Times New Roman"
26
+ EastAsiaFontName = "SimSun"
27
+ Size = 12
28
+ Bold = $false
29
+ Italic = $false
30
+ Alignment = "Justify"
31
+ FirstLineIndentCm = 0.74
32
+ LeftIndentCm = 0
33
+ RightIndentCm = 0
34
+ SpaceBeforePt = 0
35
+ SpaceAfterPt = 0
36
+ LineSpacingMultiple = 1.5
37
+ KeepTogether = $false
38
+ KeepWithNext = $false
39
+ OutlineLevel = 10
40
+ }
41
+ Heading1 = @{
42
+ TargetStyleName = "Heading 1"
43
+ BuiltinId = -2
44
+ FontName = "Times New Roman"
45
+ EastAsiaFontName = "SimHei"
46
+ Size = 16
47
+ Bold = $true
48
+ Italic = $false
49
+ Alignment = "Center"
50
+ FirstLineIndentCm = 0
51
+ LeftIndentCm = 0
52
+ RightIndentCm = 0
53
+ SpaceBeforePt = 18
54
+ SpaceAfterPt = 12
55
+ LineSpacingMultiple = 1.5
56
+ KeepTogether = $true
57
+ KeepWithNext = $true
58
+ OutlineLevel = 1
59
+ }
60
+ Heading2 = @{
61
+ TargetStyleName = "Heading 2"
62
+ BuiltinId = -3
63
+ FontName = "Times New Roman"
64
+ EastAsiaFontName = "SimHei"
65
+ Size = 14
66
+ Bold = $true
67
+ Italic = $false
68
+ Alignment = "Left"
69
+ FirstLineIndentCm = 0
70
+ LeftIndentCm = 0
71
+ RightIndentCm = 0
72
+ SpaceBeforePt = 12
73
+ SpaceAfterPt = 6
74
+ LineSpacingMultiple = 1.5
75
+ KeepTogether = $true
76
+ KeepWithNext = $true
77
+ OutlineLevel = 2
78
+ }
79
+ Heading3 = @{
80
+ TargetStyleName = "Heading 3"
81
+ BuiltinId = -4
82
+ FontName = "Times New Roman"
83
+ EastAsiaFontName = "SimHei"
84
+ Size = 12
85
+ Bold = $true
86
+ Italic = $false
87
+ Alignment = "Left"
88
+ FirstLineIndentCm = 0
89
+ LeftIndentCm = 0
90
+ RightIndentCm = 0
91
+ SpaceBeforePt = 6
92
+ SpaceAfterPt = 6
93
+ LineSpacingMultiple = 1.5
94
+ KeepTogether = $true
95
+ KeepWithNext = $true
96
+ OutlineLevel = 3
97
+ }
98
+ FigureCaption = @{
99
+ TargetStyleName = "Figure Caption"
100
+ FontName = "Times New Roman"
101
+ EastAsiaFontName = "SimSun"
102
+ Size = 10.5
103
+ Bold = $false
104
+ Italic = $false
105
+ Alignment = "Center"
106
+ FirstLineIndentCm = 0
107
+ LeftIndentCm = 0
108
+ RightIndentCm = 0
109
+ SpaceBeforePt = 6
110
+ SpaceAfterPt = 6
111
+ LineSpacingMultiple = 1.0
112
+ KeepTogether = $true
113
+ KeepWithNext = $false
114
+ OutlineLevel = 10
115
+ }
116
+ TableCaption = @{
117
+ TargetStyleName = "Table Caption"
118
+ FontName = "Times New Roman"
119
+ EastAsiaFontName = "SimSun"
120
+ Size = 10.5
121
+ Bold = $false
122
+ Italic = $false
123
+ Alignment = "Center"
124
+ FirstLineIndentCm = 0
125
+ LeftIndentCm = 0
126
+ RightIndentCm = 0
127
+ SpaceBeforePt = 6
128
+ SpaceAfterPt = 6
129
+ LineSpacingMultiple = 1.0
130
+ KeepTogether = $true
131
+ KeepWithNext = $false
132
+ OutlineLevel = 10
133
+ }
134
+ }
135
+ patterns = @{
136
+ FigureCaption = '^(Figure|Fig\.?|\u56FE)\s*[\dA-Za-z]+'
137
+ TableCaption = '^(Table|\u8868)\s*[\dA-Za-z]+'
138
+ Heading3 = '^(\d+\.\d+\.\d+)\s+\S+'
139
+ Heading2 = '^(\d+\.\d+)\s+\S+'
140
+ Heading1 = '^(Chapter\s+\d+|第[\u4E00-\u5341]+章|\d+\s+\S+)'
141
+ }
142
+ styleHints = @{
143
+ FigureCaption = '(Figure Caption|Caption Figure|\u56FE)'
144
+ TableCaption = '(Table Caption|Caption Table|\u8868)'
145
+ Heading1 = '(Heading 1|\u6807\u9898 1)'
146
+ Heading2 = '(Heading 2|\u6807\u9898 2)'
147
+ Heading3 = '(Heading 3|\u6807\u9898 3)'
148
+ Body = '(Body Text|Normal|\u6B63\u6587)'
149
+ }
150
+ }
151
+ }
152
+
153
+ function Merge-Hashtable {
154
+ param(
155
+ [hashtable]$Base,
156
+ [hashtable]$Override
157
+ )
158
+
159
+ foreach ($key in $Override.Keys) {
160
+ if ($Base.ContainsKey($key) -and $Base[$key] -is [hashtable] -and $Override[$key] -is [hashtable]) {
161
+ Merge-Hashtable -Base $Base[$key] -Override $Override[$key]
162
+ }
163
+ else {
164
+ $Base[$key] = $Override[$key]
165
+ }
166
+ }
167
+ }
168
+
169
+ function ConvertTo-Hashtable {
170
+ param([object]$Value)
171
+
172
+ if ($null -eq $Value) {
173
+ return $null
174
+ }
175
+
176
+ if ($Value -is [System.Collections.IDictionary]) {
177
+ $hash = @{}
178
+ foreach ($key in $Value.Keys) {
179
+ $hash[$key] = ConvertTo-Hashtable -Value $Value[$key]
180
+ }
181
+ return $hash
182
+ }
183
+
184
+ if ($Value -is [System.Collections.IEnumerable] -and -not ($Value -is [string])) {
185
+ $items = @()
186
+ foreach ($item in $Value) {
187
+ $items += ,(ConvertTo-Hashtable -Value $item)
188
+ }
189
+ return $items
190
+ }
191
+
192
+ return $Value
193
+ }
194
+
195
+ function Get-AlignmentValue {
196
+ param([object]$Value)
197
+
198
+ if ($Value -is [int]) {
199
+ return $Value
200
+ }
201
+
202
+ switch -Regex ([string]$Value) {
203
+ '^Center$' { return 1 }
204
+ '^Right$' { return 2 }
205
+ '^Justify$' { return 3 }
206
+ '^Distributed$' { return 4 }
207
+ default { return 0 }
208
+ }
209
+ }
210
+
211
+ function Get-ComBool {
212
+ param([object]$Value)
213
+
214
+ if ([bool]$Value) {
215
+ return -1
216
+ }
217
+
218
+ return 0
219
+ }
220
+
221
+ function Resolve-Style {
222
+ param(
223
+ $Document,
224
+ [string]$LogicalName,
225
+ [hashtable]$StyleSpec
226
+ )
227
+
228
+ $targetName = $StyleSpec.TargetStyleName
229
+ $builtinId = $null
230
+ if ($StyleSpec.ContainsKey("BuiltinId")) {
231
+ $builtinId = [int]$StyleSpec.BuiltinId
232
+ }
233
+
234
+ if ($targetName) {
235
+ try {
236
+ return $Document.Styles.Item($targetName)
237
+ }
238
+ catch {
239
+ }
240
+ }
241
+
242
+ if ($null -ne $builtinId) {
243
+ try {
244
+ return $Document.Styles.Item($builtinId)
245
+ }
246
+ catch {
247
+ }
248
+ }
249
+
250
+ if (-not $targetName) {
251
+ throw "Style '$LogicalName' needs TargetStyleName when no built-in style is available."
252
+ }
253
+
254
+ return $Document.Styles.Add($targetName, 1)
255
+ }
256
+
257
+ function Apply-StyleSpec {
258
+ param(
259
+ $Word,
260
+ $Style,
261
+ [hashtable]$StyleSpec
262
+ )
263
+
264
+ if ($StyleSpec.ContainsKey("FontName")) {
265
+ $Style.Font.Name = [string]$StyleSpec.FontName
266
+ }
267
+
268
+ if ($StyleSpec.ContainsKey("EastAsiaFontName")) {
269
+ try {
270
+ $Style.Font.NameFarEast = [string]$StyleSpec.EastAsiaFontName
271
+ }
272
+ catch {
273
+ }
274
+ }
275
+
276
+ if ($StyleSpec.ContainsKey("Size")) {
277
+ $Style.Font.Size = [double]$StyleSpec.Size
278
+ }
279
+
280
+ if ($StyleSpec.ContainsKey("Bold")) {
281
+ $Style.Font.Bold = Get-ComBool -Value $StyleSpec.Bold
282
+ }
283
+
284
+ if ($StyleSpec.ContainsKey("Italic")) {
285
+ $Style.Font.Italic = Get-ComBool -Value $StyleSpec.Italic
286
+ }
287
+
288
+ if ($StyleSpec.ContainsKey("Alignment")) {
289
+ $Style.ParagraphFormat.Alignment = Get-AlignmentValue -Value $StyleSpec.Alignment
290
+ }
291
+
292
+ if ($StyleSpec.ContainsKey("FirstLineIndentCm")) {
293
+ $Style.ParagraphFormat.FirstLineIndent = $Word.CentimetersToPoints([double]$StyleSpec.FirstLineIndentCm)
294
+ }
295
+
296
+ if ($StyleSpec.ContainsKey("LeftIndentCm")) {
297
+ $Style.ParagraphFormat.LeftIndent = $Word.CentimetersToPoints([double]$StyleSpec.LeftIndentCm)
298
+ }
299
+
300
+ if ($StyleSpec.ContainsKey("RightIndentCm")) {
301
+ $Style.ParagraphFormat.RightIndent = $Word.CentimetersToPoints([double]$StyleSpec.RightIndentCm)
302
+ }
303
+
304
+ if ($StyleSpec.ContainsKey("SpaceBeforePt")) {
305
+ $Style.ParagraphFormat.SpaceBefore = [double]$StyleSpec.SpaceBeforePt
306
+ }
307
+
308
+ if ($StyleSpec.ContainsKey("SpaceAfterPt")) {
309
+ $Style.ParagraphFormat.SpaceAfter = [double]$StyleSpec.SpaceAfterPt
310
+ }
311
+
312
+ if ($StyleSpec.ContainsKey("LineSpacingMultiple")) {
313
+ $Style.ParagraphFormat.LineSpacingRule = 5
314
+ $Style.ParagraphFormat.LineSpacing = $Word.LinesToPoints([double]$StyleSpec.LineSpacingMultiple)
315
+ }
316
+
317
+ if ($StyleSpec.ContainsKey("KeepTogether")) {
318
+ $Style.ParagraphFormat.KeepTogether = Get-ComBool -Value $StyleSpec.KeepTogether
319
+ }
320
+
321
+ if ($StyleSpec.ContainsKey("KeepWithNext")) {
322
+ $Style.ParagraphFormat.KeepWithNext = Get-ComBool -Value $StyleSpec.KeepWithNext
323
+ }
324
+
325
+ if ($StyleSpec.ContainsKey("OutlineLevel")) {
326
+ $Style.ParagraphFormat.OutlineLevel = [int]$StyleSpec.OutlineLevel
327
+ }
328
+ }
329
+
330
+ function Get-ParagraphText {
331
+ param($Paragraph)
332
+ return ($Paragraph.Range.Text -replace "[`r`n]+$", "").Trim()
333
+ }
334
+
335
+ function Get-StyleName {
336
+ param($Paragraph)
337
+
338
+ try {
339
+ return [string]$Paragraph.Range.Style.NameLocal
340
+ }
341
+ catch {
342
+ try {
343
+ return [string]$Paragraph.Range.Style.Name
344
+ }
345
+ catch {
346
+ return ""
347
+ }
348
+ }
349
+ }
350
+
351
+ function Get-ParagraphKind {
352
+ param(
353
+ [string]$Text,
354
+ [string]$CurrentStyleName,
355
+ [hashtable]$Config
356
+ )
357
+
358
+ if ([string]::IsNullOrWhiteSpace($Text)) {
359
+ return $null
360
+ }
361
+
362
+ foreach ($kind in @("FigureCaption", "TableCaption", "Heading1", "Heading2", "Heading3")) {
363
+ if ($Config.styleHints.ContainsKey($kind) -and $CurrentStyleName -match $Config.styleHints[$kind]) {
364
+ return $kind
365
+ }
366
+ }
367
+
368
+ foreach ($kind in @("FigureCaption", "TableCaption", "Heading3", "Heading2", "Heading1")) {
369
+ if ($Config.patterns.ContainsKey($kind) -and $Text -match $Config.patterns[$kind]) {
370
+ return $kind
371
+ }
372
+ }
373
+
374
+ if ($Config.styleHints.ContainsKey("Body") -and $CurrentStyleName -match $Config.styleHints.Body) {
375
+ return "Body"
376
+ }
377
+
378
+ return "Body"
379
+ }
380
+
381
+ $resolvedInput = (Resolve-Path -LiteralPath $InputPath).Path
382
+ if (-not $InPlace -and -not $OutputPath) {
383
+ $directory = Split-Path -Parent $resolvedInput
384
+ $leaf = Split-Path -LeafBase $resolvedInput
385
+ $extension = [System.IO.Path]::GetExtension($resolvedInput)
386
+ $OutputPath = Join-Path $directory "$leaf.normalized$extension"
387
+ }
388
+
389
+ $config = Get-DefaultConfig
390
+ if ($ConfigPath) {
391
+ $overrideObject = Get-Content -LiteralPath $ConfigPath -Raw -Encoding UTF8 | ConvertFrom-Json
392
+ $overrideConfig = ConvertTo-Hashtable -Value $overrideObject
393
+ Merge-Hashtable -Base $config -Override $overrideConfig
394
+ }
395
+
396
+ $word = $null
397
+ $document = $null
398
+ $styles = @{}
399
+ $stats = @{
400
+ Body = 0
401
+ Heading1 = 0
402
+ Heading2 = 0
403
+ Heading3 = 0
404
+ FigureCaption = 0
405
+ TableCaption = 0
406
+ }
407
+ $previewChanges = New-Object System.Collections.Generic.List[object]
408
+
409
+ try {
410
+ $word = New-Object -ComObject Word.Application
411
+ $word.Visible = [bool]$Visible
412
+ $word.DisplayAlerts = 0
413
+
414
+ $document = $word.Documents.Open($resolvedInput, $false, $false)
415
+
416
+ foreach ($logicalName in $config.styles.Keys) {
417
+ $style = Resolve-Style -Document $document -LogicalName $logicalName -StyleSpec $config.styles[$logicalName]
418
+ Apply-StyleSpec -Word $word -Style $style -StyleSpec $config.styles[$logicalName]
419
+ $styles[$logicalName] = $style
420
+ }
421
+
422
+ foreach ($paragraph in $document.Paragraphs) {
423
+ $text = Get-ParagraphText -Paragraph $paragraph
424
+ if ([string]::IsNullOrWhiteSpace($text)) {
425
+ continue
426
+ }
427
+
428
+ $currentStyleName = Get-StyleName -Paragraph $paragraph
429
+ $kind = Get-ParagraphKind -Text $text -CurrentStyleName $currentStyleName -Config $config
430
+ if (-not $kind) {
431
+ continue
432
+ }
433
+
434
+ $targetStyle = $styles[$kind]
435
+ $targetStyleName = ""
436
+ try {
437
+ $targetStyleName = [string]$targetStyle.NameLocal
438
+ }
439
+ catch {
440
+ try {
441
+ $targetStyleName = [string]$targetStyle.Name
442
+ }
443
+ catch {
444
+ $targetStyleName = $kind
445
+ }
446
+ }
447
+
448
+ if ($currentStyleName -ne $targetStyleName) {
449
+ $previewChanges.Add([pscustomobject]@{
450
+ kind = $kind
451
+ fromStyle = $currentStyleName
452
+ toStyle = $targetStyleName
453
+ text = if ($text.Length -gt 80) { $text.Substring(0, 80) } else { $text }
454
+ }) | Out-Null
455
+ }
456
+
457
+ if (-not $AuditOnly) {
458
+ $paragraph.Range.Style = $targetStyle
459
+ $stats[$kind]++
460
+ }
461
+ }
462
+
463
+ if ($AuditOnly) {
464
+ $finalPath = $resolvedInput
465
+ }
466
+ else {
467
+ if ($InPlace) {
468
+ $document.Save()
469
+ $finalPath = $resolvedInput
470
+ }
471
+ else {
472
+ $resolvedOutput = [System.IO.Path]::GetFullPath($OutputPath)
473
+ $document.SaveAs([ref]$resolvedOutput)
474
+ $finalPath = $resolvedOutput
475
+ }
476
+ }
477
+
478
+ [pscustomobject]@{
479
+ input = $resolvedInput
480
+ output = $finalPath
481
+ auditOnly = [bool]$AuditOnly
482
+ stats = [pscustomobject]$stats
483
+ previewChanges = $previewChanges
484
+ } | ConvertTo-Json -Depth 5
485
+ }
486
+ finally {
487
+ if ($document) {
488
+ $document.Close([ref]0)
489
+ }
490
+
491
+ if ($word) {
492
+ $word.Quit()
493
+ [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($word)
494
+ }
495
+
496
+ [gc]::Collect()
497
+ [gc]::WaitForPendingFinalizers()
498
+ }
@@ -0,0 +1,148 @@
1
+ param(
2
+ [Parameter(Mandatory = $true)]
3
+ [string]$InputPath,
4
+
5
+ [Parameter(Mandatory = $true)]
6
+ [string]$OutputPath,
7
+
8
+ [ValidateSet("svg", "png", "pdf")]
9
+ [string]$Format = "svg",
10
+
11
+ [ValidateSet("default", "neutral", "forest", "dark", "base")]
12
+ [string]$Theme = "base",
13
+
14
+ [int]$Width = 1600,
15
+
16
+ [int]$Height = 1200,
17
+
18
+ [double]$Scale = 2.0,
19
+
20
+ [string]$BackgroundColor = "white",
21
+
22
+ [string]$ConfigPath,
23
+
24
+ [switch]$Quiet
25
+ )
26
+
27
+ Set-StrictMode -Version Latest
28
+ $ErrorActionPreference = "Stop"
29
+
30
+ function New-DefaultConfigFile {
31
+ param([string]$Path)
32
+
33
+ $config = @'
34
+ {
35
+ "theme": "base",
36
+ "themeVariables": {
37
+ "fontFamily": "Times New Roman",
38
+ "fontSize": "18px",
39
+ "primaryColor": "#ffffff",
40
+ "primaryTextColor": "#111827",
41
+ "primaryBorderColor": "#111827",
42
+ "lineColor": "#374151",
43
+ "secondaryColor": "#f8fafc",
44
+ "tertiaryColor": "#ffffff"
45
+ },
46
+ "flowchart": {
47
+ "htmlLabels": false,
48
+ "curve": "linear"
49
+ },
50
+ "sequence": {
51
+ "useMaxWidth": false
52
+ },
53
+ "er": {
54
+ "layoutDirection": "TB"
55
+ }
56
+ }
57
+ '@
58
+ $encoding = New-Object System.Text.UTF8Encoding($false)
59
+ [System.IO.File]::WriteAllText($Path, $config, $encoding)
60
+ }
61
+
62
+ function Resolve-MermaidRunner {
63
+ $mmdc = Get-Command mmdc -ErrorAction SilentlyContinue
64
+ if ($mmdc) {
65
+ return @{
66
+ Command = $mmdc.Source
67
+ PrefixArgs = @()
68
+ }
69
+ }
70
+
71
+ $npx = Get-Command npx.cmd -ErrorAction SilentlyContinue
72
+ if (-not $npx) {
73
+ $npx = Get-Command npx -ErrorAction SilentlyContinue
74
+ }
75
+
76
+ if ($npx) {
77
+ return @{
78
+ Command = $npx.Source
79
+ PrefixArgs = @("-y", "@mermaid-js/mermaid-cli")
80
+ }
81
+ }
82
+
83
+ throw "Neither mmdc nor npx was found. Install Node.js and mermaid-cli."
84
+ }
85
+
86
+ $resolvedInput = (Resolve-Path -LiteralPath $InputPath).Path
87
+ $resolvedOutput = [System.IO.Path]::GetFullPath($OutputPath)
88
+ $outputDir = Split-Path -Parent $resolvedOutput
89
+
90
+ if (-not (Test-Path -LiteralPath $outputDir)) {
91
+ New-Item -ItemType Directory -Path $outputDir -Force | Out-Null
92
+ }
93
+
94
+ $effectiveConfigPath = $ConfigPath
95
+ $temporaryConfig = $null
96
+
97
+ if (-not $effectiveConfigPath) {
98
+ $temporaryConfig = Join-Path ([System.IO.Path]::GetTempPath()) ("mermaid-config-" + [guid]::NewGuid().ToString("N") + ".json")
99
+ New-DefaultConfigFile -Path $temporaryConfig
100
+ $effectiveConfigPath = $temporaryConfig
101
+ }
102
+ else {
103
+ $effectiveConfigPath = (Resolve-Path -LiteralPath $effectiveConfigPath).Path
104
+ }
105
+
106
+ $runner = Resolve-MermaidRunner
107
+ $arguments = @()
108
+ $arguments += $runner.PrefixArgs
109
+ $arguments += @(
110
+ "-i", $resolvedInput,
111
+ "-o", $resolvedOutput,
112
+ "-c", $effectiveConfigPath,
113
+ "-b", $BackgroundColor,
114
+ "-w", "$Width",
115
+ "-H", "$Height",
116
+ "-s", "$Scale"
117
+ )
118
+
119
+ if ($Theme -ne "base") {
120
+ $arguments += @("-t", $Theme)
121
+ }
122
+
123
+ if ($Quiet) {
124
+ $arguments += "-q"
125
+ }
126
+
127
+ try {
128
+ & $runner.Command @arguments
129
+ if ($LASTEXITCODE -ne 0) {
130
+ throw "Mermaid rendering failed with exit code $LASTEXITCODE."
131
+ }
132
+
133
+ [pscustomobject]@{
134
+ input = $resolvedInput
135
+ output = $resolvedOutput
136
+ format = $Format
137
+ theme = $Theme
138
+ width = $Width
139
+ height = $Height
140
+ scale = $Scale
141
+ command = $runner.Command
142
+ } | ConvertTo-Json -Depth 4
143
+ }
144
+ finally {
145
+ if ($temporaryConfig -and (Test-Path -LiteralPath $temporaryConfig)) {
146
+ Remove-Item -LiteralPath $temporaryConfig -Force
147
+ }
148
+ }