ma-agents 3.8.0 → 3.11.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.
- package/README.md +13 -5
- package/bin/cli.js +140 -63
- package/lib/agents.js +12 -20
- package/lib/bmad-cache/cache-manifest.json +8 -8
- package/lib/bmad-cache/cis/_git_preserved/index +0 -0
- package/lib/bmad-cache/cis/_git_preserved/logs/HEAD +1 -1
- package/lib/bmad-cache/cis/_git_preserved/logs/refs/heads/main +1 -1
- package/lib/bmad-cache/cis/_git_preserved/logs/refs/remotes/origin/HEAD +1 -1
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-42ffc048f54e58ce94c6331bc6be97ebbb7936f2.idx +0 -0
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/{pack-cad8ff313ea5db860ddcc7780f03917dcba1da8d.pack → pack-42ffc048f54e58ce94c6331bc6be97ebbb7936f2.pack} +0 -0
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-42ffc048f54e58ce94c6331bc6be97ebbb7936f2.rev +0 -0
- package/lib/bmad-cache/cis/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/cis/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/cis/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/cis/src/module-help.csv +5 -5
- package/lib/bmad-cache/gds/_git_preserved/index +0 -0
- package/lib/bmad-cache/gds/_git_preserved/logs/HEAD +1 -1
- package/lib/bmad-cache/gds/_git_preserved/logs/refs/heads/main +1 -1
- package/lib/bmad-cache/gds/_git_preserved/logs/refs/remotes/origin/HEAD +1 -1
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-9427a146a90c00bb542cba038874bf9671ba4dc0.idx +0 -0
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/{pack-c1322f7c8531a89dc4f3f34c4955d194f286c1e6.pack → pack-9427a146a90c00bb542cba038874bf9671ba4dc0.pack} +0 -0
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-9427a146a90c00bb542cba038874bf9671ba4dc0.rev +0 -0
- package/lib/bmad-cache/gds/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/gds/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/gds/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/gds/src/module-help.csv +34 -34
- package/lib/bmad-cache/tea/.claude-plugin/marketplace.json +1 -1
- package/lib/bmad-cache/tea/.github/workflows/publish.yaml +168 -0
- package/lib/bmad-cache/tea/README.md +67 -57
- package/lib/bmad-cache/tea/_git_preserved/index +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-f0df537f2649464ff6c5aee241165eb9c8664227.idx +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/{pack-9b16db8eb5022c18cef1f0a27d63b6e0f4bc2b2a.pack → pack-f0df537f2649464ff6c5aee241165eb9c8664227.pack} +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-f0df537f2649464ff6c5aee241165eb9c8664227.rev +0 -0
- package/lib/bmad-cache/tea/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/tea/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/tea/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/tea/package-lock.json +2 -2
- package/lib/bmad-cache/tea/package.json +5 -6
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/contract-testing.md +2 -3
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pact-consumer-framework-setup.md +42 -95
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pactjs-utils-consumer-helpers.md +5 -6
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pactjs-utils-provider-verifier.md +1 -1
- package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/tea-index.csv +1 -1
- package/lib/bmad-cache/tea/src/module-help.csv +9 -9
- package/lib/bmad-extension/.claude-plugin/marketplace.json.template +2 -2
- package/lib/bmad-extension/skills/add-sprint/SKILL.md +39 -0
- package/lib/bmad-extension/skills/add-to-sprint/SKILL.md +39 -0
- package/lib/bmad-extension/skills/bmad-dev-story/workflow.md +39 -0
- package/lib/bmad-extension/skills/bmad-sprint-planning/workflow.md +41 -0
- package/lib/bmad-extension/skills/bmad-sprint-status/workflow.md +39 -0
- package/lib/bmad-extension/skills/cleanup-done/SKILL.md +39 -0
- package/lib/bmad-extension/skills/close-sprint/SKILL.md +39 -0
- package/lib/bmad-extension/skills/generate-backlog/SKILL.md +41 -0
- package/lib/bmad-extension/skills/modify-sprint/SKILL.md +39 -0
- package/lib/bmad-extension/skills/module.yaml +1 -1
- package/lib/bmad-extension/skills/prioritize-backlog/SKILL.md +39 -0
- package/lib/bmad-extension/skills/remove-from-sprint/SKILL.md +39 -0
- package/lib/bmad-extension/skills/sprint-status-view/SKILL.md +39 -0
- package/lib/bmad-extension/workflows/add-sprint/workflow.md +39 -0
- package/lib/bmad-extension/workflows/add-to-sprint/workflow.md +39 -0
- package/lib/bmad-extension/workflows/modify-sprint/workflow.md +39 -0
- package/lib/bmad-extension/workflows/sprint-status-view/workflow.md +39 -0
- package/lib/bmad-extension-plugin/.claude-plugin/marketplace.json +2 -2
- package/lib/bmad-extension-plugin/skills/add-sprint/SKILL.md +39 -0
- package/lib/bmad-extension-plugin/skills/add-to-sprint/SKILL.md +39 -0
- package/lib/bmad-extension-plugin/skills/bmad-dev-story/workflow.md +39 -0
- package/lib/bmad-extension-plugin/skills/bmad-sprint-planning/workflow.md +41 -0
- package/lib/bmad-extension-plugin/skills/bmad-sprint-status/workflow.md +39 -0
- package/lib/bmad-extension-plugin/skills/cleanup-done/SKILL.md +39 -0
- package/lib/bmad-extension-plugin/skills/close-sprint/SKILL.md +39 -0
- package/lib/bmad-extension-plugin/skills/generate-backlog/SKILL.md +41 -0
- package/lib/bmad-extension-plugin/skills/modify-sprint/SKILL.md +39 -0
- package/lib/bmad-extension-plugin/skills/module.yaml +1 -1
- package/lib/bmad-extension-plugin/skills/prioritize-backlog/SKILL.md +39 -0
- package/lib/bmad-extension-plugin/skills/remove-from-sprint/SKILL.md +39 -0
- package/lib/bmad-extension-plugin/skills/sprint-status-view/SKILL.md +39 -0
- package/lib/bmad.js +76 -8
- package/lib/installer.js +6 -1
- package/package.json +4 -4
- package/skills/add-sprint/SKILL.md +39 -0
- package/skills/add-to-sprint/SKILL.md +39 -0
- package/skills/bmad-sprint-planning/SKILL.md +41 -0
- package/skills/bmad-sprint-status/SKILL.md +39 -0
- package/skills/cleanup-done/SKILL.md +39 -0
- package/skills/close-sprint/SKILL.md +39 -0
- package/skills/generate-backlog/SKILL.md +41 -0
- package/skills/modify-sprint/SKILL.md +39 -0
- package/skills/prioritize-backlog/SKILL.md +39 -0
- package/skills/remove-from-sprint/SKILL.md +39 -0
- package/skills/sprint-status-view/SKILL.md +39 -0
- package/skills/story-status-lookup/SKILL.md +38 -21
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-cad8ff313ea5db860ddcc7780f03917dcba1da8d.idx +0 -0
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-cad8ff313ea5db860ddcc7780f03917dcba1da8d.rev +0 -0
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-c1322f7c8531a89dc4f3f34c4955d194f286c1e6.idx +0 -0
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-c1322f7c8531a89dc4f3f34c4955d194f286c1e6.rev +0 -0
- package/lib/bmad-cache/tea/.github/workflows/manual-release.yaml +0 -216
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-9b16db8eb5022c18cef1f0a27d63b6e0f4bc2b2a.idx +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-9b16db8eb5022c18cef1f0a27d63b6e0f4bc2b2a.rev +0 -0
package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pact-consumer-framework-setup.md
CHANGED
|
@@ -76,9 +76,9 @@ export default defineConfig({
|
|
|
76
76
|
|
|
77
77
|
**Key Points**:
|
|
78
78
|
|
|
79
|
-
- **`fileParallelism: false` is required** — primary defense against non-deterministic pact generation. Without it, parallel workers race on the shared pact JSON file and corrupt interactions. Symptom: local runs pass, CI randomly fails with `Cannot change pact content for already published pact`.
|
|
79
|
+
- **`fileParallelism: false` is required** — primary defense against non-deterministic pact generation. Without it, parallel workers race on the shared pact JSON file and corrupt interactions. Symptom: local runs pass, CI randomly fails with `Cannot change pact content for already published pact`. The `publish-pact.sh` `jq` sort (Example 4) provides byte-stability at publish time.
|
|
80
80
|
- **`pool: 'forks'` + `singleFork: true` is required for multi-file consumer suites** — same config the provider side uses (`pactjs-utils-provider-verifier.md` Example 7). Best current understanding: the `@pact-foundation/pact` napi-rs binding is not robust across Vitest worker threads sharing a process; with the default threads pool (Vitest v1) and multiple `.pacttest.ts` files on the same consumer+provider pair, we observed reproducible "request was expected but not received" flakes on Linux CI only. `singleFork: true` serializes every pact file into one forked subprocess and eliminated the flake on two repos (`pactjs-utils`, `seon-mcp-server`). Vitest v2+ defaults to `forks`, but set the pool explicitly so the contract does not drift with Vitest version bumps.
|
|
81
|
-
- **
|
|
81
|
+
- **One `.pacttest.ts` per consumer+provider pair is the canonical pattern** — not just an observation. Two files for the same pair in one process (which `singleFork: true` guarantees) cause an FFI handle collision: the second file's `new PactV4(...)` call re-enters the FFI handle still holding stale state from the first file → "request was expected but not received" sporadically on Linux CI. The fix is structural — merge the files, not the config. `pool: 'forks'` is still required for pact JSON write safety but does NOT prevent same-pair file splits from colliding. Multiple files for **different** pairs (different consumer or provider name) are correct and safe. See Example 10 for the ✅/❌ pattern.
|
|
82
82
|
- **Interacting settings**: leave `isolate` at its default (`true`). Do NOT set `sequence.concurrent: true`, `maxConcurrency > 1`, or `maxWorkers > 1` in this config — they defeat the serialization this rule relies on. `hookTimeout` may be raised if mock-server startup is slow, but keep `testTimeout` ≥ `hookTimeout`.
|
|
83
83
|
- Do NOT add `setupFiles`, `coverage`, or other settings from the unit test config
|
|
84
84
|
- Keep it minimal — Pact tests run in Node environment with extended timeout
|
|
@@ -96,8 +96,7 @@ export default defineConfig({
|
|
|
96
96
|
```json
|
|
97
97
|
{
|
|
98
98
|
"scripts": {
|
|
99
|
-
"test:pact:consumer": "
|
|
100
|
-
"test:pact:consumer:run": "vitest run --config vitest.config.pact.ts",
|
|
99
|
+
"test:pact:consumer": "vitest run --config vitest.config.pact.ts",
|
|
101
100
|
"publish:pact": ". ./scripts/env-setup.sh && ./scripts/publish-pact.sh",
|
|
102
101
|
"can:i:deploy:consumer": ". ./scripts/env-setup.sh && PACTICIPANT=<service-name> ./scripts/can-i-deploy.sh",
|
|
103
102
|
"record:consumer:deployment": ". ./scripts/env-setup.sh && PACTICIPANT=<service-name> ./scripts/record-deployment.sh"
|
|
@@ -109,8 +108,6 @@ Replace `<service-name>` with the consumer's pacticipant name (e.g., `my-fronten
|
|
|
109
108
|
|
|
110
109
|
**Key Points**:
|
|
111
110
|
|
|
112
|
-
- **`test:pact:consumer` IS the determinism gate** — it runs the inner command 3× and fails if pact output is not byte-stable. This is the command CI and developers run before pushing. See Example 10 for the `check-pact-determinism.sh` script itself.
|
|
113
|
-
- **`test:pact:consumer:run` is the fast inner command** for TDD loops (a single pass of the suite, no gate). Developers can iterate with this; CI always goes through the outer gated script.
|
|
114
111
|
- Use colon-separated naming: `test:pact:consumer`, NOT `test:contract` or `test:contract:consumer`
|
|
115
112
|
- Broker scripts source `env-setup.sh` inline in package.json (`. ./scripts/env-setup.sh && ...`)
|
|
116
113
|
- `PACTICIPANT` is set per-script invocation, not globally
|
|
@@ -139,7 +136,7 @@ export GITHUB_SHA="${GITHUB_SHA:-$(git rev-parse --short HEAD)}"
|
|
|
139
136
|
export GITHUB_BRANCH="${GITHUB_BRANCH:-$(git rev-parse --abbrev-ref HEAD)}"
|
|
140
137
|
```
|
|
141
138
|
|
|
142
|
-
#### `scripts/publish-pact.sh` — Publish Pacts to Broker
|
|
139
|
+
#### `scripts/publish-pact.sh` — Publish Pacts to Broker
|
|
143
140
|
|
|
144
141
|
```bash
|
|
145
142
|
#!/bin/bash
|
|
@@ -147,9 +144,8 @@ export GITHUB_BRANCH="${GITHUB_BRANCH:-$(git rev-parse --abbrev-ref HEAD)}"
|
|
|
147
144
|
#
|
|
148
145
|
# Before publish, normalize each pact JSON: sort interactions by (description, provider state name,
|
|
149
146
|
# method, path) and sort object keys via `jq -S`. This gives byte-stable output to the broker even
|
|
150
|
-
# if the PactV4 generator produces ordering drift between runs.
|
|
151
|
-
#
|
|
152
|
-
# content" from PactFlow never fires on ordering-only changes that slip past the gate.
|
|
147
|
+
# if the PactV4 generator produces ordering drift between runs. Ensures "Cannot change pact content"
|
|
148
|
+
# from PactFlow never fires on ordering-only changes.
|
|
153
149
|
#
|
|
154
150
|
# Requires: PACT_BROKER_BASE_URL, PACT_BROKER_TOKEN, GITHUB_SHA, GITHUB_BRANCH, jq
|
|
155
151
|
# -e: exit on error -u: error on undefined vars -o pipefail: fail if any pipe segment fails
|
|
@@ -229,7 +225,7 @@ fi
|
|
|
229
225
|
- Use `PACTICIPANT` env var (required via `${PACTICIPANT:?...}`), not hardcoded service names
|
|
230
226
|
- `can-i-deploy` includes `--retry-while-unknown=10 --retry-interval=30` (waits for provider verification)
|
|
231
227
|
- `record-deployment` has branch guard (only records on main/master)
|
|
232
|
-
- **`publish-pact.sh` normalizes interactions with `jq -S` + `sort_by(...)` before publishing** —
|
|
228
|
+
- **`publish-pact.sh` normalizes interactions with `jq -S` + `sort_by(...)` before publishing** — ensures byte-stable payload to the broker regardless of generator ordering quirks.
|
|
233
229
|
- Do NOT invent custom env vars like `PACT_CONSUMER_VERSION` or `PACT_BREAKING_CHANGE` in scripts — those are handled by `env-setup.sh` and the CI detect-breaking-change action respectively
|
|
234
230
|
|
|
235
231
|
---
|
|
@@ -276,8 +272,8 @@ jobs:
|
|
|
276
272
|
- name: Install dependencies
|
|
277
273
|
run: npm ci
|
|
278
274
|
|
|
279
|
-
# (1) Generate pact files
|
|
280
|
-
- name:
|
|
275
|
+
# (1) Generate pact files
|
|
276
|
+
- name: Run consumer contract tests
|
|
281
277
|
run: npm run test:pact:consumer
|
|
282
278
|
|
|
283
279
|
# (2) Publish pacts to broker (publish-pact.sh also normalizes interaction order as defense-in-depth)
|
|
@@ -301,8 +297,7 @@ jobs:
|
|
|
301
297
|
|
|
302
298
|
**Key Points**:
|
|
303
299
|
|
|
304
|
-
- **1:1 local/CI parity is a hard rule**: every CI step is `npm run <same-name-a-dev-uses>`. Never let CI invoke `vitest` or `pact-broker` directly — that divergence is how "works on my machine" slips in.
|
|
305
|
-
- **The determinism gate is its own visible step, not a side-effect of publish.** A failing gate must be debuggable from the CI log without re-running. Do not fold it into a `prepublish:pact` hook — folding hides the failure inside a publish log and makes attribution harder.
|
|
300
|
+
- **1:1 local/CI parity is a hard rule**: every CI step is `npm run <same-name-a-dev-uses>`. Never let CI invoke `vitest` or `pact-broker` directly — that divergence is how "works on my machine" slips in. Consumer tests, publish, can-i-deploy, and record-deployment are all the same commands a developer runs locally.
|
|
306
301
|
- **Workflow-level `env` block** for broker secrets and git vars — not per-step
|
|
307
302
|
- **`detect-breaking-change` step** runs before install to set `PACT_BREAKING_CHANGE` env var
|
|
308
303
|
- **Step numbering skips (3)** — step 3 is the webhook-triggered provider verification (happens externally)
|
|
@@ -625,89 +620,42 @@ pact-logs/
|
|
|
625
620
|
|
|
626
621
|
---
|
|
627
622
|
|
|
628
|
-
### Example 10:
|
|
623
|
+
### Example 10: Test File Organization — One File Per Consumer+Provider Pair
|
|
629
624
|
|
|
630
|
-
**Context**:
|
|
625
|
+
**Context**: Avoiding Pact Rust FFI handle collisions when structuring consumer test files.
|
|
631
626
|
|
|
632
|
-
**
|
|
633
|
-
|
|
634
|
-
#### `scripts/check-pact-determinism.sh`
|
|
635
|
-
|
|
636
|
-
```bash
|
|
637
|
-
#!/bin/bash
|
|
638
|
-
# Run a pact consumer command N times and fail if the generated pact files are not byte-stable.
|
|
639
|
-
# Primary defense against PactV4 non-deterministic output.
|
|
640
|
-
#
|
|
641
|
-
# Usage: ./scripts/check-pact-determinism.sh "<cmd>" [runs] [pact-dir]
|
|
642
|
-
# Example: ./scripts/check-pact-determinism.sh 'npm run test:pact:consumer:run' 3 ./pacts
|
|
643
|
-
#
|
|
644
|
-
# Requires: jq installed on the runner (ubuntu-latest has it; macOS users need `brew install jq`).
|
|
645
|
-
set -euo pipefail
|
|
646
|
-
|
|
647
|
-
CMD="${1:?usage: ./scripts/check-pact-determinism.sh \"<cmd>\" [runs] [pact-dir]}"
|
|
648
|
-
RUNS="${PACT_DETERMINISM_RUNS:-${2:-3}}"
|
|
649
|
-
PACT_DIR="${3:-./pacts}"
|
|
627
|
+
**Rule**: Every consumer+provider pair maps to exactly one `.pacttest.ts` file. Never split interactions for the same pair across multiple files.
|
|
650
628
|
|
|
651
|
-
|
|
652
|
-
trap 'rm -rf "$TMP_DIR"' EXIT
|
|
629
|
+
**Root cause**: The Pact Rust FFI maintains one handle per consumer+provider pair per process. With `singleFork: true` (all files run sequentially in one forked process), two files for the same pair access the same FFI handle back-to-back. The second file's `new PactV4({ consumer, provider })` call re-enters the handle still holding stale interaction state from the first file. The first test in the second file starts the mock server in this corrupted state — "request was expected but not received" results, sporadic and Linux-CI-only (execution order differs between environments).
|
|
653
630
|
|
|
654
|
-
|
|
655
|
-
# Sort interactions by (description, first provider state name, method, path), sort keys with -S.
|
|
656
|
-
# The sorted output is what we hash — so ordering-only drift does NOT count as non-determinism here.
|
|
657
|
-
# (The gate catches deeper drift; ordering drift is handled by publish-pact.sh normalization.)
|
|
658
|
-
jq -S '.interactions |= sort_by(.description, (.providerStates[0].name // ""), .request.method, .request.path)' "$1" \
|
|
659
|
-
| shasum -a 256 | awk '{print $1}'
|
|
660
|
-
}
|
|
631
|
+
**Evidence**: In `pactjs-utils`, `movies-read.pacttest.ts` and `movies-write.pacttest.ts` both used `consumer: 'SampleAppConsumer', provider: 'SampleMoviesAPI'`. The vitest config and CI workflow were correct throughout. The fix was merging the two files into `movies.pacttest.ts`. The config was not changed.
|
|
661
632
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
FAIL=0
|
|
680
|
-
for run in $(seq 2 "$RUNS"); do
|
|
681
|
-
if ! diff -q "$TMP_DIR/run-1.hashes" "$TMP_DIR/run-$run.hashes" >/dev/null; then
|
|
682
|
-
FAIL=1
|
|
683
|
-
echo ""
|
|
684
|
-
echo "❌ Pact output differs between run 1 and run $run:"
|
|
685
|
-
diff "$TMP_DIR/run-1.hashes" "$TMP_DIR/run-$run.hashes" || true
|
|
686
|
-
fi
|
|
687
|
-
done
|
|
688
|
-
|
|
689
|
-
if [ "$FAIL" -ne 0 ]; then
|
|
690
|
-
echo ""
|
|
691
|
-
echo "Pact output is non-deterministic across $RUNS runs. Likely causes:"
|
|
692
|
-
echo " • multiple .addInteraction() chained in a single it() block (PactV4 FFI drops one non-deterministically)"
|
|
693
|
-
echo " • fileParallelism: true in vitest.config.pact.ts (workers race on shared pact JSON)"
|
|
694
|
-
echo " • missing pool: 'forks' + singleFork: true (threads pool shares FFI state across files on Linux CI)"
|
|
695
|
-
echo " • Date / random matchers that don't lock a stable example value"
|
|
696
|
-
echo " • provider state params mutating between runs (e.g. Date.now())"
|
|
697
|
-
exit 1
|
|
698
|
-
fi
|
|
699
|
-
|
|
700
|
-
echo "✅ Pact output is byte-stable across $RUNS runs."
|
|
633
|
+
```typescript
|
|
634
|
+
// ❌ WRONG — same consumer+provider pair split across two files
|
|
635
|
+
// movies-read.pacttest.ts
|
|
636
|
+
const pact = new PactV4({ consumer: 'SampleAppConsumer', provider: 'SampleMoviesAPI', ... })
|
|
637
|
+
describe('Read Operations', () => { /* 4 tests: GET /movies, GET /movies/:id */ })
|
|
638
|
+
|
|
639
|
+
// movies-write.pacttest.ts ← second PactV4 for the SAME pair = FFI handle collision
|
|
640
|
+
const pact = new PactV4({ consumer: 'SampleAppConsumer', provider: 'SampleMoviesAPI', ... })
|
|
641
|
+
describe('Write Operations', () => { /* 5 tests: POST, PUT, DELETE */ })
|
|
642
|
+
|
|
643
|
+
// ✅ RIGHT — one file per consumer+provider pair, describe blocks for organization
|
|
644
|
+
// movies.pacttest.ts
|
|
645
|
+
const pact = new PactV4({ consumer: 'SampleAppConsumer', provider: 'SampleMoviesAPI', ... })
|
|
646
|
+
describe('Movies API', () => {
|
|
647
|
+
describe('Read Operations', () => { /* 4 tests */ })
|
|
648
|
+
describe('Write Operations', () => { /* 5 tests */ })
|
|
649
|
+
})
|
|
701
650
|
```
|
|
702
651
|
|
|
703
652
|
**Key Points**:
|
|
704
653
|
|
|
705
|
-
- **
|
|
706
|
-
- **
|
|
707
|
-
- **
|
|
708
|
-
-
|
|
709
|
-
- **
|
|
710
|
-
- **Defense-in-depth with `publish-pact.sh` normalization** (Example 4): the gate catches pre-publish drift; the publish-time `jq` sort ensures any ordering-only drift that slipped past the gate still produces a byte-stable payload to PactFlow.
|
|
654
|
+
- **File = contract**: A `.pacttest.ts` file represents one consumer+provider contract. One contract = one file.
|
|
655
|
+
- **Describe blocks, not files**: Organize by operation type (`Read Operations`, `Write Operations`), resource, or feature — always within one file per pair.
|
|
656
|
+
- **Different pairs = different files**: `ServiceA / BackendAPI` and `ServiceA / AuthAPI` are two contracts and correctly use two separate files. This rule only forbids splitting ONE pair.
|
|
657
|
+
- **`singleFork: true` is not a fix for this**: It ensures correct pact JSON write semantics across files, but when two files share a pair it actually guarantees the FFI collision (both land in the same process). Without it you'd get file-write races instead. Neither is safe. The fix is one file per pair.
|
|
658
|
+
- **Naming convention**: `{domain}.pacttest.ts` when one domain maps to one pair. `{consumer-kebab}-{provider-kebab}.pacttest.ts` when the filename must be self-describing about which pair it covers.
|
|
711
659
|
|
|
712
660
|
---
|
|
713
661
|
|
|
@@ -715,12 +663,11 @@ echo "✅ Pact output is byte-stable across $RUNS runs."
|
|
|
715
663
|
|
|
716
664
|
Before presenting the consumer CDC framework to the user, verify:
|
|
717
665
|
|
|
718
|
-
- [ ] `vitest.config.pact.ts` is minimal **and sets `fileParallelism: false` AND `pool: 'forks'` with `poolOptions.forks.singleFork: true`** (`fileParallelism: false` prevents shared pact JSON corruption from parallel workers; forks + `singleFork: true`
|
|
666
|
+
- [ ] `vitest.config.pact.ts` is minimal **and sets `fileParallelism: false` AND `pool: 'forks'` with `poolOptions.forks.singleFork: true`** (`fileParallelism: false` prevents shared pact JSON corruption from parallel workers; forks + `singleFork: true` is required for pact JSON write safety across files — see Example 2 Key Points for mechanism and evidence)
|
|
667
|
+
- [ ] Each consumer+provider pair is covered by exactly ONE `.pacttest.ts` file — never split interactions for the same pair across multiple files (two `PactV4` instances for the same pair in one process cause FFI handle collision → "request was expected but not received" on Linux CI; `singleFork: true` does NOT prevent this — it ensures both files share one process, which guarantees the collision; see Example 10)
|
|
719
668
|
- [ ] `vitest.config.pact.ts` does NOT set `sequence.concurrent: true`, `maxConcurrency > 1`, `maxWorkers > 1`, or `isolate: false` — all four defeat the serialization the rule relies on
|
|
720
|
-
- [ ] `
|
|
721
|
-
- [ ]
|
|
722
|
-
- [ ] `scripts/publish-pact.sh` normalizes interactions with `jq -S '.interactions |= sort_by(.description, (.providerStates[0].name // ""), .request.method, .request.path)'` before the `pact-broker publish` call (defense-in-depth alongside the gate)
|
|
723
|
-
- [ ] Script names match pactjs-utils (`test:pact:consumer`, `test:pact:consumer:run`, `publish:pact`, `can:i:deploy:consumer`, `record:consumer:deployment`)
|
|
669
|
+
- [ ] `scripts/publish-pact.sh` normalizes interactions with `jq -S '.interactions |= sort_by(.description, (.providerStates[0].name // ""), .request.method, .request.path)'` before the `pact-broker publish` call (ensures byte-stable payload to PactFlow regardless of generator ordering)
|
|
670
|
+
- [ ] Script names match pactjs-utils (`test:pact:consumer`, `publish:pact`, `can:i:deploy:consumer`, `record:consumer:deployment`)
|
|
724
671
|
- [ ] Scripts source `env-setup.sh` inline in package.json
|
|
725
672
|
- [ ] Shell scripts use `pact-broker` not `npx pact-broker`
|
|
726
673
|
- [ ] Shell scripts use `PACTICIPANT` env var pattern
|
|
@@ -730,7 +677,7 @@ Before presenting the consumer CDC framework to the user, verify:
|
|
|
730
677
|
- [ ] CI workflow named `contract-test-consumer.yml`
|
|
731
678
|
- [ ] CI has workflow-level env block (not per-step)
|
|
732
679
|
- [ ] CI has `detect-breaking-change` step before install
|
|
733
|
-
- [ ] CI step (1)
|
|
680
|
+
- [ ] CI step (1) generates pact files (calls `npm run test:pact:consumer`) — its own visible step, not folded into publish
|
|
734
681
|
- [ ] CI steps are 1:1 with developer commands — every CI step calls `npm run <same-name>` a dev would run locally (no direct `vitest` or `pact-broker` invocation)
|
|
735
682
|
- [ ] CI step numbering skips (3) — webhook-triggered provider verification
|
|
736
683
|
- [ ] CI can-i-deploy has `PACT_BREAKING_CHANGE != 'true'` condition
|
package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pactjs-utils-consumer-helpers.md
CHANGED
|
@@ -260,10 +260,9 @@ it.each([
|
|
|
260
260
|
|
|
261
261
|
**Key Points**:
|
|
262
262
|
|
|
263
|
-
- **This rule stacks with two
|
|
264
|
-
- Symptom of violating this rule: the pact file is byte-different between otherwise-identical runs;
|
|
263
|
+
- **This rule stacks with two MANDATORY vitest settings and one file-organization rule. All four address different failure modes; none substitutes for the others**: (1) `fileParallelism: false` — prevents parallel workers racing on the shared pact JSON file; (2) `pool: 'forks'` with `singleFork: true` — required for pact JSON write safety across multiple files; (3) **one `.pacttest.ts` per consumer+provider pair** — `singleFork: true` keeps all files in one process, so two files for the same pair produce an FFI handle collision ("request was expected but not received" on Linux CI, sporadic); (4) one-interaction-per-`it()` (this rule) — prevents the FFI from dropping interactions within a single test body. See `pact-consumer-framework-setup.md` Example 10 for the file-organization ✅/❌ pattern.
|
|
264
|
+
- Symptom of violating this rule: the pact file is byte-different between otherwise-identical runs; PactFlow rejects a republish with `Cannot change pact content`.
|
|
265
265
|
- The rule applies to both HTTP consumer pacts (`PactV4`) and message consumer pacts (`MessageConsumerPact`).
|
|
266
|
-
- See `pact-consumer-framework-setup.md` Example 10 for the determinism gate that automatically catches violations of this rule.
|
|
267
266
|
|
|
268
267
|
## Key Points
|
|
269
268
|
|
|
@@ -278,13 +277,13 @@ it.each([
|
|
|
278
277
|
- **Body shorthand**: `setJsonBody` keeps body-only responses concise and readable
|
|
279
278
|
- **Matchers check type, not value**: `string('My movie')` means "any string", `integer(1)` means "any integer". The example values are arbitrary — the provider can return different values and verification still passes as long as the type matches. Use matchers only in `.willRespondWith()` (responses), never in `.withRequest()` (requests) — Postel's Law applies.
|
|
280
279
|
- **Reuse test values across files**: Interactions are uniquely identified by `uponReceiving` + `.given()`, not by placeholder values. Two test files can both use `testId: 100` without conflicting. On the provider side, shared values simplify state handlers — idempotent handlers (check if exists, create if not) only need to ensure one record exists. Use different values only when testing different states of the same entity type (e.g., `movieExists(100)` for happy paths vs. `movieNotFound(999)` for error paths).
|
|
281
|
-
- **One `addInteraction()` per `it()` block (MANDATORY for PactV4)**: Multiple interactions inside one `it()` cause the Rust FFI to non-deterministically drop interactions. Use one `it()` per interaction or `it.each(...)` for parameterized cases. See Example 6
|
|
280
|
+
- **One `addInteraction()` per `it()` block (MANDATORY for PactV4)**: Multiple interactions inside one `it()` cause the Rust FFI to non-deterministically drop interactions. Use one `it()` per interaction or `it.each(...)` for parameterized cases. See Example 6.
|
|
282
281
|
|
|
283
282
|
## Related Fragments
|
|
284
283
|
|
|
285
284
|
- `pactjs-utils-overview.md` — installation, decision tree, design philosophy
|
|
286
285
|
- `pactjs-utils-provider-verifier.md` — provider-side state handler implementation; same `pool: 'forks'` + `singleFork: true` rule as consumer
|
|
287
|
-
- `pact-consumer-framework-setup.md` — Vitest `fileParallelism: false` + `pool: 'forks'` + `singleFork: true` config
|
|
286
|
+
- `pact-consumer-framework-setup.md` — Vitest `fileParallelism: false` + `pool: 'forks'` + `singleFork: true` config and CI wiring
|
|
288
287
|
- `contract-testing.md` — foundational patterns with raw Pact.js
|
|
289
288
|
|
|
290
289
|
## Anti-Patterns
|
|
@@ -375,6 +374,6 @@ it('returns empty list', async () => {
|
|
|
375
374
|
});
|
|
376
375
|
```
|
|
377
376
|
|
|
378
|
-
See Example 6 above for the full rationale
|
|
377
|
+
See Example 6 above for the full rationale.
|
|
379
378
|
|
|
380
379
|
_Source: @seontechnologies/pactjs-utils consumer-helpers module, pactjs-utils sample-app consumer tests_
|
package/lib/bmad-cache/tea/src/agents/bmad-tea/resources/knowledge/pactjs-utils-provider-verifier.md
CHANGED
|
@@ -296,7 +296,7 @@ export default defineConfig({
|
|
|
296
296
|
- `pactjs-utils-overview.md` — installation, decision tree, design philosophy
|
|
297
297
|
- `pactjs-utils-consumer-helpers.md` — consumer-side state parameter creation, **one-interaction-per-`it()` rule**
|
|
298
298
|
- `pactjs-utils-request-filter.md` — auth injection for provider verification
|
|
299
|
-
- `pact-consumer-framework-setup.md` — consumer-side framework setup, Vitest `fileParallelism: false`,
|
|
299
|
+
- `pact-consumer-framework-setup.md` — consumer-side framework setup, Vitest `fileParallelism: false`, CI wiring
|
|
300
300
|
- `pact-broker-webhooks.md` — PactFlow → GitHub webhook auth/staleness for webhook-triggered provider verification (`contract_requiring_verification_published`)
|
|
301
301
|
- `contract-testing.md` — foundational patterns with raw Pact.js
|
|
302
302
|
|
|
@@ -38,7 +38,7 @@ pactjs-utils-consumer-helpers,Pact.js Utils Consumer Helpers,"createProviderStat
|
|
|
38
38
|
pactjs-utils-provider-verifier,Pact.js Utils Provider Verifier,"buildVerifierOptions, buildMessageVerifierOptions; vitest pool:forks + singleFork for FFI safety (same rule applies to consumer and provider)","pactjs-utils,provider,consumer,contract-testing,pact,api,backend,ci,vitest,ffi",specialized,knowledge/pactjs-utils-provider-verifier.md
|
|
39
39
|
pactjs-utils-request-filter,Pact.js Utils Request Filter,"createRequestFilter, noOpRequestFilter for auth injection","pactjs-utils,auth,contract-testing,pact",specialized,knowledge/pactjs-utils-request-filter.md
|
|
40
40
|
pact-mcp,Pact MCP Server,"SmartBear MCP for PactFlow: generate tests, review, can-i-deploy, provider states","pact,mcp,pactflow,contract-testing,broker",specialized,knowledge/pact-mcp.md
|
|
41
|
-
pact-consumer-framework-setup,Pact Consumer CDC Framework Setup,"Directory structure, vitest config with fileParallelism:false + pool:forks + singleFork:true (FFI safety),
|
|
41
|
+
pact-consumer-framework-setup,Pact Consumer CDC Framework Setup,"Directory structure, vitest config with fileParallelism:false + pool:forks + singleFork:true (FFI safety), one-file-per-consumer+provider-pair rule (FFI handle collision prevention), jq-normalized publishing, 1:1 local/CI parity, PactV4 patterns","pactjs-utils,consumer,contract-testing,pact,ci,framework,setup,vitest,shell-scripts,jq,pactv4,ffi,file-organization,one-file-per-pair",specialized,knowledge/pact-consumer-framework-setup.md
|
|
42
42
|
pact-broker-webhooks,Pact Broker Webhooks,"PactFlow → GitHub repository_dispatch auth via dedicated machine user + classic PAT (repo scope, no expiration) + PactFlow secret; staleness monitoring and PAT rotation runbook","pact,pactflow,broker,webhooks,github,auth,pat,ci,operations,security",specialized,knowledge/pact-broker-webhooks.md
|
|
43
43
|
adr-quality-readiness-checklist,ADR Quality Readiness Checklist,"8-category 29-criteria framework for ADR testability and NFR assessment","nfr,testability,adr,quality,assessment,checklist",extended,knowledge/adr-quality-readiness-checklist.md
|
|
44
44
|
playwright-cli,Playwright CLI,"Token-efficient CLI for AI coding agents: element refs, sessions, snapshots, trace analysis, debug=cli autonomous investigation","cli,browser,agent,automation,snapshot,trace,debug",core,knowledge/playwright-cli.md
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
module,skill,display-name,menu-code,description,action,args,phase,after,before,required,output-location,outputs
|
|
2
2
|
Test Architecture Enterprise,_meta,,,,,,,,,false,https://bmad-code-org.github.io/bmad-method-test-architecture-enterprise/llms.txt,
|
|
3
|
-
Test Architecture Enterprise,bmad-teach-me-testing,Teach Me Testing,TMT,Teach testing fundamentals through 7 sessions (TEA Academy)
|
|
4
|
-
Test Architecture Enterprise,bmad-testarch-test-design,Test Design,TD,Risk-based test planning
|
|
5
|
-
Test Architecture Enterprise,bmad-testarch-framework,Test Framework,TF,Initialize production-ready test framework
|
|
6
|
-
Test Architecture Enterprise,bmad-testarch-ci,CI Setup,CI,Configure CI/CD quality pipeline
|
|
7
|
-
Test Architecture Enterprise,bmad-testarch-atdd,ATDD,AT,Generate red-phase acceptance test scaffolds before implementation
|
|
8
|
-
Test Architecture Enterprise,bmad-testarch-automate,Test Automation,TA,Expand test coverage
|
|
9
|
-
Test Architecture Enterprise,bmad-testarch-test-review,Test Review,RV,Quality audit (0-100 scoring)
|
|
10
|
-
Test Architecture Enterprise,bmad-testarch-nfr,NFR Assessment,NR,Non-functional requirements assessment
|
|
11
|
-
Test Architecture Enterprise,bmad-testarch-trace,Traceability,TR,Coverage traceability and gate
|
|
3
|
+
Test Architecture Enterprise,bmad-teach-me-testing,Teach Me Testing,TMT,Teach testing fundamentals through 7 sessions (TEA Academy).,,,0-learning,,,false,test_artifacts,progress file|session notes|certificate
|
|
4
|
+
Test Architecture Enterprise,bmad-testarch-test-design,Test Design,TD,Risk-based test planning.,,,3-solutioning,,bmad-testarch-framework,false,test_artifacts,test design document
|
|
5
|
+
Test Architecture Enterprise,bmad-testarch-framework,Test Framework,TF,Initialize production-ready test framework.,,,3-solutioning,bmad-testarch-test-design,bmad-testarch-ci,false,test_artifacts,framework scaffold
|
|
6
|
+
Test Architecture Enterprise,bmad-testarch-ci,CI Setup,CI,Configure CI/CD quality pipeline.,,,3-solutioning,bmad-testarch-framework,,false,test_artifacts,ci config
|
|
7
|
+
Test Architecture Enterprise,bmad-testarch-atdd,ATDD,AT,Generate red-phase acceptance test scaffolds before implementation.,,,4-implementation,bmad-create-story:create,bmad-dev-story,false,test_artifacts,atdd-checklist|red-phase acceptance tests
|
|
8
|
+
Test Architecture Enterprise,bmad-testarch-automate,Test Automation,TA,Expand test coverage.,,,4-implementation,bmad-testarch-atdd,,false,test_artifacts,test suite
|
|
9
|
+
Test Architecture Enterprise,bmad-testarch-test-review,Test Review,RV,Quality audit (0-100 scoring).,,,4-implementation,bmad-testarch-automate,,false,test_artifacts,review report
|
|
10
|
+
Test Architecture Enterprise,bmad-testarch-nfr,NFR Assessment,NR,Non-functional requirements assessment.,,,4-implementation,bmad-testarch-automate,,false,test_artifacts,nfr report
|
|
11
|
+
Test Architecture Enterprise,bmad-testarch-trace,Traceability,TR,Coverage traceability and gate.,,,4-implementation,bmad-testarch-test-review,,false,test_artifacts,traceability matrix|gate decision
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"_comment": [
|
|
3
3
|
"BMAD Builder convention: the wrapper directory '.claude-plugin/' is a SHARED convention used by skills-capable platforms — it is NOT a Claude-only binding. BMAD adopted Anthropic's published plugin layout because it was the closest thing to an open standard at the time; multi-tool routing (claude-code, copilot, cline, roo-code, kilocode, cursor) is handled by BMAD's own installer based on the --tools flag. See https://bmad-builder-docs.bmad-method.org/how-to/distribute-your-module/ and https://bmad-builder-docs.bmad-method.org/explanation/.",
|
|
4
4
|
"This is a TEMPLATE file consumed by scripts/build-plugin.js (Story 22.4). Tokens of the form ${var} are replaced at build time; the resolved manifest lands at lib/bmad-extension-plugin/.claude-plugin/marketplace.json. Do NOT hand-edit the generated file.",
|
|
5
|
-
"Fields follow the v6.
|
|
5
|
+
"Fields follow the v6.6.0 schema read by tools/installer/modules/custom-module-manager.js (top-level: name, owner, description, license, homepage, repository, keywords; per-plugin: name, source, description, version, author, skills[]).",
|
|
6
6
|
"plugins[].source interpretation: a value of \"./\" means 'the directory containing .claude-plugin/' — i.e. the plugin output root (lib/bmad-extension-plugin/). Skill paths (\"./skills/<name>\") are resolved relative to that same root. Story 22.4's build script MUST honor this convention.",
|
|
7
7
|
"compatible_tools is an informational, BMAD-wide convention (not read by the installer) used to signal multi-tool parity with downstream consumers. The authoritative list of supported tools is the --tools flag accepted by the BMAD installer.",
|
|
8
8
|
"bmad_min_version forward-compat policy: this floor assumes upstream bmad-method changes remain additive (new fields / new optional schema). Any breaking upstream change requires bumping bmad_min_version in lockstep with the pinned bmad-method dependency in package.json."
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"roo-code",
|
|
40
40
|
"kilocode"
|
|
41
41
|
],
|
|
42
|
-
"bmad_min_version": "6.
|
|
42
|
+
"bmad_min_version": "6.6.0",
|
|
43
43
|
"plugins": [
|
|
44
44
|
{
|
|
45
45
|
"name": "ma-skills",
|
|
@@ -11,6 +11,45 @@ triggers:
|
|
|
11
11
|
|
|
12
12
|
Guided workflow to create a new sprint entry in the `sprints` section of `sprint-status.yaml` with capacity limits, optional ISO dates, and auto-incremented sprint ID.
|
|
13
13
|
|
|
14
|
+
## Backend Routing
|
|
15
|
+
|
|
16
|
+
Before executing any file-system operations, determine and route to the correct backend:
|
|
17
|
+
|
|
18
|
+
1. Read `_bmad-output/implementation-artifacts/sprint-status.yaml` and extract the `tracking_system` field.
|
|
19
|
+
If the field is absent or the file does not exist, read `sprint_backend` from `_bmad/bmm/config.yaml`. Use that value if present, otherwise default to `file-system`.
|
|
20
|
+
|
|
21
|
+
2. If `tracking_system` is `file-system`:
|
|
22
|
+
Proceed with the **File-System Backend** instructions below.
|
|
23
|
+
|
|
24
|
+
3. If `tracking_system` is `jira`:
|
|
25
|
+
a. Perform the Jira operation: Create a new sprint in the board for project `{jira_project_key}` at `{jira_url}` using the sprint create API. Set the sprint name, goal (if provided), start date, and end date from the provided sprint data. The new sprint starts in "future/planning" state.
|
|
26
|
+
Use whatever Jira-capable tool is available in your current tool context.
|
|
27
|
+
Map Jira entities to the canonical schema (Sprint → sprints[], Backlog → backlog[],
|
|
28
|
+
Epic → epics[], Jira status → canonical vocabulary per Section 6.3 of the routing spec).
|
|
29
|
+
b. If the Jira operation SUCCEEDS: continue with the Jira data returned. Jira is the source of truth.
|
|
30
|
+
c. If the Jira operation FAILS for any reason:
|
|
31
|
+
- If no Jira-capable tool is available in your current context:
|
|
32
|
+
Pause and present the user with:
|
|
33
|
+
> "No Jira-capable tool is available. To use Jira tracking, configure a Jira integration
|
|
34
|
+
> in your agent (an MCP server, plugin, or native integration connected to the Jira
|
|
35
|
+
> instance at `{jira_url}`). How would you like to proceed?
|
|
36
|
+
> (a) Retry — attempt the Jira operation again once a Jira tool is configured
|
|
37
|
+
> (b) Switch to file management — update sprint-status.yaml and config to use
|
|
38
|
+
> file-system backend, then complete this operation locally. This change is permanent."
|
|
39
|
+
- If a Jira tool attempted the operation but returned an error:
|
|
40
|
+
Pause and present the user with:
|
|
41
|
+
> "The Jira operation failed: {actual Jira error details}. How would you like to proceed?
|
|
42
|
+
> (a) Retry — attempt the Jira operation again
|
|
43
|
+
> (b) Switch to file management — update sprint-status.yaml and config to use
|
|
44
|
+
> file-system backend, then complete this operation locally. This change is permanent."
|
|
45
|
+
If user chooses (b) in either case: write `tracking_system: file-system` to `sprint-status.yaml`,
|
|
46
|
+
update `sprint_backend: file-system` in `_bmad/bmm/config.yaml`,
|
|
47
|
+
then proceed with **File-System Backend** instructions below.
|
|
48
|
+
|
|
49
|
+
4. **File-System Backend** — execute the workflow steps below.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
14
53
|
<workflow>
|
|
15
54
|
|
|
16
55
|
<step n="0" goal="Load configuration and validate file existence">
|
|
@@ -13,6 +13,45 @@ Guided workflow to move backlog items to a sprint in the unified `sprint-status.
|
|
|
13
13
|
|
|
14
14
|
**Movement semantics:** Each item exists in exactly one location — either the `backlog` array OR a sprint's `items` array, never both. This skill atomically removes items from `backlog` and appends them to the target sprint's `items` array in a single file write.
|
|
15
15
|
|
|
16
|
+
## Backend Routing
|
|
17
|
+
|
|
18
|
+
Before executing any file-system operations, determine and route to the correct backend:
|
|
19
|
+
|
|
20
|
+
1. Read `_bmad-output/implementation-artifacts/sprint-status.yaml` and extract the `tracking_system` field.
|
|
21
|
+
If the field is absent or the file does not exist, read `sprint_backend` from `_bmad/bmm/config.yaml`. Use that value if present, otherwise default to `file-system`.
|
|
22
|
+
|
|
23
|
+
2. If `tracking_system` is `file-system`:
|
|
24
|
+
Proceed with the **File-System Backend** instructions below.
|
|
25
|
+
|
|
26
|
+
3. If `tracking_system` is `jira`:
|
|
27
|
+
a. Perform the Jira operation: Find the Jira issue matching the item ID in project `{jira_project_key}` at `{jira_url}` (search by issue key or summary). Find the active sprint on the board for project `{jira_project_key}`. Move the issue to the active sprint using the "add issue to sprint" operation.
|
|
28
|
+
Use whatever Jira-capable tool is available in your current tool context.
|
|
29
|
+
Map Jira entities to the canonical schema (Sprint → sprints[], Backlog → backlog[],
|
|
30
|
+
Epic → epics[], Jira status → canonical vocabulary per Section 6.3 of the routing spec).
|
|
31
|
+
b. If the Jira operation SUCCEEDS: continue with the Jira data returned. Jira is the source of truth.
|
|
32
|
+
c. If the Jira operation FAILS for any reason:
|
|
33
|
+
- If no Jira-capable tool is available in your current context:
|
|
34
|
+
Pause and present the user with:
|
|
35
|
+
> "No Jira-capable tool is available. To use Jira tracking, configure a Jira integration
|
|
36
|
+
> in your agent (an MCP server, plugin, or native integration connected to the Jira
|
|
37
|
+
> instance at `{jira_url}`). How would you like to proceed?
|
|
38
|
+
> (a) Retry — attempt the Jira operation again once a Jira tool is configured
|
|
39
|
+
> (b) Switch to file management — update sprint-status.yaml and config to use
|
|
40
|
+
> file-system backend, then complete this operation locally. This change is permanent."
|
|
41
|
+
- If a Jira tool attempted the operation but returned an error:
|
|
42
|
+
Pause and present the user with:
|
|
43
|
+
> "The Jira operation failed: {actual Jira error details}. How would you like to proceed?
|
|
44
|
+
> (a) Retry — attempt the Jira operation again
|
|
45
|
+
> (b) Switch to file management — update sprint-status.yaml and config to use
|
|
46
|
+
> file-system backend, then complete this operation locally. This change is permanent."
|
|
47
|
+
If user chooses (b) in either case: write `tracking_system: file-system` to `sprint-status.yaml`,
|
|
48
|
+
update `sprint_backend: file-system` in `_bmad/bmm/config.yaml`,
|
|
49
|
+
then proceed with **File-System Backend** instructions below.
|
|
50
|
+
|
|
51
|
+
4. **File-System Backend** — execute the workflow steps below.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
16
55
|
<workflow>
|
|
17
56
|
|
|
18
57
|
<step n="0" goal="Load configuration and validate file existence">
|
|
@@ -36,6 +36,45 @@ Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
|
|
|
36
36
|
|
|
37
37
|
---
|
|
38
38
|
|
|
39
|
+
## Backend Routing
|
|
40
|
+
|
|
41
|
+
Before executing any status-update operations, determine and route to the correct backend:
|
|
42
|
+
|
|
43
|
+
1. Read `_bmad-output/implementation-artifacts/sprint-status.yaml` and extract the `tracking_system` field.
|
|
44
|
+
If the field is absent or the file does not exist, read `sprint_backend` from `_bmad/bmm/config.yaml`. Use that value if present, otherwise default to `file-system`.
|
|
45
|
+
|
|
46
|
+
2. If `tracking_system` is `file-system`:
|
|
47
|
+
Proceed with the **File-System Backend** instructions below.
|
|
48
|
+
|
|
49
|
+
3. If `tracking_system` is `jira`:
|
|
50
|
+
a. Perform the Jira operation: Find the Jira issue matching the item ID in project `{jira_project_key}` at `{jira_url}` (search by issue key or summary). Transition the issue to the new status using the Jira issue transition API. Map canonical status to Jira workflow status: backlog → Backlog/Open, ready-for-dev → To Do/Selected for Development, in-progress → In Progress, review → In Review/Code Review, done → Done/Resolved, on-hold → On Hold/Blocked, cancelled → Won't Do/Cancelled.
|
|
51
|
+
Use whatever Jira-capable tool is available in your current tool context.
|
|
52
|
+
Map Jira entities to the canonical schema (Sprint → sprints[], Backlog → backlog[],
|
|
53
|
+
Epic → epics[], Jira status → canonical vocabulary per Section 6.3 of the routing spec).
|
|
54
|
+
b. If the Jira operation SUCCEEDS: continue with the Jira data returned. Jira is the source of truth.
|
|
55
|
+
c. If the Jira operation FAILS for any reason:
|
|
56
|
+
- If no Jira-capable tool is available in your current context:
|
|
57
|
+
Pause and present the user with:
|
|
58
|
+
> "No Jira-capable tool is available. To use Jira tracking, configure a Jira integration
|
|
59
|
+
> in your agent (an MCP server, plugin, or native integration connected to the Jira
|
|
60
|
+
> instance at `{jira_url}`). How would you like to proceed?
|
|
61
|
+
> (a) Retry — attempt the Jira operation again once a Jira tool is configured
|
|
62
|
+
> (b) Switch to file management — update sprint-status.yaml and config to use
|
|
63
|
+
> file-system backend, then complete this operation locally. This change is permanent."
|
|
64
|
+
- If a Jira tool attempted the operation but returned an error:
|
|
65
|
+
Pause and present the user with:
|
|
66
|
+
> "The Jira operation failed: {actual Jira error details}. How would you like to proceed?
|
|
67
|
+
> (a) Retry — attempt the Jira operation again
|
|
68
|
+
> (b) Switch to file management — update sprint-status.yaml and config to use
|
|
69
|
+
> file-system backend, then complete this operation locally. This change is permanent."
|
|
70
|
+
If user chooses (b) in either case: write `tracking_system: file-system` to `sprint-status.yaml`,
|
|
71
|
+
update `sprint_backend: file-system` in `_bmad/bmm/config.yaml`,
|
|
72
|
+
then proceed with **File-System Backend** instructions below.
|
|
73
|
+
|
|
74
|
+
4. **File-System Backend** — execute the workflow steps below.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
39
78
|
## EXECUTION
|
|
40
79
|
|
|
41
80
|
<workflow>
|
|
@@ -42,6 +42,47 @@ Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
|
|
|
42
42
|
|
|
43
43
|
---
|
|
44
44
|
|
|
45
|
+
## Backend Routing
|
|
46
|
+
|
|
47
|
+
Before executing any file-system operations, determine and route to the correct backend:
|
|
48
|
+
|
|
49
|
+
1. Read `_bmad-output/implementation-artifacts/sprint-status.yaml` and extract the `tracking_system` field.
|
|
50
|
+
If the field is absent or the file does not exist, read `sprint_backend` from `_bmad/bmm/config.yaml`. Use that value if present, otherwise default to `file-system`.
|
|
51
|
+
|
|
52
|
+
2. If `tracking_system` is `file-system`:
|
|
53
|
+
Proceed with the **File-System Backend** instructions below.
|
|
54
|
+
|
|
55
|
+
3. If `tracking_system` is `jira`:
|
|
56
|
+
> "This operation will create/update Jira sprints and items in bulk. If it fails mid-way, Jira may be in partial state. The Jira server URL is `{jira_url}` and project key is `{jira_project_key}` (from `_bmad/bmm/config.yaml`). Proceed?"
|
|
57
|
+
|
|
58
|
+
a. Perform the Jira operation: Query all epics, backlog issues, sprint definitions, and sprint items for project `{jira_project_key}` at `{jira_url}` (multiple sequential read calls). For the write phase: create new Jira sprints for each sprint definition not already in Jira (one API call per sprint). Create or update Jira issues for each item in the plan (one API call per item). Map item fields as follows: title → issue summary, type → issue type (story → Story, bug → Bug), status → Jira workflow status (see status mapping below), priority → issue priority/rank. Map sprint fields: name → sprint name, start_date → sprint start date, end_date → sprint end date. Status mapping: backlog → Backlog/Open, ready-for-dev → To Do/Selected for Development, in-progress → In Progress, review → In Review/Code Review, done → Done/Resolved, on-hold → On Hold/Blocked, cancelled → Won't Do/Cancelled.
|
|
59
|
+
Use whatever Jira-capable tool is available in your current tool context.
|
|
60
|
+
Map Jira entities to the canonical schema (Sprint → sprints[], Backlog → backlog[],
|
|
61
|
+
Epic → epics[], Jira status → canonical vocabulary per Section 6.3 of the routing spec).
|
|
62
|
+
b. If the Jira operation SUCCEEDS: continue with the Jira data returned. Jira is the source of truth.
|
|
63
|
+
c. If the Jira operation FAILS for any reason:
|
|
64
|
+
- If no Jira-capable tool is available in your current context:
|
|
65
|
+
Pause and present the user with:
|
|
66
|
+
> "No Jira-capable tool is available. To use Jira tracking, configure a Jira integration
|
|
67
|
+
> in your agent (an MCP server, plugin, or native integration connected to the Jira
|
|
68
|
+
> instance at `{jira_url}`). How would you like to proceed?
|
|
69
|
+
> (a) Retry — attempt the Jira operation again once a Jira tool is configured
|
|
70
|
+
> (b) Switch to file management — update sprint-status.yaml and config to use
|
|
71
|
+
> file-system backend, then complete this operation locally. This change is permanent."
|
|
72
|
+
- If a Jira tool attempted the operation but returned an error:
|
|
73
|
+
Pause and present the user with:
|
|
74
|
+
> "The Jira operation failed: {actual Jira error details}. How would you like to proceed?
|
|
75
|
+
> (a) Retry — attempt the Jira operation again
|
|
76
|
+
> (b) Switch to file management — update sprint-status.yaml and config to use
|
|
77
|
+
> file-system backend, then complete this operation locally. This change is permanent."
|
|
78
|
+
If user chooses (b) in either case: write `tracking_system: file-system` to `sprint-status.yaml`,
|
|
79
|
+
update `sprint_backend: file-system` in `_bmad/bmm/config.yaml`,
|
|
80
|
+
then proceed with **File-System Backend** instructions below.
|
|
81
|
+
|
|
82
|
+
4. **File-System Backend** — execute the workflow steps below.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
45
86
|
## EXECUTION
|
|
46
87
|
|
|
47
88
|
<workflow>
|
|
@@ -37,6 +37,45 @@ Load config from `{project-root}/_bmad/bmm/config.yaml` and resolve:
|
|
|
37
37
|
|
|
38
38
|
---
|
|
39
39
|
|
|
40
|
+
## Backend Routing
|
|
41
|
+
|
|
42
|
+
Before executing any file-system operations, determine and route to the correct backend:
|
|
43
|
+
|
|
44
|
+
1. Read `_bmad-output/implementation-artifacts/sprint-status.yaml` and extract the `tracking_system` field.
|
|
45
|
+
If the field is absent or the file does not exist, read `sprint_backend` from `_bmad/bmm/config.yaml`. Use that value if present, otherwise default to `file-system`.
|
|
46
|
+
|
|
47
|
+
2. If `tracking_system` is `file-system`:
|
|
48
|
+
Proceed with the **File-System Backend** instructions below.
|
|
49
|
+
|
|
50
|
+
3. If `tracking_system` is `jira`:
|
|
51
|
+
a. Perform the Jira operation: Query the active sprint for project `{jira_project_key}` at `{jira_url}` and retrieve all sprint issues with their statuses. Query backlog issue count. Query epic progress (completed stories per epic). Map Jira sprint states and issue statuses to canonical vocabulary per the status mapping below. Use this data for health analysis — no writes. Status mapping: Backlog/Open → backlog, To Do/Selected for Development → ready-for-dev, In Progress → in-progress, In Review/Code Review → review, Done/Resolved → done, On Hold/Blocked → on-hold, Won't Do/Cancelled → cancelled.
|
|
52
|
+
Use whatever Jira-capable tool is available in your current tool context.
|
|
53
|
+
Map Jira entities to the canonical schema (Sprint → sprints[], Backlog → backlog[],
|
|
54
|
+
Epic → epics[], Jira status → canonical vocabulary per Section 6.3 of the routing spec).
|
|
55
|
+
b. If the Jira operation SUCCEEDS: continue with the Jira data returned. Jira is the source of truth.
|
|
56
|
+
c. If the Jira operation FAILS for any reason:
|
|
57
|
+
- If no Jira-capable tool is available in your current context:
|
|
58
|
+
Pause and present the user with:
|
|
59
|
+
> "No Jira-capable tool is available. To use Jira tracking, configure a Jira integration
|
|
60
|
+
> in your agent (an MCP server, plugin, or native integration connected to the Jira
|
|
61
|
+
> instance at `{jira_url}`). How would you like to proceed?
|
|
62
|
+
> (a) Retry — attempt the Jira operation again once a Jira tool is configured
|
|
63
|
+
> (b) Switch to file management — update sprint-status.yaml and config to use
|
|
64
|
+
> file-system backend, then complete this operation locally. This change is permanent."
|
|
65
|
+
- If a Jira tool attempted the operation but returned an error:
|
|
66
|
+
Pause and present the user with:
|
|
67
|
+
> "The Jira operation failed: {actual Jira error details}. How would you like to proceed?
|
|
68
|
+
> (a) Retry — attempt the Jira operation again
|
|
69
|
+
> (b) Switch to file management — update sprint-status.yaml and config to use
|
|
70
|
+
> file-system backend, then complete this operation locally. This change is permanent."
|
|
71
|
+
If user chooses (b) in either case: write `tracking_system: file-system` to `sprint-status.yaml`,
|
|
72
|
+
update `sprint_backend: file-system` in `_bmad/bmm/config.yaml`,
|
|
73
|
+
then proceed with **File-System Backend** instructions below.
|
|
74
|
+
|
|
75
|
+
4. **File-System Backend** — execute the steps below.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
40
79
|
## EXECUTION
|
|
41
80
|
|
|
42
81
|
<workflow>
|