ma-agents 3.9.0 → 3.12.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 -0
- package/bin/cli.js +36 -36
- package/lib/agents.js +1 -1
- 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 +1 -1
- package/lib/bmad-extension/skills/add-to-sprint/SKILL.md +1 -1
- package/lib/bmad-extension/skills/bmad-dev-story/workflow.md +1 -1
- package/lib/bmad-extension/skills/bmad-sprint-planning/workflow.md +1 -1
- package/lib/bmad-extension/skills/bmad-sprint-status/workflow.md +1 -1
- package/lib/bmad-extension/skills/cleanup-done/SKILL.md +1 -1
- package/lib/bmad-extension/skills/close-sprint/SKILL.md +1 -1
- package/lib/bmad-extension/skills/generate-backlog/SKILL.md +1 -1
- package/lib/bmad-extension/skills/modify-sprint/SKILL.md +1 -1
- package/lib/bmad-extension/skills/module.yaml +1 -1
- package/lib/bmad-extension/skills/prioritize-backlog/SKILL.md +1 -1
- package/lib/bmad-extension/skills/remove-from-sprint/SKILL.md +1 -1
- package/lib/bmad-extension/skills/sprint-status-view/SKILL.md +1 -1
- 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 +1 -1
- package/lib/bmad-extension-plugin/skills/add-to-sprint/SKILL.md +1 -1
- package/lib/bmad-extension-plugin/skills/bmad-dev-story/workflow.md +1 -1
- package/lib/bmad-extension-plugin/skills/bmad-sprint-planning/workflow.md +1 -1
- package/lib/bmad-extension-plugin/skills/bmad-sprint-status/workflow.md +1 -1
- package/lib/bmad-extension-plugin/skills/cleanup-done/SKILL.md +1 -1
- package/lib/bmad-extension-plugin/skills/close-sprint/SKILL.md +1 -1
- package/lib/bmad-extension-plugin/skills/generate-backlog/SKILL.md +1 -1
- package/lib/bmad-extension-plugin/skills/modify-sprint/SKILL.md +1 -1
- package/lib/bmad-extension-plugin/skills/module.yaml +1 -1
- package/lib/bmad-extension-plugin/skills/prioritize-backlog/SKILL.md +1 -1
- package/lib/bmad-extension-plugin/skills/remove-from-sprint/SKILL.md +1 -1
- package/lib/bmad-extension-plugin/skills/sprint-status-view/SKILL.md +1 -1
- package/lib/bmad.js +85 -1
- package/lib/installer.js +2 -0
- package/package.json +4 -4
- 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
|
@@ -216,17 +216,28 @@ See `CONTRIBUTING.md` for guidelines.
|
|
|
216
216
|
|
|
217
217
|
## Publishing TEA to NPM
|
|
218
218
|
|
|
219
|
-
TEA uses an automated
|
|
219
|
+
TEA uses an automated publish workflow modeled after the main `BMAD-METHOD` repo. It supports:
|
|
220
|
+
|
|
221
|
+
- `next` prereleases published automatically from `main`
|
|
222
|
+
- manual stable releases on the `latest` dist-tag
|
|
223
|
+
- trusted npm publishing (no `NPM_TOKEN` secret)
|
|
224
|
+
- metadata sync for `package.json`, `package-lock.json`, and `.claude-plugin/marketplace.json`
|
|
220
225
|
|
|
221
226
|
### Prerequisites (One-Time Setup)
|
|
222
227
|
|
|
223
|
-
1. **
|
|
224
|
-
-
|
|
225
|
-
-
|
|
226
|
-
-
|
|
227
|
-
|
|
228
|
+
1. **npm Trusted Publishing:**
|
|
229
|
+
- In npm package settings for `bmad-method-test-architecture-enterprise`, configure Trusted Publishers for this GitHub repository
|
|
230
|
+
- Allow publishes from the `bmad-code-org/bmad-method-test-architecture-enterprise` repo and the `.github/workflows/publish.yaml` workflow
|
|
231
|
+
- GitHub Actions must be able to request an OIDC token (`id-token: write`), which the workflow already does
|
|
232
|
+
|
|
233
|
+
2. **GitHub App Secrets for Stable Releases:**
|
|
234
|
+
- Add `RELEASE_APP_ID`
|
|
235
|
+
- Add `RELEASE_APP_PRIVATE_KEY`
|
|
236
|
+
- Install the corresponding GitHub App on this repository with contents write access
|
|
237
|
+
- If `main` is protected, ensure the app is allowed to push the release commit and tag
|
|
238
|
+
- These are used only for manual stable releases so the workflow can push the version bump commit and tag back to `main`
|
|
228
239
|
|
|
229
|
-
|
|
240
|
+
3. **Verify Package Configuration:**
|
|
230
241
|
```bash
|
|
231
242
|
# Check package.json settings
|
|
232
243
|
cat package.json | grep -A 3 "publishConfig"
|
|
@@ -242,71 +253,61 @@ TEA uses an automated release workflow that handles versioning, metadata sync, t
|
|
|
242
253
|
|
|
243
254
|
#### Option 1: Using npm Scripts (Recommended)
|
|
244
255
|
|
|
245
|
-
From your local terminal after merging to
|
|
256
|
+
From your local terminal after merging to `main`:
|
|
246
257
|
|
|
247
258
|
```bash
|
|
248
|
-
#
|
|
249
|
-
npm run release:
|
|
250
|
-
|
|
251
|
-
# Alpha release (early testing)
|
|
252
|
-
npm run release:alpha
|
|
259
|
+
# Publish the next prerelease from current main
|
|
260
|
+
npm run release:next
|
|
253
261
|
|
|
254
|
-
#
|
|
262
|
+
# Publish a stable patch release
|
|
255
263
|
npm run release:patch
|
|
256
264
|
|
|
257
|
-
#
|
|
265
|
+
# Publish a stable minor release
|
|
258
266
|
npm run release:minor
|
|
259
267
|
|
|
260
|
-
#
|
|
268
|
+
# Publish a stable major release
|
|
261
269
|
npm run release:major
|
|
262
270
|
```
|
|
263
271
|
|
|
264
272
|
#### Option 2: Manual Workflow Trigger
|
|
265
273
|
|
|
266
274
|
1. Go to **Actions** tab in GitHub
|
|
267
|
-
2. Click **"
|
|
275
|
+
2. Click **"Publish"** workflow
|
|
268
276
|
3. Click **"Run workflow"**
|
|
269
277
|
4. Choose the branch to release, typically `main`
|
|
270
|
-
5. Select
|
|
271
|
-
|
|
278
|
+
5. Select channel:
|
|
279
|
+
- `next` for a prerelease publish
|
|
280
|
+
- `latest` for a stable release
|
|
281
|
+
6. If using `latest`, choose the bump type (`patch`, `minor`, `major`)
|
|
282
|
+
7. Click **"Run workflow"**
|
|
272
283
|
|
|
273
284
|
### What Happens Automatically
|
|
274
285
|
|
|
275
286
|
The workflow performs these steps:
|
|
276
287
|
|
|
277
288
|
1. ✅ **Validation**: Runs the full `npm test` suite, including schema checks, install tests, knowledge checks, linting, markdown linting, formatting, and release metadata validation
|
|
278
|
-
2. ✅ **Version Bump**:
|
|
279
|
-
- `
|
|
280
|
-
- `
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
- `
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
### Version Bump Strategy
|
|
295
|
-
|
|
296
|
-
**For TEA Module:**
|
|
297
|
-
|
|
298
|
-
- **Beta (`1.12.x-beta.x`)**: Release candidate testing on the next patch line
|
|
299
|
-
- **Alpha (`1.12.x-alpha.x`)**: Early development and experimental validation
|
|
300
|
-
- **Patch (`1.12.x`)**: Bug fixes, no breaking changes
|
|
301
|
-
- **Minor (`1.x.0`)**: New features, backwards compatible
|
|
302
|
-
- **Major (`x.0.0`)**: Breaking changes
|
|
289
|
+
2. ✅ **Version Bump**:
|
|
290
|
+
- `next`: derives the next prerelease version and publishes it with dist-tag `next`
|
|
291
|
+
- `latest`: bumps the stable version (`patch`, `minor`, or `major`)
|
|
292
|
+
3. ✅ **Metadata Sync**: Updates `.claude-plugin/marketplace.json` to match the package version before publishing
|
|
293
|
+
4. ✅ **Publish**: Publishes to npm with provenance enabled
|
|
294
|
+
- `next` → `npm publish --tag next --provenance`
|
|
295
|
+
- `latest` → `npm publish --tag latest --provenance`
|
|
296
|
+
5. ✅ **Stable Release Finalization**: For `latest`, creates a version bump commit, tags it, pushes it to `main`, and creates a GitHub Release
|
|
297
|
+
|
|
298
|
+
### Channel Strategy
|
|
299
|
+
|
|
300
|
+
- **`next`**: prerelease channel for the newest merged changes
|
|
301
|
+
- **`latest`**: stable channel for intentional releases
|
|
302
|
+
- **`patch`**: bug fixes, no breaking changes
|
|
303
|
+
- **`minor`**: new features, backwards compatible
|
|
304
|
+
- **`major`**: breaking changes
|
|
303
305
|
|
|
304
306
|
**Recommended Release Path:**
|
|
305
307
|
|
|
306
|
-
1.
|
|
307
|
-
2.
|
|
308
|
-
3. `
|
|
309
|
-
4. When stable: `1.12.4-beta.1` → `1.12.4`
|
|
308
|
+
1. Merge releasable work to `main`
|
|
309
|
+
2. Let `next` publish for early validation
|
|
310
|
+
3. When ready, cut a stable `latest` release via `patch`, `minor`, or `major`
|
|
310
311
|
|
|
311
312
|
### Verify Publication
|
|
312
313
|
|
|
@@ -314,6 +315,7 @@ The workflow performs these steps:
|
|
|
314
315
|
|
|
315
316
|
```bash
|
|
316
317
|
npm view bmad-method-test-architecture-enterprise
|
|
318
|
+
npm view bmad-method-test-architecture-enterprise dist-tags
|
|
317
319
|
```
|
|
318
320
|
|
|
319
321
|
**Install TEA:**
|
|
@@ -337,24 +339,31 @@ If you need to unpublish a version:
|
|
|
337
339
|
|
|
338
340
|
```bash
|
|
339
341
|
# Unpublish specific version (within 72 hours)
|
|
340
|
-
npm unpublish bmad-method-test-architecture-enterprise@1.
|
|
342
|
+
npm unpublish bmad-method-test-architecture-enterprise@1.13.2-next.0
|
|
341
343
|
|
|
342
344
|
# Deprecate version (preferred for older releases)
|
|
343
|
-
npm deprecate bmad-method-test-architecture-enterprise@1.
|
|
345
|
+
npm deprecate bmad-method-test-architecture-enterprise@1.13.2-next.0 "Use version X.Y.Z instead"
|
|
344
346
|
```
|
|
345
347
|
|
|
346
348
|
### Troubleshooting
|
|
347
349
|
|
|
348
|
-
**
|
|
350
|
+
**Trusted publishing failed:**
|
|
349
351
|
|
|
350
|
-
- Verify
|
|
351
|
-
-
|
|
352
|
+
- Verify npm Trusted Publishing is configured for this repository and workflow
|
|
353
|
+
- Verify the workflow has `id-token: write`
|
|
354
|
+
- Confirm the publish is running from the canonical repository, not a fork
|
|
352
355
|
|
|
353
356
|
**"Package already exists":**
|
|
354
357
|
|
|
355
358
|
- Check if package name is already taken on NPM
|
|
356
359
|
- Update `name` in `package.json` if needed
|
|
357
360
|
|
|
361
|
+
**"Version push failed":**
|
|
362
|
+
|
|
363
|
+
- Verify `RELEASE_APP_ID` and `RELEASE_APP_PRIVATE_KEY` are configured
|
|
364
|
+
- Verify the GitHub App is installed on this repository with contents write access
|
|
365
|
+
- If branch protection is enabled on `main`, verify the app is allowed to push the release commit and tag
|
|
366
|
+
|
|
358
367
|
**"Tests failed":**
|
|
359
368
|
|
|
360
369
|
- Fix failing tests before release
|
|
@@ -362,9 +371,9 @@ npm deprecate bmad-method-test-architecture-enterprise@1.12.4-beta.0 "Use versio
|
|
|
362
371
|
|
|
363
372
|
**"Git push failed (protected branch)":**
|
|
364
373
|
|
|
365
|
-
- This is expected
|
|
366
|
-
-
|
|
367
|
-
-
|
|
374
|
+
- This is not expected once the release GitHub App is configured correctly
|
|
375
|
+
- Verify branch protection allows the app to push the release commit and tag
|
|
376
|
+
- If needed, create the GitHub Release manually after resolving the app permissions
|
|
368
377
|
|
|
369
378
|
### Release Checklist
|
|
370
379
|
|
|
@@ -375,7 +384,8 @@ Before releasing:
|
|
|
375
384
|
- [ ] CHANGELOG.md updated
|
|
376
385
|
- [ ] No uncommitted changes
|
|
377
386
|
- [ ] On `main` branch
|
|
378
|
-
- [ ]
|
|
387
|
+
- [ ] npm Trusted Publishing configured
|
|
388
|
+
- [ ] `RELEASE_APP_ID` and `RELEASE_APP_PRIVATE_KEY` configured
|
|
379
389
|
- [ ] Package name available on NPM
|
|
380
390
|
|
|
381
391
|
After releasing:
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# pack-refs with: peeled fully-peeled sorted
|
|
2
|
-
|
|
2
|
+
b0ee2a5128d0f0b9f32c30a0017722a846518349 refs/remotes/origin/main
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
b0ee2a5128d0f0b9f32c30a0017722a846518349
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
b0ee2a5128d0f0b9f32c30a0017722a846518349
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bmad-method-test-architecture-enterprise",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "bmad-method-test-architecture-enterprise",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.15.1",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@clack/prompts": "^0.11.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "bmad-method-test-architecture-enterprise",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.15.1",
|
|
5
5
|
"description": "Master Test Architect for quality strategy, test automation, and release gates",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"bmad",
|
|
@@ -33,11 +33,10 @@
|
|
|
33
33
|
"lint:fix": "eslint . --fix",
|
|
34
34
|
"lint:md": "markdownlint-cli2 '**/*.md'",
|
|
35
35
|
"prepare": "command -v husky >/dev/null 2>&1 && husky || exit 0",
|
|
36
|
-
"release:
|
|
37
|
-
"release:
|
|
38
|
-
"release:
|
|
39
|
-
"release:
|
|
40
|
-
"release:patch": "gh workflow run manual-release.yaml -f version_bump=patch",
|
|
36
|
+
"release:major": "gh workflow run publish.yaml -f channel=latest -f bump=major",
|
|
37
|
+
"release:minor": "gh workflow run publish.yaml -f channel=latest -f bump=minor",
|
|
38
|
+
"release:next": "gh workflow run publish.yaml -f channel=next",
|
|
39
|
+
"release:patch": "gh workflow run publish.yaml -f channel=latest -f bump=patch",
|
|
41
40
|
"test": "npm run test:schemas && npm run test:install && npm run test:knowledge && npm run test:release-metadata && npm run test:tea-workflow-descriptions && npm run validate:schemas && npm run lint && npm run lint:md && npm run format:check",
|
|
42
41
|
"test:coverage": "c8 npm test",
|
|
43
42
|
"test:install": "node test/test-installation-components.js",
|
|
@@ -167,8 +167,7 @@ describe('User API Contract', () => {
|
|
|
167
167
|
```json
|
|
168
168
|
{
|
|
169
169
|
"scripts": {
|
|
170
|
-
"test:pact:consumer": "
|
|
171
|
-
"test:pact:consumer:run": "vitest run --config vitest.config.pact.ts",
|
|
170
|
+
"test:pact:consumer": "vitest run --config vitest.config.pact.ts",
|
|
172
171
|
"publish:pact": ". ./scripts/env-setup.sh && ./scripts/publish-pact.sh"
|
|
173
172
|
}
|
|
174
173
|
}
|
|
@@ -1056,7 +1055,7 @@ Four rules that together prevent both (a) non-deterministic pact generation fail
|
|
|
1056
1055
|
1. **Consumer Vitest `fileParallelism: false`** in `vitest.config.pact.ts` — prevents parallel workers from racing on the shared pact JSON. See `pact-consumer-framework-setup.md` Example 2.
|
|
1057
1056
|
2. **Consumer Vitest `pool: 'forks'` + `poolOptions.forks.singleFork: true`** in `vitest.config.pact.ts` — same config as the provider side (`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; serialization alone (via `fileParallelism: false`) is insufficient on the default threads pool in Vitest v1. Forks + `singleFork: true` runs every pact file in one subprocess with a coherent FFI handle and eliminated a reproducible Linux-CI flake on two repos (`pactjs-utils`, `seon-mcp-server`). Single-file consumer suites have not been observed to flake; this rule is still recommended as a future-proof. See `pact-consumer-framework-setup.md` Example 2.
|
|
1058
1057
|
3. **One `addInteraction()` per `it()` block** — see `pactjs-utils-consumer-helpers.md` Example 6.
|
|
1059
|
-
4.
|
|
1058
|
+
4. **`publish-pact.sh` jq normalization** sorts interactions before publish — ensures byte-stable payload to PactFlow regardless of generator ordering quirks. See `pact-consumer-framework-setup.md` Example 4.
|
|
1060
1059
|
|
|
1061
1060
|
Provider suites require the same `pool: 'forks'` + `singleFork: true` combination — see `pactjs-utils-provider-verifier.md` Example 7.
|
|
1062
1061
|
|
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
|