@ikunin/sprintpilot 2.3.5 → 2.3.6

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.
@@ -1,6 +1,6 @@
1
1
  addon:
2
2
  name: sprintpilot
3
- version: 2.3.5
3
+ version: 2.3.6
4
4
  description: Sprintpilot — autopilot and multi-agent addon for BMad Method (git workflow, parallel agents, autonomous story execution)
5
5
  bmad_compatibility: ">=6.2.0"
6
6
  modules:
@@ -640,6 +640,50 @@ function hasGraphvizBinary() {
640
640
  }
641
641
  }
642
642
 
643
+ // Find the Mermaid CLI binary on PATH. Cross-platform: npm installs
644
+ // CLI tools as `.cmd` shims on Windows, and Node's spawn family does
645
+ // not auto-resolve PATHEXT extensions without `shell: true`. We probe
646
+ // platform-appropriate candidates explicitly. Returns the resolved
647
+ // binary name (suitable for spawnSync) or null if none found.
648
+ function findMermaidCliBinary() {
649
+ const candidates =
650
+ process.platform === 'win32'
651
+ ? ['mmdc.cmd', 'mmdc.ps1', 'mmdc.bat', 'mmdc.exe', 'mmdc']
652
+ : ['mmdc'];
653
+ for (const name of candidates) {
654
+ try {
655
+ const r = spawnSync(name, ['--version'], { stdio: 'ignore' });
656
+ if (r.status === 0) return name;
657
+ } catch {
658
+ // ENOENT etc — try next candidate
659
+ }
660
+ }
661
+ return null;
662
+ }
663
+
664
+ // Try to render `<mmd>` to a sibling `<mmd>.png` via mmdc. Returns
665
+ // { written: true, file: <png-path> } — success
666
+ // { written: false, reason: 'mmdc-missing' } — toolchain absent
667
+ // { written: false, reason: 'render-failed', message: <stderr> } — toolchain errored
668
+ // Never throws; the caller threads the result into the envelope.
669
+ function tryRenderMermaidPng(mmdPath) {
670
+ const bin = findMermaidCliBinary();
671
+ if (!bin) {
672
+ return { written: false, reason: 'mmdc-missing' };
673
+ }
674
+ const pngPath = mmdPath.endsWith('.mmd') ? mmdPath.slice(0, -4) + '.png' : mmdPath + '.png';
675
+ const r = spawnSync(bin, ['-i', mmdPath, '-o', pngPath, '-b', 'transparent', '--quiet'], {
676
+ encoding: 'utf8',
677
+ stdio: ['ignore', 'pipe', 'pipe'],
678
+ windowsHide: true,
679
+ });
680
+ if (r.status !== 0) {
681
+ const message = (r.stderr || r.stdout || 'mmdc exited non-zero').trim();
682
+ return { written: false, reason: 'render-failed', message };
683
+ }
684
+ return { written: true, file: pngPath };
685
+ }
686
+
643
687
  function defaultRenderOutputPath(projectRoot, format) {
644
688
  const ext = format === 'graphviz' ? 'dot' : 'mmd';
645
689
  return path.join(projectRoot, '_bmad-output', 'implementation-artifacts', `sprint-plan-dag.${ext}`);
@@ -694,12 +738,29 @@ function runRender({ projectRoot, epic, format, output }) {
694
738
  };
695
739
  }
696
740
 
741
+ // Sibling-PNG render (mermaid only). Non-fatal: caller surfaces the
742
+ // reason if mmdc is missing or errored. graphviz users render via
743
+ // `dot -Tpng …` themselves; no auto-PNG for that format.
744
+ let pngEnvelope = null;
745
+ if (effectiveFormat === 'mermaid') {
746
+ const pngResult = tryRenderMermaidPng(outputPath);
747
+ if (pngResult.written) {
748
+ pngEnvelope = { png_file: pngResult.file };
749
+ } else {
750
+ pngEnvelope = {
751
+ png_reason: pngResult.reason,
752
+ ...(pngResult.message ? { png_message: pngResult.message } : {}),
753
+ };
754
+ }
755
+ }
756
+
697
757
  return {
698
758
  wrote: true,
699
759
  file: outputPath,
700
760
  format: effectiveFormat,
701
761
  requested_format: requestedFormat,
702
762
  ...(fallbackReason ? { fallback: fallbackReason } : {}),
763
+ ...(pngEnvelope || {}),
703
764
  nodes: dag.nodes.length,
704
765
  edges: dag.edges.length,
705
766
  };
@@ -113,8 +113,8 @@ node _Sprintpilot/scripts/resolve-dag.js render --format mermaid \
113
113
  [--epic <id>] [--output <path>] --project-root <root>
114
114
  ```
115
115
 
116
- Returns JSON `{wrote, file, format, nodes, edges, fallback?}`. Then
117
- read the rendered file and inline its contents in a ```mermaid fenced
116
+ Returns JSON `{wrote, file, format, nodes, edges, fallback?, png_file?, png_reason?, png_message?}`.
117
+ Then read the rendered file and inline its contents in a ```mermaid fenced
118
118
  code block so the chat client (Claude Code, etc.) renders the diagram
119
119
  inline. Also report the file path so the user can preview elsewhere:
120
120
 
@@ -134,6 +134,21 @@ cross-references back to the user's tracker (Jira / Linear / GitHub /
134
134
  GitLab). Stories/epics without an issue_id render with the bare key —
135
135
  silence communicates "not tracked" rather than spamming `[no issue]`.
136
136
 
137
+ **PNG sibling render.** As a side-effect of the mermaid render, the
138
+ script tries to produce a `<file>.png` next to the `.mmd` via the
139
+ official Mermaid CLI (`mmdc`). Three outcomes to surface:
140
+
141
+ - `png_file` set → PNG produced. Report:
142
+ > Also wrote PNG: `<png_file>` (rendered via Mermaid CLI).
143
+ - `png_reason: "mmdc-missing"` → Mermaid CLI not installed. Report:
144
+ > PNG render skipped — install Mermaid CLI to get a `.png` next to
145
+ > the `.mmd`:
146
+ > `npm install -g @mermaid-js/mermaid-cli`
147
+ > (Requires Node 18+. Then re-run this skill.)
148
+ - `png_reason: "render-failed"` → mmdc errored. Report the `png_message`
149
+ verbatim and suggest re-running with `mmdc -i <mmd> -o <png>` to see
150
+ the full error.
151
+
137
152
  ### Graphviz
138
153
 
139
154
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ikunin/sprintpilot",
3
- "version": "2.3.5",
3
+ "version": "2.3.6",
4
4
  "description": "Sprintpilot — autopilot and multi-agent addon for BMad Method v6: git workflow, parallel agents, autonomous story execution",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {