bmad-dashboard 1.0.10 → 1.0.12
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/README.md +2 -2
- package/package.json +1 -1
- package/server/artifactDetails.js +22 -7
package/README.md
CHANGED
|
@@ -159,9 +159,9 @@ On every **push to `main`**, GitHub Actions:
|
|
|
159
159
|
1. Runs tests and build in the `dashboard/` directory.
|
|
160
160
|
2. If tests pass, bumps the **patch** version (e.g. `1.0.9` → `1.0.10`), publishes to npm via **Trusted Publishers (OIDC)**, and commits the version bump back to `main` (with message `chore(release): 1.0.10 [skip ci]` so the release commit does not trigger another publish).
|
|
161
161
|
|
|
162
|
-
**Setup (one-time):**
|
|
162
|
+
**Setup (one-time), either:** **Option A — Granular token (recommended):** Create a [Granular access token](https://docs.npmjs.com/about-access-tokens) on npm with **read and write** access for this package and **Bypass 2FA** enabled. Add it as repo secret **`NPM_TOKEN`** under **Settings** → **Secrets and variables** → **Actions**. **Option B — Trusted Publishers (OIDC):** Link npm to GitHub and set Trusted publishing for this package (workflow `release.yml`) on npmjs.com; leave `NPM_TOKEN` unset. The workflow file is `.github/workflows/release.yml`.
|
|
163
163
|
|
|
164
|
-
**If
|
|
164
|
+
**If OIDC gives 404 on publish:** The package must exist on npm before you can add a Trusted Publisher (you configure it in the package’s Settings). If [npmjs.com/package/bmad-dashboard](https://www.npmjs.com/package/bmad-dashboard) returns 404, do **one manual publish** from your machine: `cd dashboard && npm login && npm publish --access public` (enter OTP when prompted). After that, add the Trusted Publisher for `release.yml` in the package settings; then CI can publish future versions.
|
|
165
165
|
|
|
166
166
|
---
|
|
167
167
|
|
package/package.json
CHANGED
|
@@ -11,20 +11,23 @@ import {
|
|
|
11
11
|
|
|
12
12
|
const ARCH_STEP_IDS = [1, 2, 3, 4, 5, 6, 7, 8]
|
|
13
13
|
|
|
14
|
-
/** Match a single AC line: bold type (Given/When/Then/And) or plain type, then text */
|
|
15
|
-
const AC_LINE_BOLD =
|
|
16
|
-
const AC_LINE_PLAIN =
|
|
14
|
+
/** Match a single AC line: bold type (Given/When/Then/And) or plain type, then text. Support both - and * bullets. */
|
|
15
|
+
const AC_LINE_BOLD = /^[-*]\s*\*\*(Given|When|Then|And)\s*:?\s*(?:\*\*\s*)?(.+)$/
|
|
16
|
+
const AC_LINE_PLAIN = /^[-*]\s*(Given|When|Then|And)\s*:?\s*(.+)$/
|
|
17
17
|
|
|
18
18
|
function parseStoryBody(body, num, title, statusByKey) {
|
|
19
19
|
const id = num.replace('.', '-')
|
|
20
|
-
const rest = (body || '').trim()
|
|
20
|
+
const rest = (body || '').replace(/\r\n/g, '\n').replace(/\r/g, '\n').trim()
|
|
21
21
|
let userStory = ''
|
|
22
22
|
const acceptanceCriteria = []
|
|
23
|
-
// Multiple possible markers for start of acceptance criteria block
|
|
23
|
+
// Multiple possible markers for start of acceptance criteria block (case-insensitive)
|
|
24
24
|
const acMarkers = [
|
|
25
25
|
/\*\*Acceptance Criteria\s*:?\s*\*\*/i,
|
|
26
|
+
/\*\*Acceptance criteria\s*:?\s*\*\*/i,
|
|
26
27
|
/^Acceptance Criteria\s*:?\s*$/im,
|
|
28
|
+
/^Acceptance criteria\s*:?\s*$/im,
|
|
27
29
|
/^#+\s*Acceptance Criteria\s*:?\s*$/im,
|
|
30
|
+
/^#+\s*Acceptance criteria\s*:?\s*$/im,
|
|
28
31
|
]
|
|
29
32
|
let acIndex = -1
|
|
30
33
|
let acBlockStart = 0
|
|
@@ -44,10 +47,21 @@ function parseStoryBody(body, num, title, statusByKey) {
|
|
|
44
47
|
const acBlock = rest.slice(acBlockStart).trim()
|
|
45
48
|
const acLines = acBlock.split(/\n/).map((line) => line.trim()).filter(Boolean)
|
|
46
49
|
for (const line of acLines) {
|
|
50
|
+
if (line.startsWith('###')) break // next story or heading
|
|
47
51
|
let m = line.match(AC_LINE_BOLD)
|
|
48
52
|
if (!m) m = line.match(AC_LINE_PLAIN)
|
|
49
53
|
if (m) acceptanceCriteria.push({ type: m[1], text: m[2].trim() })
|
|
50
|
-
else if (line.startsWith('- ')
|
|
54
|
+
else if ((line.startsWith('- ') || line.startsWith('* ')) && line.length > 2)
|
|
55
|
+
acceptanceCriteria.push({ type: null, text: line.slice(2).trim() })
|
|
56
|
+
}
|
|
57
|
+
// If we found AC header but no criteria matched, take any list items in the block
|
|
58
|
+
if (acceptanceCriteria.length === 0 && acBlock.length > 0) {
|
|
59
|
+
for (const line of acLines) {
|
|
60
|
+
if (line.startsWith('###')) break
|
|
61
|
+
const bullet = line.match(/^[-*]\s+(.+)$/) || line.match(/^\d+\.\s+(.+)$/)
|
|
62
|
+
if (bullet && bullet[1].trim().length > 0)
|
|
63
|
+
acceptanceCriteria.push({ type: null, text: bullet[1].trim() })
|
|
64
|
+
}
|
|
51
65
|
}
|
|
52
66
|
}
|
|
53
67
|
// Fallback: no AC header but body has bullet list that looks like criteria (Given/When/Then/And)
|
|
@@ -58,7 +72,8 @@ function parseStoryBody(body, num, title, statusByKey) {
|
|
|
58
72
|
let m = t.match(AC_LINE_BOLD)
|
|
59
73
|
if (!m) m = t.match(AC_LINE_PLAIN)
|
|
60
74
|
if (m) acceptanceCriteria.push({ type: m[1], text: m[2].trim() })
|
|
61
|
-
else if (t.startsWith('- ')
|
|
75
|
+
else if ((t.startsWith('- ') || t.startsWith('* ')) && t.length > 2)
|
|
76
|
+
acceptanceCriteria.push({ type: null, text: t.slice(2).trim() })
|
|
62
77
|
}
|
|
63
78
|
}
|
|
64
79
|
if (!userStory && rest) {
|