@ngocsangairvds/vsaf 3.1.25 → 3.1.26

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ngocsangairvds/vsaf",
3
- "version": "3.1.25",
4
- "description": "fix gitnexus skip git",
3
+ "version": "3.1.26",
4
+ "description": "fix confluence format",
5
5
  "keywords": ["claude", "claude-code", "ai", "sdlc", "framework", "bmad", "gitnexus", "superpowers"],
6
6
  "bin": {
7
7
  "vsaf": "./bin/vsaf.js"
@@ -9,19 +9,21 @@ description: Push PRD document to Confluence. Use after /vsaf-doc-prd or /vsaf-d
9
9
  Publish the current PRD to Confluence — create a new page if it doesn't exist, or update the existing one. The comment becomes the Confluence version note.
10
10
 
11
11
  ## Input
12
+ - `[file]` — optional path to a specific markdown file (defaults to scanning `.vsaf/docs/planning-artifacts/prd-*.md`)
12
13
  - `[comment]` — optional version note (e.g. "Initial draft", "Updated scope after stakeholder review")
13
14
 
14
15
  ## Prerequisites
15
16
  - Confluence MCP must be configured (`vsaf init` sets this up)
16
- - A PRD file must exist in `.vsaf/docs/planning-artifacts/`
17
+ - A PRD markdown file must exist
17
18
 
18
19
  ## Steps
19
20
 
20
21
  ### Step 1 — Find PRD file
21
- - List files in `.vsaf/docs/planning-artifacts/` matching `prd-*.md`
22
+ - If a file path was given as argument, use that file directly
23
+ - Otherwise list files in `.vsaf/docs/planning-artifacts/` matching `prd-*.md`
22
24
  - If multiple found: ask user which one to push
23
25
  - If none found: STOP — tell user to run `/vsaf-doc-prd` first
24
- - Read full PRD content
26
+ - Read full file content
25
27
 
26
28
  ### Step 2 — Load Confluence config
27
29
  Read `.vsaf/_bmad/bmm/config.yaml` and extract:
@@ -34,36 +36,105 @@ If either field is missing or empty:
34
36
  - Save answers back to config so the user is not asked again
35
37
 
36
38
  ### Step 3 — Determine page title
37
- Page title format: `[PRD] {feature-name}` derive feature name from the filename (e.g. `prd-user-management.md` → `[PRD] User Management`)
39
+ - If file is from `prd-*.md`: title = `[PRD] {Feature Name}` (derive from filename: `prd-user-management.md` → `[PRD] User Management`)
40
+ - Otherwise: use the first `# Heading` in the file as the page title, or the filename stem if no heading found
38
41
 
39
- ### Step 4 — Check if page exists
40
- Use the `confluence` MCP to search for a page with that exact title in the configured space:
42
+ ### Step 4 — Convert markdown Confluence storage format (HTML)
43
+
44
+ **CRITICAL: Never send raw markdown or CDATA-wrapped content to Confluence.**
45
+ **CRITICAL: Do NOT wrap the entire page body in `<![CDATA[...]]>`. CDATA is only valid inside `<ac:plain-text-body>` for code blocks.**
46
+
47
+ Convert the full file content to Confluence storage format using these rules:
48
+
49
+ **Block elements:**
50
+ ```
51
+ # Heading → <h1>Heading</h1>
52
+ ## Heading → <h2>Heading</h2>
53
+ ### Heading → <h3>Heading</h3>
54
+ #### Heading → <h4>Heading</h4>
55
+ paragraph text → <p>paragraph text</p>
56
+ --- → <hr/>
57
+ ```
58
+
59
+ **Inline elements:**
60
+ ```
61
+ **bold** → <strong>bold</strong>
62
+ *italic* → <em>italic</em>
63
+ `inline code` → <code>inline code</code>
64
+ [text](url) → <a href="url">text</a>
65
+ ```
66
+
67
+ **Lists:**
41
68
  ```
42
- CQL: title = "[PRD] {feature-name}" AND space = "{space_key}"
69
+ - item → <ul><li>item</li></ul>
70
+ 1. item → <ol><li>item</li></ol>
43
71
  ```
44
- - **Found** → proceed to Step 5 (update)
45
- - **Not found** → proceed to Step 6 (create)
46
72
 
47
- ### Step 5 — Update existing page
48
- - Use the `confluence` MCP update tool with:
49
- - Page ID from search result
50
- - New content: full PRD markdown converted to Confluence format
51
- - Version comment: the `[comment]` argument (or "Updated via vsaf-push-prd" if blank)
52
- - Confirm the two-stage update if the MCP requires it
73
+ **Tables:**
74
+ ```
75
+ | H1 | H2 | → <table><tbody>
76
+ |----|----| <tr><th>H1</th><th>H2</th></tr>
77
+ | a | b | <tr><td>a</td><td>b</td></tr>
78
+ </tbody></table>
79
+ ```
53
80
 
54
- ### Step 6 Create new page
55
- - Use the `confluence` MCP create tool with:
56
- - Space key from config
57
- - Parent page title from config (find its ID first if needed)
58
- - Title: `[PRD] {feature-name}`
59
- - Content: full PRD markdown
60
- - Version comment: the `[comment]` argument (or "Created via vsaf-push-prd" if blank)
81
+ **Code blocksthe ONLY place CDATA is correct:**
82
+ ````
83
+ ```lang → <ac:structured-macro ac:name="code">
84
+ code here <ac:parameter ac:name="language">lang</ac:parameter>
85
+ ``` <ac:plain-text-body><![CDATA[code here]]></ac:plain-text-body>
86
+ </ac:structured-macro>
87
+ ````
61
88
 
62
- ### Step 7 — Output to user
89
+ **Info/warning/tip boxes:**
90
+ ```
91
+ > [!NOTE] title → <ac:structured-macro ac:name="info">
92
+ > body <ac:parameter ac:name="title">title</ac:parameter>
93
+ <ac:rich-text-body><p>body</p></ac:rich-text-body>
94
+ </ac:structured-macro>
95
+
96
+ > [!WARNING] → ac:name="warning"
97
+ > [!TIP] → ac:name="tip"
98
+ ```
99
+
100
+ **Blockquote:**
101
+ ```
102
+ > text → <blockquote><p>text</p></blockquote>
103
+ ```
104
+
105
+ When calling the Confluence MCP create/update tool, set the content representation to **`storage`**.
106
+
107
+ ### Step 5 — Check if page exists
108
+ Use the `confluence` MCP to search for a page with that exact title in the configured space:
109
+ ```
110
+ CQL: title = "{page_title}" AND space = "{space_key}"
111
+ ```
112
+ - **Found** → proceed to Step 6 (update)
113
+ - **Not found** → proceed to Step 7 (create)
114
+
115
+ ### Step 6 — Update existing page
116
+ Call the `confluence` MCP update tool with:
117
+ - Page ID from search result
118
+ - Content: the **converted wiki markup** from Step 4
119
+ - Representation: `wiki`
120
+ - Version comment: the `[comment]` argument (or "Updated via vsaf-push-prd" if blank)
121
+
122
+ Confirm the two-stage update prompt if the MCP requires it.
123
+
124
+ ### Step 7 — Create new page
125
+ Call the `confluence` MCP create tool with:
126
+ - Space key from config
127
+ - Parent page title from config (find its ID first if needed)
128
+ - Title: determined in Step 3
129
+ - Content: the **converted wiki markup** from Step 4
130
+ - Representation: `wiki`
131
+ - Version comment: the `[comment]` argument (or "Created via vsaf-push-prd" if blank)
132
+
133
+ ### Step 8 — Output to user
63
134
  ```
64
135
  ## PRD pushed to Confluence
65
136
 
66
- - Page: [PRD] {feature-name}
137
+ - Page: {page_title}
67
138
  - Action: [Created / Updated]
68
139
  - Space: {space_key}
69
140
  - Comment: {comment}
@@ -76,4 +147,5 @@ Run /vsaf-push-srs to also publish the SRS, or continue with /vsaf-build
76
147
  ## Notes
77
148
  - Never push a PRD that has failed `/vsaf-validate-prd` validation
78
149
  - If the Confluence MCP is not configured, tell the user to run `vsaf init` and enter their token
79
- - Do not modify the local PRD file during this step
150
+ - Do not modify the local file during this step
151
+ - The file argument accepts any markdown file path, not just files under `.vsaf/`
@@ -9,19 +9,21 @@ description: Push SRS document to Confluence. Use after /vsaf-doc-srs or SRS edi
9
9
  Publish the current SRS to Confluence — create a new page if it doesn't exist, or update the existing one. The comment becomes the Confluence version note.
10
10
 
11
11
  ## Input
12
+ - `[file]` — optional path to a specific markdown file (defaults to scanning `.vsaf/docs/srs/*.md`)
12
13
  - `[comment]` — optional version note (e.g. "Initial draft", "Revised after tech review")
13
14
 
14
15
  ## Prerequisites
15
16
  - Confluence MCP must be configured (`vsaf init` sets this up)
16
- - An SRS file must exist in `.vsaf/docs/srs/`
17
+ - An SRS markdown file must exist
17
18
 
18
19
  ## Steps
19
20
 
20
21
  ### Step 1 — Find SRS file
21
- - List files in `.vsaf/docs/srs/` matching `*.md` (exclude `*-results.md`)
22
+ - If a file path was given as argument, use that file directly
23
+ - Otherwise list files in `.vsaf/docs/srs/` matching `*.md` (exclude `*-results.md`)
22
24
  - If multiple found: ask user which one to push
23
25
  - If none found: STOP — tell user to run `/vsaf-doc-srs` first
24
- - Read full SRS content
26
+ - Read full file content
25
27
 
26
28
  ### Step 2 — Load Confluence config
27
29
  Read `.vsaf/_bmad/bmm/config.yaml` and extract:
@@ -34,45 +36,120 @@ If either field is missing or empty:
34
36
  - Save answers back to config so the user is not asked again
35
37
 
36
38
  ### Step 3 — Determine page title
37
- Page title format: `[SRS] {feature-name}` derive feature name from the filename (e.g. `user-management.md` `[SRS] User Management`)
39
+ - If file is from `srs-*.md` or `SRS-*.md`: title = `[SRS] {Feature Name}` (derive from filename)
40
+ - Otherwise: use the first `# Heading` in the file as the page title, or the filename stem if no heading found
38
41
 
39
- ### Step 4 — Check if page exists
40
- Use the `confluence` MCP to search for a page with that exact title in the configured space:
42
+ ### Step 4 — Convert markdown Confluence storage format (HTML)
43
+
44
+ **CRITICAL: Never send raw markdown or CDATA-wrapped content to Confluence.**
45
+ **CRITICAL: Do NOT wrap the entire page body in `<![CDATA[...]]>`. CDATA is only valid inside `<ac:plain-text-body>` for code blocks.**
46
+
47
+ Convert the full file content to Confluence storage format using these rules:
48
+
49
+ **Block elements:**
50
+ ```
51
+ # Heading → <h1>Heading</h1>
52
+ ## Heading → <h2>Heading</h2>
53
+ ### Heading → <h3>Heading</h3>
54
+ #### Heading → <h4>Heading</h4>
55
+ paragraph text → <p>paragraph text</p>
56
+ --- → <hr/>
57
+ ```
58
+
59
+ **Inline elements:**
60
+ ```
61
+ **bold** → <strong>bold</strong>
62
+ *italic* → <em>italic</em>
63
+ `inline code` → <code>inline code</code>
64
+ [text](url) → <a href="url">text</a>
65
+ ```
66
+
67
+ **Lists:**
41
68
  ```
42
- CQL: title = "[SRS] {feature-name}" AND space = "{space_key}"
69
+ - item → <ul><li>item</li></ul>
70
+ 1. item → <ol><li>item</li></ol>
43
71
  ```
44
- - **Found** → proceed to Step 5 (update)
45
- - **Not found** → proceed to Step 6 (create)
46
72
 
47
- ### Step 5 — Update existing page
48
- - Use the `confluence` MCP update tool with:
49
- - Page ID from search result
50
- - New content: full SRS markdown converted to Confluence format
51
- - Version comment: the `[comment]` argument (or "Updated via vsaf-push-srs" if blank)
52
- - Confirm the two-stage update if the MCP requires it
73
+ **Tables:**
74
+ ```
75
+ | H1 | H2 | → <table><tbody>
76
+ |----|----| <tr><th>H1</th><th>H2</th></tr>
77
+ | a | b | <tr><td>a</td><td>b</td></tr>
78
+ </tbody></table>
79
+ ```
53
80
 
54
- ### Step 6 Create new page
55
- - Use the `confluence` MCP create tool with:
56
- - Space key from config
57
- - Parent page title from config (find its ID first if needed)
58
- - Title: `[SRS] {feature-name}`
59
- - Content: full SRS markdown
60
- - Version comment: the `[comment]` argument (or "Created via vsaf-push-srs" if blank)
81
+ **Code blocksthe ONLY place CDATA is correct:**
82
+ ````
83
+ ```lang → <ac:structured-macro ac:name="code">
84
+ code here <ac:parameter ac:name="language">lang</ac:parameter>
85
+ ``` <ac:plain-text-body><![CDATA[code here]]></ac:plain-text-body>
86
+ </ac:structured-macro>
87
+ ````
61
88
 
62
- ### Step 7 — Link SRS page to PRD page (if PRD page exists)
89
+ **Info/warning/tip boxes:**
90
+ ```
91
+ > [!NOTE] title → <ac:structured-macro ac:name="info">
92
+ > body <ac:parameter ac:name="title">title</ac:parameter>
93
+ <ac:rich-text-body><p>body</p></ac:rich-text-body>
94
+ </ac:structured-macro>
95
+
96
+ > [!WARNING] → ac:name="warning"
97
+ > [!TIP] → ac:name="tip"
98
+ ```
99
+
100
+ **Blockquote:**
101
+ ```
102
+ > text → <blockquote><p>text</p></blockquote>
103
+ ```
104
+
105
+ When calling the Confluence MCP create/update tool, set the content representation to **`storage`**.
106
+
107
+ ### Step 5 — Check if page exists
108
+ Use the `confluence` MCP to search for a page with that exact title in the configured space:
109
+ ```
110
+ CQL: title = "{page_title}" AND space = "{space_key}"
111
+ ```
112
+ - **Found** → proceed to Step 6 (update)
113
+ - **Not found** → proceed to Step 7 (create)
114
+
115
+ ### Step 6 — Update existing page
116
+ Call the `confluence` MCP update tool with:
117
+ - Page ID from search result
118
+ - Content: the **converted wiki markup** from Step 4
119
+ - Representation: `wiki`
120
+ - Version comment: the `[comment]` argument (or "Updated via vsaf-push-srs" if blank)
121
+
122
+ Confirm the two-stage update prompt if the MCP requires it.
123
+
124
+ ### Step 7 — Create new page
125
+ Call the `confluence` MCP create tool with:
126
+ - Space key from config
127
+ - Parent page title from config (find its ID first if needed)
128
+ - Title: determined in Step 3
129
+ - Content: the **converted wiki markup** from Step 4
130
+ - Representation: `wiki`
131
+ - Version comment: the `[comment]` argument (or "Created via vsaf-push-srs" if blank)
132
+
133
+ ### Step 8 — Link SRS page to PRD page (if PRD page exists)
63
134
  - Search Confluence for the corresponding `[PRD] {feature-name}` page
64
- - If found: add a "Related Documents" section or comment on the SRS page linking back to the PRD
135
+ - If found: prepend this storage-format block at the top of the SRS content before pushing:
136
+ ```xml
137
+ <ac:structured-macro ac:name="info">
138
+ <ac:parameter ac:name="title">Related Documents</ac:parameter>
139
+ <ac:rich-text-body><p><a href="{prd_url}">[PRD] {feature-name}</a></p></ac:rich-text-body>
140
+ </ac:structured-macro>
141
+ ```
65
142
  - This creates traceability in Confluence
66
143
 
67
- ### Step 8 — Output to user
144
+ ### Step 9 — Output to user
68
145
  ```
69
146
  ## SRS pushed to Confluence
70
147
 
71
- - Page: [SRS] {feature-name}
72
- - Action: [Created / Updated]
73
- - Space: {space_key}
74
- - Comment: {comment}
75
- - URL: {confluence_page_url}
148
+ - Page: {page_title}
149
+ - Action: [Created / Updated]
150
+ - Space: {space_key}
151
+ - Comment: {comment}
152
+ - URL: {confluence_page_url}
76
153
  - PRD link: [linked / not found]
77
154
 
78
155
  ## Next step
@@ -81,5 +158,6 @@ Run /vsaf-test to generate testcases from this SRS, or /vsaf-build to implement
81
158
 
82
159
  ## Notes
83
160
  - If the Confluence MCP is not configured, tell the user to run `vsaf init` and enter their token
84
- - Do not modify the local SRS file during this step
161
+ - Do not modify the local file during this step
85
162
  - SRS result files (`*-results.md`) are test outputs — push those separately if needed
163
+ - The file argument accepts any markdown file path, not just files under `.vsaf/`