@ngocsangairvds/vsaf 3.1.25 → 3.1.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.
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.27",
4
+ "description": "improve 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,22 @@ 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 or directory (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
- ### Step 1 — Find PRD file
21
- - List files in `.vsaf/docs/planning-artifacts/` matching `prd-*.md`
22
- - If multiple found: ask user which one to push
23
- - If none found: STOP tell user to run `/vsaf-doc-prd` first
24
- - Read full PRD content
21
+ ### Step 1 — Find PRD file(s)
22
+ - If a **directory path** was given (e.g. `@docs/architecture/`): read all `*.md` files in that directory and combine them into a single page body, separated by `<hr/>`. Use the directory name as the page title base.
23
+ - If a **specific file path** was given: use that file directly.
24
+ - Otherwise: list files in `.vsaf/docs/planning-artifacts/` matching `prd-*.md`
25
+ - If multiple found: ask user which one to push
26
+ - If none found: STOP — tell user to run `/vsaf-doc-prd` first
27
+ - Read full file content
25
28
 
26
29
  ### Step 2 — Load Confluence config
27
30
  Read `.vsaf/_bmad/bmm/config.yaml` and extract:
@@ -33,37 +36,108 @@ If either field is missing or empty:
33
36
  - Ask user: "Enter parent page title in Confluence (blank = root of space):"
34
37
  - Save answers back to config so the user is not asked again
35
38
 
36
- ### 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
+ ### Step 3 — Determine page title and parent page ID
40
+ - If file is from `prd-*.md`: title = `[PRD] {Feature Name}` (derive from filename: `prd-user-management.md` → `[PRD] User Management`)
41
+ - If input was a directory: title = the numbered section label provided by the user (e.g. `3.4.2.12 VRoute — Architecture Design`)
42
+ - Otherwise: use the first `# Heading` in the file as the page title, or the filename stem if no heading found
38
43
 
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:
44
+ **Resolve parent page ID:**
45
+ Use `confluence_search_pages` to search for the parent page title in the configured space. Extract the `id` field from the result — this is the `parentId` needed for page creation. Do NOT skip this step.
46
+
47
+ ### Step 4 — Convert markdown → Confluence storage format
48
+
49
+ **CRITICAL RULES — read before writing a single tag:**
50
+
51
+ 1. **Never send raw markdown.** All content must be converted to Confluence Storage Format (XHTML).
52
+ 2. **Never wrap the entire body in `<![CDATA[...]]>`.** CDATA is ONLY valid inside `<ac:plain-text-body>` within code macros.
53
+ 3. **All Confluence macro attributes MUST use the `ac:` namespace prefix.** The tag is `<ac:parameter ac:name="...">`, never `<parameter name="...">`. Wrong namespace = XML parse error.
54
+ 4. **Escape HTML entities in regular text:** `&` → `&amp;`, `<` → `&lt;`, `>` → `&gt;`.
55
+ 5. **Every opened tag must be closed.** Confluence's XML parser is strict — an unclosed tag aborts the entire page push.
56
+
57
+ **Block elements:**
58
+ ```
59
+ # Heading → <h1>Heading</h1>
60
+ ## Heading → <h2>Heading</h2>
61
+ ### Heading → <h3>Heading</h3>
62
+ #### Heading → <h4>Heading</h4>
63
+ paragraph text → <p>paragraph text</p>
64
+ --- → <hr/>
65
+ ```
66
+
67
+ **Inline elements:**
68
+ ```
69
+ **bold** → <strong>bold</strong>
70
+ *italic* → <em>italic</em>
71
+ `inline code` → <code>inline code</code>
72
+ [text](url) → <a href="url">text</a>
73
+ ```
74
+
75
+ **Lists:**
76
+ ```
77
+ - item → <ul><li>item</li></ul>
78
+ 1. item → <ol><li>item</li></ol>
79
+ ```
80
+
81
+ **Tables:**
41
82
  ```
42
- CQL: title = "[PRD] {feature-name}" AND space = "{space_key}"
83
+ | H1 | H2 | → <table><tbody>
84
+ |----|----| → <tr><th>H1</th><th>H2</th></tr>
85
+ | a | b | <tr><td>a</td><td>b</td></tr>
86
+ </tbody></table>
43
87
  ```
44
- - **Found** → proceed to Step 5 (update)
45
- - **Not found** → proceed to Step 6 (create)
46
88
 
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
89
+ **Code blocksthe ONLY correct place for CDATA:**
90
+ ```
91
+ ```lang → <ac:structured-macro ac:name="code">
92
+ code here <ac:parameter ac:name="language">lang</ac:parameter>
93
+ ``` <ac:plain-text-body><![CDATA[code here]]></ac:plain-text-body>
94
+ </ac:structured-macro>
95
+ ```
96
+ ⚠️ The attribute is `ac:name` not `name`. Using `<ac:parameter name="language">` will cause an XML parse error.
97
+
98
+ **Info/warning/tip boxes:**
99
+ ```
100
+ > [!NOTE] title → <ac:structured-macro ac:name="info">
101
+ > body <ac:parameter ac:name="title">title</ac:parameter>
102
+ <ac:rich-text-body><p>body</p></ac:rich-text-body>
103
+ </ac:structured-macro>
104
+
105
+ > [!WARNING] → ac:name="warning"
106
+ > [!TIP] → ac:name="tip"
107
+ ```
108
+
109
+ **Blockquote:**
110
+ ```
111
+ > text → <blockquote><p>text</p></blockquote>
112
+ ```
113
+
114
+ ### Step 5 — Check if page exists
115
+ Use `confluence_search_pages` to search for a page with that exact title in the configured space.
116
+ - **Found** → proceed to Step 6 (update)
117
+ - **Not found** → proceed to Step 7 (create)
118
+
119
+ ### Step 6 — Update existing page
120
+ Call `confluence_update_page` with:
121
+ - `pageId`: the ID from the search result
122
+ - `bodyStorageValue`: the **storage format HTML** converted in Step 4
123
+ - Version comment: the `[comment]` argument (or "Updated via vsaf-push-prd" if blank)
124
+
125
+ Confirm the two-stage update prompt if the MCP requires it.
126
+
127
+ ### Step 7 — Create new page
128
+ Call `confluence_create_page` with:
129
+ - `spaceKey`: the space key from config
130
+ - `parentId`: the parent page ID resolved in Step 3
131
+ - `title`: the page title determined in Step 3
132
+ - `bodyStorageValue`: the **storage format HTML** converted in Step 4
53
133
 
54
- ### Step 6Create 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)
134
+ > The `bodyStorageValue` parameter takes Confluence Storage Format (XHTML) directly do not add a separate `representation` field.
61
135
 
62
- ### Step 7 — Output to user
136
+ ### Step 8 — Output to user
63
137
  ```
64
138
  ## PRD pushed to Confluence
65
139
 
66
- - Page: [PRD] {feature-name}
140
+ - Page: {page_title}
67
141
  - Action: [Created / Updated]
68
142
  - Space: {space_key}
69
143
  - Comment: {comment}
@@ -76,4 +150,5 @@ Run /vsaf-push-srs to also publish the SRS, or continue with /vsaf-build
76
150
  ## Notes
77
151
  - Never push a PRD that has failed `/vsaf-validate-prd` validation
78
152
  - 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
153
+ - Do not modify the local file during this step
154
+ - The file argument accepts any markdown file path or directory, not just files under `.vsaf/`
@@ -9,19 +9,22 @@ 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 or directory (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
- ### Step 1 — Find SRS file
21
- - List files in `.vsaf/docs/srs/` matching `*.md` (exclude `*-results.md`)
22
- - If multiple found: ask user which one to push
23
- - If none found: STOP tell user to run `/vsaf-doc-srs` first
24
- - Read full SRS content
21
+ ### Step 1 — Find SRS file(s)
22
+ - If a **directory path** was given (e.g. `@docs/srs/`): read all `*.md` files in that directory (excluding `*-results.md`) and combine them into a single page body, separated by `<hr/>`. Use the directory name as the page title base.
23
+ - If a **specific file path** was given: use that file directly.
24
+ - Otherwise: list files in `.vsaf/docs/srs/` matching `*.md` (exclude `*-results.md`)
25
+ - If multiple found: ask user which one to push
26
+ - If none found: STOP — tell user to run `/vsaf-doc-srs` first
27
+ - Read full file content
25
28
 
26
29
  ### Step 2 — Load Confluence config
27
30
  Read `.vsaf/_bmad/bmm/config.yaml` and extract:
@@ -33,46 +36,123 @@ If either field is missing or empty:
33
36
  - Ask user: "Enter parent page title in Confluence (blank = root of space):"
34
37
  - Save answers back to config so the user is not asked again
35
38
 
36
- ### 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
+ ### Step 3 — Determine page title and parent page ID
40
+ - If file is from `srs-*.md` or `SRS-*.md`: title = `[SRS] {Feature Name}` (derive from filename)
41
+ - If input was a directory: title = the numbered section label provided by the user
42
+ - Otherwise: use the first `# Heading` in the file as the page title, or the filename stem if no heading found
38
43
 
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:
44
+ **Resolve parent page ID:**
45
+ Use `confluence_search_pages` to search for the parent page title in the configured space. Extract the `id` field from the result — this is the `parentId` needed for page creation. Do NOT skip this step.
46
+
47
+ ### Step 4 — Convert markdown → Confluence storage format
48
+
49
+ **CRITICAL RULES — read before writing a single tag:**
50
+
51
+ 1. **Never send raw markdown.** All content must be converted to Confluence Storage Format (XHTML).
52
+ 2. **Never wrap the entire body in `<![CDATA[...]]>`.** CDATA is ONLY valid inside `<ac:plain-text-body>` within code macros.
53
+ 3. **All Confluence macro attributes MUST use the `ac:` namespace prefix.** The tag is `<ac:parameter ac:name="...">`, never `<parameter name="...">`. Wrong namespace = XML parse error.
54
+ 4. **Escape HTML entities in regular text:** `&` → `&amp;`, `<` → `&lt;`, `>` → `&gt;`.
55
+ 5. **Every opened tag must be closed.** Confluence's XML parser is strict — an unclosed tag aborts the entire page push.
56
+
57
+ **Block elements:**
58
+ ```
59
+ # Heading → <h1>Heading</h1>
60
+ ## Heading → <h2>Heading</h2>
61
+ ### Heading → <h3>Heading</h3>
62
+ #### Heading → <h4>Heading</h4>
63
+ paragraph text → <p>paragraph text</p>
64
+ --- → <hr/>
65
+ ```
66
+
67
+ **Inline elements:**
68
+ ```
69
+ **bold** → <strong>bold</strong>
70
+ *italic* → <em>italic</em>
71
+ `inline code` → <code>inline code</code>
72
+ [text](url) → <a href="url">text</a>
73
+ ```
74
+
75
+ **Lists:**
76
+ ```
77
+ - item → <ul><li>item</li></ul>
78
+ 1. item → <ol><li>item</li></ol>
79
+ ```
80
+
81
+ **Tables:**
41
82
  ```
42
- CQL: title = "[SRS] {feature-name}" AND space = "{space_key}"
83
+ | H1 | H2 | → <table><tbody>
84
+ |----|----| → <tr><th>H1</th><th>H2</th></tr>
85
+ | a | b | <tr><td>a</td><td>b</td></tr>
86
+ </tbody></table>
43
87
  ```
44
- - **Found** → proceed to Step 5 (update)
45
- - **Not found** → proceed to Step 6 (create)
46
88
 
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
89
+ **Code blocksthe ONLY correct place for CDATA:**
90
+ ```
91
+ ```lang → <ac:structured-macro ac:name="code">
92
+ code here <ac:parameter ac:name="language">lang</ac:parameter>
93
+ ``` <ac:plain-text-body><![CDATA[code here]]></ac:plain-text-body>
94
+ </ac:structured-macro>
95
+ ```
96
+ ⚠️ The attribute is `ac:name` not `name`. Using `<ac:parameter name="language">` will cause an XML parse error.
97
+
98
+ **Info/warning/tip boxes:**
99
+ ```
100
+ > [!NOTE] title → <ac:structured-macro ac:name="info">
101
+ > body <ac:parameter ac:name="title">title</ac:parameter>
102
+ <ac:rich-text-body><p>body</p></ac:rich-text-body>
103
+ </ac:structured-macro>
104
+
105
+ > [!WARNING] → ac:name="warning"
106
+ > [!TIP] → ac:name="tip"
107
+ ```
108
+
109
+ **Blockquote:**
110
+ ```
111
+ > text → <blockquote><p>text</p></blockquote>
112
+ ```
113
+
114
+ ### Step 5 — Check if page exists
115
+ Use `confluence_search_pages` to search for a page with that exact title in the configured space.
116
+ - **Found** → proceed to Step 6 (update)
117
+ - **Not found** → proceed to Step 7 (create)
118
+
119
+ ### Step 6 — Update existing page
120
+ Call `confluence_update_page` with:
121
+ - `pageId`: the ID from the search result
122
+ - `bodyStorageValue`: the **storage format HTML** converted in Step 4
123
+ - Version comment: the `[comment]` argument (or "Updated via vsaf-push-srs" if blank)
124
+
125
+ Confirm the two-stage update prompt if the MCP requires it.
126
+
127
+ ### Step 7 — Create new page
128
+ Call `confluence_create_page` with:
129
+ - `spaceKey`: the space key from config
130
+ - `parentId`: the parent page ID resolved in Step 3
131
+ - `title`: the page title determined in Step 3
132
+ - `bodyStorageValue`: the **storage format HTML** converted in Step 4
53
133
 
54
- ### Step 6Create 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)
134
+ > The `bodyStorageValue` parameter takes Confluence Storage Format (XHTML) directly do not add a separate `representation` field.
61
135
 
62
- ### Step 7 — Link SRS page to PRD page (if PRD page exists)
136
+ ### Step 8 — Link SRS page to PRD page (if PRD page exists)
63
137
  - 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
138
+ - If found: prepend this block at the top of the SRS content before pushing:
139
+ ```xml
140
+ <ac:structured-macro ac:name="info">
141
+ <ac:parameter ac:name="title">Related Documents</ac:parameter>
142
+ <ac:rich-text-body><p><a href="{prd_url}">[PRD] {feature-name}</a></p></ac:rich-text-body>
143
+ </ac:structured-macro>
144
+ ```
65
145
  - This creates traceability in Confluence
66
146
 
67
- ### Step 8 — Output to user
147
+ ### Step 9 — Output to user
68
148
  ```
69
149
  ## SRS pushed to Confluence
70
150
 
71
- - Page: [SRS] {feature-name}
72
- - Action: [Created / Updated]
73
- - Space: {space_key}
74
- - Comment: {comment}
75
- - URL: {confluence_page_url}
151
+ - Page: {page_title}
152
+ - Action: [Created / Updated]
153
+ - Space: {space_key}
154
+ - Comment: {comment}
155
+ - URL: {confluence_page_url}
76
156
  - PRD link: [linked / not found]
77
157
 
78
158
  ## Next step
@@ -81,5 +161,6 @@ Run /vsaf-test to generate testcases from this SRS, or /vsaf-build to implement
81
161
 
82
162
  ## Notes
83
163
  - 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
164
+ - Do not modify the local file during this step
85
165
  - SRS result files (`*-results.md`) are test outputs — push those separately if needed
166
+ - The file argument accepts any markdown file path or directory, not just files under `.vsaf/`