bmad-module-skill-forge 1.0.0 → 1.1.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/.claude-plugin/marketplace.json +1 -1
- package/README.md +3 -3
- package/docs/_data/pinned.yaml +5 -2
- package/docs/{RELEASING.md → _internal/RELEASING.md} +87 -61
- package/docs/{STABILITY.md → _internal/STABILITY.md} +2 -2
- package/package.json +1 -6
- package/release-audits/v1.0.0-launch-audit.md +313 -2
- package/src/skf-audit-skill/steps-c/step-01-init.md +60 -0
- package/src/skf-audit-skill/steps-c/step-02-re-index.md +7 -1
- package/src/skf-audit-skill/steps-c/step-03-structural-diff.md +19 -1
- package/src/skf-audit-skill/steps-c/step-04-semantic-diff.md +10 -1
- package/src/skf-audit-skill/steps-c/step-05-severity-classify.md +8 -0
- package/src/skf-audit-skill/steps-c/step-06-report.md +8 -0
- package/src/skf-brief-skill/assets/skill-brief-schema.md +36 -18
- package/src/skf-drop-skill/steps-c/step-02-execute.md +1 -1
- package/src/skf-export-skill/assets/managed-section-format.md +1 -1
- package/src/skf-export-skill/steps-c/step-04-update-context.md +4 -4
- package/src/skf-rename-skill/steps-c/step-02-execute.md +1 -1
- package/src/skf-test-skill/steps-c/step-03-coverage-check.md +1 -1
- package/src/skf-update-skill/steps-c/step-02-detect-changes.md +123 -0
- package/tools/validate-docs-drift.js +42 -2
|
@@ -38,7 +38,7 @@ description: Pre-flight gate audit of every must-have launch-checklist item, wit
|
|
|
38
38
|
| H5 | `CHANGELOG.md` missing hand-curated `## [1.0.0]` entry | FIXED-IN-THIS-STORY | Inserted `## [1.0.0] - TBD` section with `v1-0-0-changelog-draft.md` body between lines 5 and 7, and added `(pre-v0.3.0 tag, never published)` parenthetical to the dangling `Revert "0.2.0"` line, per Story 5.1 AC 5 / AC 13 + Task 6 | [deferred-work.md → 2-2](../_bmad-output/implementation-artifacts/deferred-work.md) |
|
|
39
39
|
| H6 | `docs/STABILITY.md:6` DRAFT banner | FIXED-IN-THIS-STORY | Replaced DRAFT banner with `STABLE — locked at v1.0.0. Amendments follow the "Changes to This Contract" section below.` per Story 5.1 AC 14 + Task 7 | [`docs/STABILITY.md:6`](./STABILITY.md) |
|
|
40
40
|
| H7 | `0.10.1-alpha.0` CHANGELOG `closes [#11]` / `[#12]` pollution | NOT-APPLICABLE | The pollution lived in the immutable `v0.10.1-alpha.0` tarball and in the orphaned commit `2a57dcbd`; current `main`'s `CHANGELOG.md` does NOT contain those refs (`grep -c 'closes \[#1[12]\]' CHANGELOG.md` → `0`). Alpha tarball is historical / immutable; no repo edit | [Epic 3 retro](../_bmad-output/implementation-artifacts/epic-3-retro-2026-04-21.md) |
|
|
41
|
-
| H8 | `docs/RELEASING.md` missing `### Cutting v1.0.0-rc.1` hand-bump procedure | FIXED-IN-THIS-STORY | Authored new H3 section under `## Rollback Playbook` umbrella (last H3, after `### Baseline snapshots`) with the same five-element shape (Trigger / CLI / Outcome / Constraints / Verification) as Scenarios A–G, per Story 5.1 AC 15 + Task 8 | [`docs/RELEASING.md` § Cutting v1.0.0
|
|
41
|
+
| H8 | `docs/RELEASING.md` missing `### Cutting v1.0.0-rc.1` hand-bump procedure | FIXED-IN-THIS-STORY | Authored new H3 section under `## Rollback Playbook` umbrella (last H3, after `### Baseline snapshots`) with the same five-element shape (Trigger / CLI / Outcome / Constraints / Verification) as Scenarios A–G, per Story 5.1 AC 15 + Task 8 (section subsequently renamed to `### Cutting v1.0.0 under --tag latest` by Story 5.3 Commit 2 per AC 14) | [`docs/RELEASING.md` § Cutting v1.0.0 under --tag latest](./RELEASING.md) |
|
|
42
42
|
| H9 | `prevent_self_review: false` on `release` env + admin ruleset bypass | DEFERRED-POST-V1 | Solo-maintainer repo today; both flips happen together at second-maintainer onboarding. Standing flag with no fire date | [Epic 3 retro standing flag + `deferred-work.md` 1-2](../_bmad-output/implementation-artifacts/deferred-work.md) |
|
|
43
43
|
| H10 | `CONTRIBUTING.md` → `docs/` anchor validator coverage | DEFERRED-POST-V1 | Pre-existing tooling gap; not introduced by any Epic 1–4 story; captured as a CI-as-enforced-gate candidate for a dedicated post-v1.0.0 tooling story | [Epic 4 retro + `deferred-work.md`](../_bmad-output/implementation-artifacts/deferred-work.md) |
|
|
44
44
|
|
|
@@ -198,7 +198,7 @@ None — audit passes clean; Story 5.2 unblocked.
|
|
|
198
198
|
|
|
199
199
|
## Sign-off
|
|
200
200
|
|
|
201
|
-
Signed off by Armel (@armelhbobdad) at 2026-04-23 16:40Z (post-publish, after smoke test completion). v1.0.0-rc.3 survived smoke test clean; Story 5.3 unblocked.
|
|
201
|
+
Signed off by Armel (@armelhbobdad) at 2026-04-23 16:40Z (post-publish, after smoke test completion). v1.0.0-rc.3 survived smoke test clean; Story 5.3 unblocked. v1.0.0 launched 2026-04-23 18:56:39Z; Story 5.4 cross-platform verification in scope. v1.0.0 cross-platform install verification VERIFIED at 2026-04-23T20:23:53Z; Epic 5 cleared.
|
|
202
202
|
|
|
203
203
|
## Post-commit footer
|
|
204
204
|
|
|
@@ -415,3 +415,314 @@ $ npm view bmad-module-skill-forge versions --json | jq '. | map(select(startswi
|
|
|
415
415
|
**AC 12 title-convention note (D2 resolution):** AC 12 prescribes issue titles `v1.0.0-rc.N blocker: <one-line>` for failures of AC 6/7/8/9/10/11 (RC-content defects). Issues [#198](https://github.com/armelhbobdad/bmad-module-skill-forge/issues/198) and [#202](https://github.com/armelhbobdad/bmad-module-skill-forge/issues/202) were filed during Story 5.2 with `release.yaml`-prefixed titles instead, because each failure was a pipeline/workflow defect (failing step inside `release.yaml`), not an RC-content defect — none of the ACs 6–11 fired. The title-convention distinction: use `v1.0.0-rc.N blocker:` when the RC itself has a content defect (wrong version on npm, missing attestation, broken install, etc.); use `fix(release):` conventional-commit prefix when the release workflow has a defect. Codify this split at the Epic 5 retrospective.
|
|
416
416
|
|
|
417
417
|
**Lesson for Epic 5 retrospective:** The canonical release path from `main` dispatch had zero prior E2E validation before Story 5.2 attempted it. Stories 3-1 through 3-4 implicitly assumed the path worked; each defect surfaced by Story 5.2 was invisible because the alpha cut (`v0.10.1-alpha.0`) took the non-main-dispatch branch and skipped every affected step. Recommendation: future release-pipeline epics must include a **staging dispatch test** against a sandbox repo (or at minimum a full-workflow dry-run against the default branch) before declaring the pipeline ready. Catching 5+ defects via the first real v1.0.0 cut is demonstrably more expensive than discovering them in pre-launch testing.
|
|
418
|
+
|
|
419
|
+
## Story 5.3 v1.0.0 Final Cut
|
|
420
|
+
|
|
421
|
+
Story 5.3 promoted the passing `v1.0.0-rc.3` RC to `v1.0.0` under `--tag latest` via the canonical `release.yaml` workflow with two-gate maintainer approval. The dispatch succeeded on the first attempt (in contrast to Story 5.2's 7-attempt saga), validating that the pipeline defects surfaced during Story 5.2 (Stories 3-4, 3-5, and PRs #205 / #207) were fully resolved. The cut is the NFR6 immutability activation event: from `2026-04-23T18:56:39Z`, `v1.0.0` is forever-burned on npm under `--tag latest`; rollback from this instant is `npm deprecate` + ship-forward only.
|
|
422
|
+
|
|
423
|
+
### Workflow dispatch run
|
|
424
|
+
|
|
425
|
+
- **Run URL:** <https://github.com/armelhbobdad/bmad-module-skill-forge/actions/runs/24852899833>
|
|
426
|
+
- **Run id:** `24852899833`
|
|
427
|
+
- **Dispatch command:** `gh workflow run release.yaml -f version_bump=major --ref main`
|
|
428
|
+
- **Dispatch timestamp:** `2026-04-23T18:49:46Z` (per GitHub API `run_started_at` on run `24852899833`)
|
|
429
|
+
- **Release env gate approved at:** `2026-04-23T18:52:32Z` (set-up-job start; 2m 46s gate wait from dispatch)
|
|
430
|
+
- **Bot PR approval-or-admin-bypass merge at:** `2026-04-23T18:56:30Z` (admin-bypass-merge — the PR's `Wait for PR approval or admin-bypass merge` step cleared in 0s because the merge had already happened by the time that step evaluated; matches the rc.3 pattern where PR #209 was admin-bypass-merged)
|
|
431
|
+
- **Run completion:** `2026-04-23T18:56:48Z`
|
|
432
|
+
- **Final conclusion:** `success`
|
|
433
|
+
- **Step failures:** none. Of 31 declared job steps, 30 ran successfully and 1 (step 27 `Skip PR flow (non-main dispatch ref)`) was skipped by design: the step's `if: github.ref != 'refs/heads/main'` guard evaluated false (the ref IS main), so the non-main fallback path was correctly bypassed.
|
|
434
|
+
|
|
435
|
+
### Bot PR auto-merge evidence
|
|
436
|
+
|
|
437
|
+
- **Bot PR:** [#213 `release: bump to v1.0.0`](https://github.com/armelhbobdad/bmad-module-skill-forge/pull/213)
|
|
438
|
+
- **Head branch:** `release/bot/v1.0.0-24852899833` (temp branch; auto-deleted post-merge per standard flow)
|
|
439
|
+
- **Head commit:** `62d56418836c90153401eae2d49500dbfa1c70d8` (the `release: bump to v1.0.0` commit)
|
|
440
|
+
- **Merge commit:** `393a5a2012e8914faa3f67e1af94bc3ca0c90062`
|
|
441
|
+
- **Merged at:** `2026-04-23T18:56:30Z`
|
|
442
|
+
- **Merge path:** admin-bypass-merge (maintainer clicked merge on the PR without formal review approval; both `reviewDecision == APPROVED` and `state == MERGED` are accepted by `release.yaml:481-569`). This matches the Story 5.2 rc.3 pattern and is the expected path per Story 3.4.
|
|
443
|
+
|
|
444
|
+
### npm publish evidence
|
|
445
|
+
|
|
446
|
+
**Pre-cut dist-tags snapshot (from Task 1 recon, `2026-04-23 ~18:48Z`):**
|
|
447
|
+
|
|
448
|
+
```json
|
|
449
|
+
{
|
|
450
|
+
"latest": "0.10.0",
|
|
451
|
+
"alpha": "0.10.1-alpha.0",
|
|
452
|
+
"rc": "1.0.0-rc.3"
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
**Post-cut dist-tags snapshot (from Task 3 verification, `2026-04-23 ~18:57Z`):**
|
|
457
|
+
|
|
458
|
+
```json
|
|
459
|
+
{
|
|
460
|
+
"latest": "1.0.0",
|
|
461
|
+
"alpha": "0.10.1-alpha.0",
|
|
462
|
+
"rc": "1.0.0-rc.3"
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
**Dist-tag deltas:** `latest` flipped `0.10.0` → `1.0.0` (the whole point of Story 5.3); `rc` UNCHANGED at `1.0.0-rc.3` (Story 5.3's `major`-from-rc cut does NOT bump the rc tag); `alpha` UNCHANGED at `0.10.1-alpha.0`.
|
|
467
|
+
|
|
468
|
+
**`npm view bmad-module-skill-forge@1.0.0 --json | jq '.dist'` (verbatim):**
|
|
469
|
+
|
|
470
|
+
```json
|
|
471
|
+
{
|
|
472
|
+
"integrity": "sha512-6tQOBCuf05SMRs/1MNWm6+f7OYOGh6tz62AbTvMG3bjspqMQa6Ln9y5paQtQRh4eWyuPvTlPaKqV6Vug8IIOeA==",
|
|
473
|
+
"shasum": "a582acf226016bb075dc5235a721da9d16104b35",
|
|
474
|
+
"tarball": "https://registry.npmjs.org/bmad-module-skill-forge/-/bmad-module-skill-forge-1.0.0.tgz",
|
|
475
|
+
"fileCount": 227,
|
|
476
|
+
"unpackedSize": 1697974,
|
|
477
|
+
"attestations": {
|
|
478
|
+
"url": "https://registry.npmjs.org/-/npm/v1/attestations/bmad-module-skill-forge@1.0.0",
|
|
479
|
+
"provenance": {
|
|
480
|
+
"predicateType": "https://slsa.dev/provenance/v1"
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
"signatures": [
|
|
484
|
+
{
|
|
485
|
+
"keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U",
|
|
486
|
+
"sig": "MEUCIHcz/PIyH7DaVNN872V0uwQXmO29h6WmeXgGRxP0RFR7AiEA2zX6/x2aXiDN4V7irzXiWKNYG+uqFiQwBRGdt0DGFvg="
|
|
487
|
+
}
|
|
488
|
+
]
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
**Provenance attestation URL:** <https://registry.npmjs.org/-/npm/v1/attestations/bmad-module-skill-forge@1.0.0>
|
|
493
|
+
|
|
494
|
+
**Versions list (after publish):**
|
|
495
|
+
|
|
496
|
+
```
|
|
497
|
+
$ npm view bmad-module-skill-forge versions --json | jq '. | map(select(startswith("1.0.0")))'
|
|
498
|
+
[
|
|
499
|
+
"1.0.0-rc.3",
|
|
500
|
+
"1.0.0"
|
|
501
|
+
]
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
**AC 6 NFR4 provenance-coverage status:** PASS — SLSA L2 attestation present for `1.0.0` (`predicateType: https://slsa.dev/provenance/v1`; the SLSA Build L2 level follows from npm's trusted-publishing design, which signs provenance statements via GitHub Actions OIDC with tamper-evident build metadata — see <https://docs.npmjs.com/generating-provenance-statements>).
|
|
505
|
+
|
|
506
|
+
### GitHub Release v1.0.0
|
|
507
|
+
|
|
508
|
+
**`gh release view v1.0.0 --json tagName,isPrerelease,name,createdAt,url`:**
|
|
509
|
+
|
|
510
|
+
```json
|
|
511
|
+
{
|
|
512
|
+
"createdAt": "2026-04-23T18:56:33Z",
|
|
513
|
+
"isPrerelease": false,
|
|
514
|
+
"name": "Skill Forge (SKF) v1.0.0",
|
|
515
|
+
"tagName": "v1.0.0",
|
|
516
|
+
"url": "https://github.com/armelhbobdad/bmad-module-skill-forge/releases/tag/v1.0.0"
|
|
517
|
+
}
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
- `isPrerelease: false` ✓ — load-bearing for NFR6 threshold; `release.yaml:697-704` computes `prerelease` as `contains(version, 'alpha|beta|rc')` and `1.0.0` contains none of those substrings.
|
|
521
|
+
- Release URL: <https://github.com/armelhbobdad/bmad-module-skill-forge/releases/tag/v1.0.0>
|
|
522
|
+
- Release body: auto-generated by `release.yaml § Generate release notes` from the conventional-commits between `v1.0.0-rc.3` and `v1.0.0` (expected empty — the commit range contains only `docs(release):` and `chore(release):` entries, neither of which emits `### Features` or `### Bug Fixes` under conventional-changelog; the reconciled CHANGELOG carries the hand-curated v1.0.0 prose separately). **Post-sign-off amplification (Story 5.3 code-review patch 2a, 2026-04-23):** the Release body was subsequently replaced via `gh release edit v1.0.0 --notes-file …` with the verbatim hand-curated CHANGELOG § [1.0.0] prose (First Major Release / Initial Release / Highlights / Workflows / Confidence Tiers / IDE Support / Links) plus a 6-line footer linking to the CHANGELOG entry and the `v1.0.0-rc.3...v1.0.0` compare view. Post-amplification body length: 3844 bytes (up from 473). This edit does not alter npm, the tag, or provenance; it only changes the public Release-page prose for discoverability.
|
|
523
|
+
|
|
524
|
+
### Main-branch side-effects
|
|
525
|
+
|
|
526
|
+
**`main` branch advance (AC 8a):**
|
|
527
|
+
|
|
528
|
+
```
|
|
529
|
+
$ git log main -2 --format='%H %an %s'
|
|
530
|
+
393a5a2012e8914faa3f67e1af94bc3ca0c90062 github-actions[bot] Merge pull request #213 from armelhbobdad/release/bot/v1.0.0-24852899833
|
|
531
|
+
62d56418836c90153401eae2d49500dbfa1c70d8 github-actions[bot] release: bump to v1.0.0
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
- Merge commit: `393a5a2` (parents: `3e60788` pre-Story-5.3 main tip + `62d56418` bot release commit)
|
|
535
|
+
- Release commit: `62d56418` (parent: `3e60788`)
|
|
536
|
+
- Topology matches rc.3 precedent: PR merge commit on top, workflow-authored release commit underneath.
|
|
537
|
+
|
|
538
|
+
**Version-file bumps (AC 8b, 8c):**
|
|
539
|
+
|
|
540
|
+
```
|
|
541
|
+
$ jq -r .version package.json
|
|
542
|
+
1.0.0
|
|
543
|
+
|
|
544
|
+
$ jq -r '.plugins[0].version' .claude-plugin/marketplace.json
|
|
545
|
+
1.0.0
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
AC 8c: 2nd live end-to-end proof of the Story 5.1 H3 jq-based marketplace-sync step (1st was rc.3).
|
|
549
|
+
|
|
550
|
+
**CHANGELOG post-workflow topology (AC 8d, 8e, 8f):**
|
|
551
|
+
|
|
552
|
+
```
|
|
553
|
+
$ grep -cE '^## \[1\.0\.0\]' CHANGELOG.md # 2 (auto-gen + stale TBD; reconciled in Commit 2)
|
|
554
|
+
$ grep -c '^## \[1.0.0-rc.3\]' CHANGELOG.md # 1 (rc.3 block survived)
|
|
555
|
+
$ head -5 CHANGELOG.md # # Changelog + preamble + ## [Unreleased]
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
**Zero-conventional-commit edge case:** the auto-generated `## [1.0.0]` block had an EMPTY body (no `### Features` / `### Bug Fixes` sub-sections) because the commit range `v1.0.0-rc.3..v1.0.0` contained only `docs(release):` and `chore(release):` entries. This is the expected behavior per deferred-work 3-3; AC 10 reconciliation preserves the auto-gen header (compare URL + date) and injects the hand-curated prose. The `awk`-based preamble-restore from Story 3.3 worked correctly despite the empty block.
|
|
559
|
+
|
|
560
|
+
**Tag anchor verification (AC 9):**
|
|
561
|
+
|
|
562
|
+
```
|
|
563
|
+
$ git tag -l 'v1.0.0'
|
|
564
|
+
v1.0.0
|
|
565
|
+
|
|
566
|
+
$ git rev-parse 'v1.0.0^{}' # dereference annotated tag to commit
|
|
567
|
+
393a5a2012e8914faa3f67e1af94bc3ca0c90062
|
|
568
|
+
|
|
569
|
+
$ git log main -1 --format='%H'
|
|
570
|
+
393a5a2012e8914faa3f67e1af94bc3ca0c90062
|
|
571
|
+
|
|
572
|
+
=> MATCH ✓ (tag anchors on PR merge commit per Story 3.4 P9 defensive guard)
|
|
573
|
+
|
|
574
|
+
$ git log v1.0.0 -1 --format='%s'
|
|
575
|
+
Merge pull request #213 from armelhbobdad/release/bot/v1.0.0-24852899833
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
**Note:** `v1.0.0` is an **annotated tag object** (tag SHA `4579b954ee6512a1c39ef4e3f06ecdb60e67358f`), not a lightweight tag. `git rev-parse v1.0.0` returns the tag object SHA, not the commit SHA — use `^{}` to dereference. This is consistent with the rc.3 tag shape from Story 5.2.
|
|
579
|
+
|
|
580
|
+
### CHANGELOG reconciliation
|
|
581
|
+
|
|
582
|
+
**Pre-reconciliation state (post-workflow):** two `## [1.0.0]` H2 blocks — (A) auto-generated at line 7 with compare URL `compare/v1.0.0-rc.3...v1.0.0` and empty body, (B) hand-curated `## [1.0.0] - TBD` placeholder at line 397 (originally staged by Story 5.1).
|
|
583
|
+
|
|
584
|
+
**Post-reconciliation state:** single `## [1.0.0]` block at line 7 with preserved auto-gen header (compare URL + date `2026-04-23`) and hand-curated body (First Major Release → Initial Release → Highlights → Workflows → Confidence Tiers → IDE Support → Links); stale TBD placeholder deleted.
|
|
585
|
+
|
|
586
|
+
**Post-edit verification (AC 10 iii):**
|
|
587
|
+
|
|
588
|
+
```
|
|
589
|
+
$ grep -cE '^## \[1\.0\.0\]' CHANGELOG.md # 1 (exactly one reconciled block)
|
|
590
|
+
$ grep -c '^## \[1\.0\.0\] - TBD' CHANGELOG.md # 0 (stale placeholder gone)
|
|
591
|
+
$ grep -cE '^## \[1\.0\.0\]\(https' CHANGELOG.md # 1 (compare-URL header preserved)
|
|
592
|
+
$ grep -c '^## \[1.0.0-rc.3\]' CHANGELOG.md # 1 (rc.3 block untouched)
|
|
593
|
+
$ grep -c '^## \[0.10.0\]' CHANGELOG.md # 1 (older history intact)
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
**Diff excerpt (block A insertion, head):**
|
|
597
|
+
|
|
598
|
+
```diff
|
|
599
|
+
## [1.0.0](https://github.com/armelhbobdad/bmad-module-skill-forge/compare/v1.0.0-rc.3...v1.0.0) (2026-04-23)
|
|
600
|
+
+
|
|
601
|
+
+### First Major Release
|
|
602
|
+
+
|
|
603
|
+
+First major release of Skill Forge (SKF). Introduces the `INCONCLUSIVE` test verdict, atomic stack-skill writes, a shared feasibility schema across VS/RA/SS, and formalizes Linux/macOS-only support. Sets the stable contract for subsequent 1.x releases.
|
|
604
|
+
+
|
|
605
|
+
+### Initial Release
|
|
606
|
+
+
|
|
607
|
+
+Skill Forge (SKF) — an agent skill compiler that transforms code repositories, documentation, and developer discourse into [agentskills.io](https://agentskills.io)-compliant agent skills with AST-backed provenance.
|
|
608
|
+
+[... hand-curated body continues with Highlights / Workflows / Confidence Tiers / IDE Support / Links ...]
|
|
609
|
+
## [1.0.0-rc.3](https://github.com/armelhbobdad/bmad-module-skill-forge/compare/v0.10.0...v1.0.0-rc.3) (2026-04-23)
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
**Diff excerpt (block B deletion, tail — the bracketed placeholder line inside the code fence below is narrative, not a literal diff line; run `git diff c0b2b67^..c0b2b67 -- CHANGELOG.md` for the verbatim body):**
|
|
613
|
+
|
|
614
|
+
```diff
|
|
615
|
+
-## [1.0.0] - TBD
|
|
616
|
+
-
|
|
617
|
+
-<!--
|
|
618
|
+
-Hand-curated v1.0.0 release notes. Source: _bmad-output/planning-artifacts/v1-0-0-changelog-draft.md.
|
|
619
|
+
-Date placeholder "TBD" — replaced with actual publish date at Story 5.3's v1.0.0 final cut (see
|
|
620
|
+
-docs/RELEASING.md § Cutting v1.0.0-rc.1 for the reconciliation procedure).
|
|
621
|
+
--->
|
|
622
|
+
-
|
|
623
|
+
-### First Major Release
|
|
624
|
+
-[... full hand-curated body deleted from here (moved up into reconciled block A) ...]
|
|
625
|
+
-- npm: <https://www.npmjs.com/package/bmad-module-skill-forge>
|
|
626
|
+
-
|
|
627
|
+
## [0.10.0](https://github.com/armelhbobdad/bmad-module-skill-forge/compare/v0.9.0...v0.10.0) (2026-04-06)
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
**Net CHANGELOG delta:** 710 lines → 703 lines (−7 lines from removing the TBD placeholder's HTML comment + header markers; the body itself was relocated, not deleted).
|
|
631
|
+
|
|
632
|
+
### NFR1 cycle-time record
|
|
633
|
+
|
|
634
|
+
- **Dispatch → success wall-clock:** **7m 2s** (run `24852899833`: `2026-04-23T18:49:46Z` → `2026-04-23T18:56:48Z`)
|
|
635
|
+
- **Env-gate approval sub-budget:** 2m 46s (`2026-04-23T18:49:46Z` dispatch → `2026-04-23T18:52:32Z` set-up-job start)
|
|
636
|
+
- **Workflow automation sub-budget:** 4m 16s (`2026-04-23T18:52:32Z` → `2026-04-23T18:56:48Z`)
|
|
637
|
+
- **NFR1 target:** 20 min (15 CI + 5 approval)
|
|
638
|
+
- **Status:** within envelope; 13 min of headroom against the 20-min target.
|
|
639
|
+
- **Rolling-10-release window:** 2 / 10 data points collected — `[Story 5.2 rc.3: 5m 4s, Story 5.3 v1.0.0: 7m 2s]`. Both well under NFR1's 20-min target. Stories 5.4 onward continue filling the window.
|
|
640
|
+
- **Story 5.2 retrospective comparison:** Story 5.3 dispatched successfully on the first attempt (7m 2s wall-clock). Story 5.2 took 7 attempts and ~6 hours of cumulative dev-cycle time to discover and fix 5 pipeline defects (Stories 3-4, 3-5, PRs #205 / #207). Story 5.3's first-attempt success is evidence that those fixes landed correctly; the pipeline is now E2E-proven for main-dispatched cuts.
|
|
641
|
+
|
|
642
|
+
### NFR6 v1.0.0 immutability activation
|
|
643
|
+
|
|
644
|
+
**v1.0.0 is live on npm under --tag latest as of 2026-04-23T18:56:39Z. NFR6 immutability policy is now in force: this version SHALL NEVER be unpublished or republished; rollback uses npm deprecate + ship forward per docs/RELEASING.md § Scenario A/B.**
|
|
645
|
+
|
|
646
|
+
This timestamp is the `Publish to npm via OIDC trusted publishing` step's completion time (step 29 of run `24852899833`; `2026-04-23T18:56:34Z` → `2026-04-23T18:56:39Z` in the GitHub Actions step timeline). From this instant, the version-number `1.0.0` on npm is an irreversible forensic fact: any future defect surfaced against `1.0.0` is resolved via `npm deprecate bmad-module-skill-forge@1.0.0 "<reason>"` and shipping `1.0.1` forward with the fix, NEVER via `npm unpublish` (regardless of eligibility-window rules — NFR6 forbids reclaim). This record is the auditable boundary between "pre-NFR6 state" and "NFR6-active state."
|
|
647
|
+
|
|
648
|
+
### Decision: v1.0.0 launch status
|
|
649
|
+
|
|
650
|
+
**LAUNCHED — v1.0.0 is live on npm under --tag latest with SLSA L2 provenance. Story 5.4 cross-platform verification cleared to begin (NFR9: within 1h of publish).**
|
|
651
|
+
|
|
652
|
+
The `## Sign-off` section (above) is updated with the dual-sentence form:
|
|
653
|
+
|
|
654
|
+
> Signed off by Armel (@armelhbobdad) at 2026-04-23 16:40Z (post-publish, after smoke test completion). v1.0.0-rc.3 survived smoke test clean; Story 5.3 unblocked. v1.0.0 launched 2026-04-23 18:56:39Z; Story 5.4 cross-platform verification in scope.
|
|
655
|
+
|
|
656
|
+
Story 5.4 opens with `v1.0.0 is live on npm` as its precondition; NFR9 requires cross-platform install verification (Linux + Windows via the `quality.yaml` matrix + macOS manual spot-check) within 60 minutes of the `2026-04-23T18:56:39Z` publish timestamp. Story 5.4 dispatches are in scope starting immediately after Story 5.3's Commit 2 (this audit append) lands on `main`.
|
|
657
|
+
|
|
658
|
+
## Story 5.4 Post-Publish Verification
|
|
659
|
+
|
|
660
|
+
### Workflow dispatch run
|
|
661
|
+
|
|
662
|
+
- **Workflow:** `.github/workflows/install-smoke.yaml` (authored in Story 5.4 Commit 1, PR [#219](https://github.com/armelhbobdad/bmad-module-skill-forge/pull/219), merged at `2026-04-23T20:22:07Z`, merge commit [`075dbcb`](https://github.com/armelhbobdad/bmad-module-skill-forge/commit/075dbcb2fd8100036822aa172712db07867b5e73))
|
|
663
|
+
- **Dispatch command:** `gh workflow run install-smoke.yaml -f version=latest --ref main`
|
|
664
|
+
- **Run ID:** `24856988815`
|
|
665
|
+
- **Run URL:** <https://github.com/armelhbobdad/bmad-module-skill-forge/actions/runs/24856988815>
|
|
666
|
+
- **Dispatch timestamp:** `2026-04-23T20:23:07Z`
|
|
667
|
+
- **Completion timestamp:** `2026-04-23T20:23:53Z`
|
|
668
|
+
- **Final conclusion:** `success` (all three matrix legs `success`)
|
|
669
|
+
- **Total wall-clock:** 46 seconds
|
|
670
|
+
|
|
671
|
+
### Matrix results
|
|
672
|
+
|
|
673
|
+
| Runner | Job status | `--version` stdout | Exit code | Wall-clock | Runner image version |
|
|
674
|
+
|--------|-----------|---------------------|-----------|------------|----------------------|
|
|
675
|
+
| `ubuntu-latest` | `success` | `stdout: 1.0.0` | 0 | ~5s (start `20:23:13Z` → end `20:23:18Z`) | `Runner Image 20260213.493`, `Runner Image Provisioner 20260413.86.1` |
|
|
676
|
+
| `windows-latest` | `success` | `stdout: 1.0.0` | 0 | ~40s (start `20:23:12Z` → end `20:23:52Z`) | `Runner Image 20260213.493`, `Runner Image Provisioner 20260413.84.1` |
|
|
677
|
+
| `macos-latest` | `success` | `stdout: 1.0.0` | 0 | ~8s (start `20:23:13Z` → end `20:23:21Z`) | `Runner Image 20260422.526`, `Runner Image Provisioner 20260421.0007.1` |
|
|
678
|
+
|
|
679
|
+
All three legs printed `1.0.0` verbatim (matching `package.json.version` for v1.0.0), exited 0, and completed well inside the 60-second-typical target from Story 5.4 AC 4. Windows was the slowest at 40s (expected — npx warm-up + longer shebang resolution on Windows); ubuntu-latest fastest at 5s.
|
|
680
|
+
|
|
681
|
+
### NFR9 elapsed-time record
|
|
682
|
+
|
|
683
|
+
- **Publish timestamp (Story 5.3 activating NFR6):** `2026-04-23T18:56:39Z`
|
|
684
|
+
- **NFR9 60-minute target deadline:** `2026-04-23T19:56:39Z`
|
|
685
|
+
- **Smoke-workflow dispatch timestamp:** `2026-04-23T20:23:07Z`
|
|
686
|
+
- **Smoke-workflow completion timestamp:** `2026-04-23T20:23:53Z`
|
|
687
|
+
- **Wall-clock delta from publish to completion:** `01:27` (1 hour 27 minutes 14 seconds)
|
|
688
|
+
- **NFR9 status classification:** `missed-target-non-blocking`
|
|
689
|
+
|
|
690
|
+
**Disposition rationale.** The 60-minute NFR9 target closed at `2026-04-23T19:56:39Z`; verification completed 27 minutes past the target. All three matrix legs passed with no surfaced regressions, so no live cross-platform defect existed during the unobserved window — the policy's safety goal (catching a platform regression fast while blast radius is small) was achieved in practice, just later than the 1-hour target. Per Story 5.4 AC 2, this disposition is non-blocking for Epic 5 closure. The first NFR9 data point goes into the Epic 5 retrospective, which will weigh whether the 1-hour target needs (i) softening to a 24-hour bucket for solo-maintainer operability, (ii) automation via tag-push auto-trigger to push verification toward near-real-time, or (iii) maintainer on-call commitments for future launches.
|
|
691
|
+
|
|
692
|
+
### Marketplace.json post-publish invariant
|
|
693
|
+
|
|
694
|
+
Re-verified post-smoke (Story 5.4 Task 4) — all four invariants hold, zero drift from Story 5.3 final state:
|
|
695
|
+
|
|
696
|
+
```
|
|
697
|
+
$ gh api repos/armelhbobdad/bmad-module-skill-forge/contents/package.json \
|
|
698
|
+
--jq '.content' | base64 -d | jq -r .version
|
|
699
|
+
1.0.0
|
|
700
|
+
|
|
701
|
+
$ gh api repos/armelhbobdad/bmad-module-skill-forge/contents/.claude-plugin/marketplace.json \
|
|
702
|
+
--jq '.content' | base64 -d | jq -r '.plugins[0].version'
|
|
703
|
+
1.0.0
|
|
704
|
+
|
|
705
|
+
$ npm view bmad-module-skill-forge@latest version
|
|
706
|
+
1.0.0
|
|
707
|
+
|
|
708
|
+
$ npm view bmad-module-skill-forge dist-tags --json
|
|
709
|
+
{
|
|
710
|
+
"latest": "1.0.0",
|
|
711
|
+
"alpha": "0.10.1-alpha.0",
|
|
712
|
+
"rc": "1.0.0-rc.3"
|
|
713
|
+
}
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
### Any observations or defects surfaced
|
|
717
|
+
|
|
718
|
+
None — all three matrix legs clean. No stderr noise, no deprecation warnings, no platform-specific anomalies. The published v1.0.0 tarball resolves and executes cleanly on `ubuntu-latest`, `windows-latest`, and `macos-latest` under Node 22, through the `tools/skf-npx-wrapper.js` bin entrypoint and commander dispatch.
|
|
719
|
+
|
|
720
|
+
### Decision: v1.0.0 cross-platform verification status
|
|
721
|
+
|
|
722
|
+
**VERIFIED — v1.0.0 install clean on ubuntu-latest + windows-latest + macos-latest via npm dist-tag @latest. NFR9 missed-target-non-blocking. Epic 5 cleared for close; Epic 6 cleanup unblocked.**
|
|
723
|
+
|
|
724
|
+
The `## Sign-off` block at the top of this audit is updated to the four-sentence form per Story 5.4 AC 8:
|
|
725
|
+
|
|
726
|
+
> Signed off by Armel (@armelhbobdad) at 2026-04-23 16:40Z (post-publish, after smoke test completion). v1.0.0-rc.3 survived smoke test clean; Story 5.3 unblocked. v1.0.0 launched 2026-04-23 18:56:39Z; Story 5.4 cross-platform verification in scope. v1.0.0 cross-platform install verification VERIFIED at 2026-04-23T20:23:53Z; Epic 5 cleared.
|
|
727
|
+
|
|
728
|
+
Story 5.4 closes with Epic 5 at `done`. Epic 6 cleanup stories (6-1 delete legacy `publish.yaml` + `manual-release.yaml`; 6-2 remove `release:*` scripts from `package.json`; 6-3 remove `NPM_TOKEN` secret) are now unblocked. The `install-smoke.yaml` workflow remains as a permanent reusable artifact — every future release (v1.0.1, v1.1.0, v2.0.0, ...) can redispatch it with the new version tag to produce the same cross-platform evidence.
|
|
@@ -104,12 +104,72 @@ If `{legacy_stack_provenance}` is true: log a note that this stack uses v1 prove
|
|
|
104
104
|
**If provenance map loaded:**
|
|
105
105
|
- Use `source_root` from provenance map as source code path
|
|
106
106
|
- Verify source path still exists and is accessible
|
|
107
|
+
- Extract `baseline_commit` = `provenance-map.source_commit` (fall back to `metadata.source_commit` if absent from the provenance map)
|
|
108
|
+
- Extract `baseline_ref` = `metadata.source_ref` (may be a tag, branch, `HEAD`, or `"local"`)
|
|
107
109
|
|
|
108
110
|
**If degraded mode:**
|
|
109
111
|
- Ask user: "Please provide the path to the current source code."
|
|
112
|
+
- `baseline_commit` and `baseline_ref` are unavailable — §5b will short-circuit
|
|
110
113
|
|
|
111
114
|
**Validate:** Confirm source directory exists and contains expected files.
|
|
112
115
|
|
|
116
|
+
### 5b. Detect Upstream Drift
|
|
117
|
+
|
|
118
|
+
Upstream drift detection is the primary use case of this workflow. If the local clone is still pinned to the baseline commit while upstream has shipped newer tags, auditing against the unchanged tree will misleadingly report CLEAN even after a major release.
|
|
119
|
+
|
|
120
|
+
**Skip this section** if any of the following hold:
|
|
121
|
+
- `baseline_ref` is `"local"`, `null`, or unset (non-git source)
|
|
122
|
+
- `{source_root}` is not a git worktree (`git -C {source_root} rev-parse --git-dir` fails)
|
|
123
|
+
- `baseline_commit` is unavailable
|
|
124
|
+
- Degraded mode is active (no provenance map)
|
|
125
|
+
|
|
126
|
+
When skipping, log the reason, then set the audit-ref context variables to baseline values so step-06 renders a coherent Provenance row: `audit_ref = baseline_ref or "(unknown)"`, `audit_ref_source = "baseline"` (or `"unavailable"` if both `baseline_ref` and `baseline_commit` are unset), `audit_commit = baseline_commit or "(unknown)"`, `latest_tag = null`, `remote_head = null`. Continue to §6.
|
|
127
|
+
|
|
128
|
+
**Otherwise:**
|
|
129
|
+
|
|
130
|
+
1. **Fetch upstream refs** (read-only, no working-tree mutation):
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
git -C {source_root} fetch --tags --quiet origin
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
If fetch fails (no network, no remote, detached clone), log the reason, record `upstream_fetch: "failed:{reason}"` in context, set `audit_ref = baseline_ref`, `audit_ref_source = "baseline"`, `audit_commit = baseline_commit`, `latest_tag = null`, `remote_head = null`, and continue to §6 without gating.
|
|
137
|
+
|
|
138
|
+
2. **Find latest remote ref:**
|
|
139
|
+
- Remote default-branch HEAD: `git -C {source_root} rev-parse origin/HEAD` (fall back to `origin/main` or `origin/master` if the symbolic ref is unavailable) — record as `remote_head`.
|
|
140
|
+
- Newest semver tag: `git -C {source_root} for-each-ref --sort=-v:refname --format='%(refname:short)' 'refs/tags/v*' | head -1` — record as `latest_tag`.
|
|
141
|
+
|
|
142
|
+
3. **Compare to baseline:**
|
|
143
|
+
- If `baseline_commit` equals the commit that `remote_head` resolves to AND (`latest_tag` is empty OR semver-equals `baseline_ref` OR is older than `baseline_ref`), upstream has not moved. Set `audit_ref = baseline_ref`, `audit_ref_source = "baseline"`, `audit_commit = baseline_commit`. Continue to §6.
|
|
144
|
+
- Otherwise upstream has moved — proceed to the gate.
|
|
145
|
+
|
|
146
|
+
4. **User gate — Upstream drift detected:**
|
|
147
|
+
|
|
148
|
+
"**Upstream has moved since this skill was created.**
|
|
149
|
+
|
|
150
|
+
| | Baseline | Upstream |
|
|
151
|
+
|---|---|---|
|
|
152
|
+
| Ref | `{baseline_ref}` | `{latest_tag}` (newest tag) / `{remote_head}` (default HEAD) |
|
|
153
|
+
| Commit | `{baseline_commit_short}` | `{latest_tag_commit_short}` / `{remote_head_short}` |
|
|
154
|
+
|
|
155
|
+
Auditing against the baseline clone will report little-to-no structural drift even if the upstream API has changed. Options:
|
|
156
|
+
|
|
157
|
+
- **[C] Checkout-and-audit-against-latest** — checkout `{latest_tag}` (or `{remote_head}` if no newer tag) in `{source_root}` and audit against that. Re-extraction will reflect the current upstream surface.
|
|
158
|
+
- **[S] Stay-on-baseline** — keep `{source_root}` at `{baseline_ref}` and audit structural drift against the unchanged tree. The report will note `audit_ref = baseline`.
|
|
159
|
+
- **[X] Abort** — halt the workflow without producing a report.
|
|
160
|
+
|
|
161
|
+
**Select:** [C] / [S] / [X]"
|
|
162
|
+
|
|
163
|
+
**Gate handling:**
|
|
164
|
+
- **[C]:** Acquire an exclusive lock on `{source_root}/.skf-workspace.lock` (`flock -x` or `fcntl.flock(LOCK_EX)`) before mutating the working tree — matches the concurrency discipline in `src/skf-create-skill/references/source-resolution-protocols.md` and avoids racing with a concurrent create-skill / test-skill run against the same workspace clone. If `flock` is unavailable, emit a warning and proceed. Then `git -C {source_root} checkout {chosen_ref}` (prefer `latest_tag` when present, else `remote_head`). Set `audit_ref = {chosen_ref}`, `audit_ref_source = "checkout-latest"`, `audit_commit = git rev-parse HEAD`. Hold the lock through step-02 re-extraction and release only after the extraction snapshot is complete.
|
|
165
|
+
- **[S]:** Keep baseline. Set `audit_ref = baseline_ref`, `audit_ref_source = "baseline"`, `audit_commit = baseline_commit`.
|
|
166
|
+
- **[X]:** HALT workflow — do not create drift report.
|
|
167
|
+
- **Other input:** help user, redisplay gate.
|
|
168
|
+
|
|
169
|
+
**Headless default** (when `{headless_mode}`): auto-select **[S]** and emit a loud log line: `"headless: upstream drift detected ({baseline_ref} → {latest_tag or remote_head}); staying on baseline. Re-run interactively to audit against latest."` Do not check out in headless mode — silent ref changes under automation would mutate the user's working tree without consent.
|
|
170
|
+
|
|
171
|
+
5. **Record for report:** store `audit_ref`, `audit_ref_source`, `audit_commit`, `latest_tag`, `remote_head`, and `baseline_commit` in context. Step-06 surfaces them in the Provenance section so readers can tell which comparison actually ran.
|
|
172
|
+
|
|
113
173
|
### 6. Create Drift Report
|
|
114
174
|
|
|
115
175
|
Create `{outputFile}` from `{templateFile}`:
|
|
@@ -116,7 +116,9 @@ Read the `qmd_collections` registry from `{sidecar_path}/forge-tier.yaml`.
|
|
|
116
116
|
|
|
117
117
|
Find the collection entry matching the current skill: look for an entry where `skill_name` matches the current skill being audited AND `type` is `"extraction"`.
|
|
118
118
|
|
|
119
|
-
|
|
119
|
+
Three collection states must be handled distinctly (same branching as step-04 §2 — keep them in sync):
|
|
120
|
+
|
|
121
|
+
**If a matching extraction collection is found and populated** (pre-query probe via `qmd ls {collection_name}` or equivalent returns one or more files):
|
|
120
122
|
Query qmd_bridge against the `{skill_name}-extraction` collection for temporal context on each extracted export:
|
|
121
123
|
- When was this export first added?
|
|
122
124
|
- Has it been modified recently?
|
|
@@ -125,6 +127,10 @@ Query qmd_bridge against the `{skill_name}-extraction` collection for temporal c
|
|
|
125
127
|
|
|
126
128
|
Append temporal metadata to each export in the snapshot.
|
|
127
129
|
|
|
130
|
+
**If a matching extraction collection is found but empty** (pre-query probe reports `Files: 0 (updated never)` or an empty listing):
|
|
131
|
+
Log: "QMD collection `{collection_name}` is registered but empty. Run `qmd update` to (re-)index `{collection.path}`, then re-audit. Temporal enrichment skipped for this run."
|
|
132
|
+
Continue without T2 enrichment — the unpopulated collection is a setup gap, not an extraction failure. Step-04 will fall through to its direct-content fallback for semantic diff.
|
|
133
|
+
|
|
128
134
|
**If no matching collection found in registry:**
|
|
129
135
|
Log: "No QMD extraction collection found for {skill_name}. Temporal enrichment skipped. Re-run [CS] Create Skill to generate the collection."
|
|
130
136
|
Continue without T2 enrichment — this is not an error.
|
|
@@ -29,10 +29,20 @@ Load both datasets:
|
|
|
29
29
|
**Current (from Step 02 extraction):**
|
|
30
30
|
- Export list with names, types, signatures, file paths, line numbers
|
|
31
31
|
|
|
32
|
+
**Canonicalize extractor methodology differences before matching.** The extractor used by `skf-create-skill` at baseline time and the re-extractor used by step-02 can differ in cosmetic detail (quote style, module qualification, re-export resolution). Without normalization, those cosmetic differences surface as false-positive "Changed" and "Removed" entries even when the source commit has not moved. Apply these transforms to both sets symmetrically:
|
|
33
|
+
|
|
34
|
+
- **Quote style on string defaults.** Normalize string-literal defaults in signatures to a single style — e.g., `kind: str = "Hnsw"` ↔ `kind: str = 'Hnsw'`. Pick one canonical form and apply to both sides.
|
|
35
|
+
- **Module qualification of stdlib helpers.** Strip module prefixes on well-known stdlib helpers when the unqualified form is importable at the call site: `dataclasses.field(...)` → `field(...)`, `typing.Optional[...]` → `Optional[...]`, `typing.List[...]` → `List[...]`. Do not collapse user-defined namespaces.
|
|
36
|
+
- **Public-API re-export resolution.** When `{source_root}/**/__init__.py` re-exports an internal symbol under a different public name (`from .internal import _Impl as Public`, or via `__all__`), resolve both sides to the public name before key-matching — otherwise a renamed re-export in the current scan shows up as "Removed `_Impl`" + "Added `Public`" instead of matching the baseline entry. Build the re-export map once per package by walking `__init__.py` files.
|
|
37
|
+
|
|
38
|
+
Record the set of transforms actually applied in workflow context — step-06 surfaces them in the Provenance section so a reviewer can tell which differences the diff collapsed and which were real.
|
|
39
|
+
|
|
32
40
|
Normalize both sets for comparison:
|
|
33
|
-
- Match by export name (primary key)
|
|
41
|
+
- Match by canonicalized export name (primary key)
|
|
34
42
|
- Group by file for location-aware comparison
|
|
35
43
|
|
|
44
|
+
> **Longer-term fix.** The principled remedy is to persist `skf-create-skill`'s ast-grep ruleset to `{forge_version}/extraction-rules.yaml` at create time and have step-02 replay that exact ruleset. When the file is present, step-02 extraction becomes reproducible against the baseline and the canonicalization pass above becomes a no-op. Until then, normalization is the salvage remediation for provenance maps that predate extractor pinning.
|
|
45
|
+
|
|
36
46
|
### 2. Detect Added Exports
|
|
37
47
|
|
|
38
48
|
**Launch subprocess (Pattern 4 — parallel execution):** In Claude Code, use multiple parallel Agent tool calls. In CLI, use `xargs -P` or equivalent.
|
|
@@ -106,6 +116,14 @@ If `{is_stack_skill}` is true:
|
|
|
106
116
|
|
|
107
117
|
### 5. Compile Structural Drift Section
|
|
108
118
|
|
|
119
|
+
**Rollup for high-volume uniform findings.** When ≥ 10 findings in the same table share one root cause (deleted source file, renamed module, entire package tree removed), you MAY collapse them into one row per root cause. Rollup rows replace the per-symbol `Export`/`Signature` columns with `Count` and `Representative symbols` (up to 3 names, `…` if more). Rollup applies to **Added Exports**, **Removed Exports**, and **Script/Asset Drift** tables — **not** to Changed Exports, which are heterogeneous by construction (signature changes and cross-file changes are inspected per-finding). Record which groupings were collapsed in workflow context for reviewer traceability.
|
|
120
|
+
|
|
121
|
+
**Rollup row form (Added / Removed Exports):**
|
|
122
|
+
|
|
123
|
+
| Root Cause | Count | Representative symbols | Location | Confidence |
|
|
124
|
+
|------------|-------|------------------------|----------|------------|
|
|
125
|
+
| {deleted/renamed path or similar} | {N} | `{sym1}`, `{sym2}`, `{sym3}`, … | {root-cause path} | {T1/T1-low} |
|
|
126
|
+
|
|
109
127
|
Append to {outputFile}:
|
|
110
128
|
|
|
111
129
|
```markdown
|
|
@@ -47,7 +47,16 @@ Continue to section 2.
|
|
|
47
47
|
### 2. Query Original Knowledge Context
|
|
48
48
|
|
|
49
49
|
Launch a subprocess (Pattern 3 — data operations) that:
|
|
50
|
-
1. Read the `qmd_collections` registry from `{sidecar_path}/forge-tier.yaml`. Find the entry where `skill_name` matches `{skill_name}` AND `type` is `"extraction"`.
|
|
50
|
+
1. Read the `qmd_collections` registry from `{sidecar_path}/forge-tier.yaml`. Find the entry where `skill_name` matches `{skill_name}` AND `type` is `"extraction"`. Three cases must be handled distinctly — collapsing them into "found vs. not found" silently degrades semantic diff when a collection is registered but never indexed.
|
|
51
|
+
|
|
52
|
+
- **Registry entry missing.** Log: "No QMD extraction collection found for `{skill_name}`. Semantic diff skipped." → Auto-proceed to {nextStepFile}.
|
|
53
|
+
- **Registry entry present but collection empty.** Run a pre-query probe — `qmd ls {collection_name}` (CLI) or the equivalent MCP call. If it reports zero files (`Files: 0 (updated never)` or an empty listing), the collection is registered but has never been indexed. Do **not** proceed to querying — queries will return nothing and the step would silently degrade.
|
|
54
|
+
- Log: "QMD collection `{collection_name}` is registered but empty. Run `qmd update` to (re-)index `{collection.path}`, then re-audit for full Deep-tier semantic coverage."
|
|
55
|
+
- Fall through to the **direct-content fallback** below instead of skipping outright.
|
|
56
|
+
- **Registry entry present and populated.** Use the `name` field from the registry entry as the collection to query. Proceed to bullet 2.
|
|
57
|
+
|
|
58
|
+
**Direct-content fallback** (used when the collection is registered but empty): load `SKILL.md` and `references/*.md` from the audited skill, then spot-check each documented export against the current source tree under `{source_root}` using the Deep-tier AST tooling this step already requires (ast_bridge; see step-02 §1 "Deep tier"). This fallback is reachable only from Deep tier — §1 short-circuits Quick/Forge/Forge+ before §2 runs, so AST tooling is guaranteed available here. Record findings with confidence label `T1-low-fallback` rather than T2 — this is direct content inspection, not QMD-backed semantic analysis. The step's output schema is otherwise unchanged; set `qmd_collection = null` in the Semantic Drift header and annotate: "Semantic diff ran in direct-content fallback mode — QMD collection was registered but empty."
|
|
59
|
+
|
|
51
60
|
2. Queries for knowledge context around each export documented in the skill
|
|
52
61
|
3. Retrieves: usage patterns, conventions, architectural context, dependency relationships
|
|
53
62
|
4. Returns structured findings to parent
|
|
@@ -85,6 +85,14 @@ Apply scoring rules from {severityRulesFile}:
|
|
|
85
85
|
|
|
86
86
|
### 5. Compile Severity Classification Section
|
|
87
87
|
|
|
88
|
+
**Rollup inherits from step-03.** If step-03 §5 collapsed ≥ 10 same-kind findings into a single rollup row (deleted source file, renamed module, entire package tree removed), carry that rollup through to the matching severity table as one row — do not re-expand it here. Keep the existing 6-column severity table shape; the rollup encodes root cause, count, and representative symbols **inline in the `Finding` cell** rather than adding new columns, so rollup and per-item rows render cleanly in one table. Changed-signature and cross-file findings remain per-row; they were not eligible for rollup in step-03 and are not eligible here.
|
|
89
|
+
|
|
90
|
+
**Rollup row form (any severity table):**
|
|
91
|
+
|
|
92
|
+
| # | Finding | Type | Detail | Location | Confidence |
|
|
93
|
+
|---|---------|------|--------|----------|------------|
|
|
94
|
+
| N | {root cause} (×{Count}; rep: `{sym1}`, `{sym2}`, `{sym3}`, …) | {structural/semantic} | {shared detail} | {root-cause path} | {T1/T2} |
|
|
95
|
+
|
|
88
96
|
Append to {outputFile}:
|
|
89
97
|
|
|
90
98
|
```markdown
|
|
@@ -77,6 +77,11 @@ Append to {outputFile}:
|
|
|
77
77
|
{IF any CRITICAL or HIGH findings:}
|
|
78
78
|
**Recommended:** Run `[US] Update Skill` workflow to apply priority remediations automatically.
|
|
79
79
|
|
|
80
|
+
{IF `audit_ref != baseline_ref` (source version bump detected in step-01 §5b):}
|
|
81
|
+
**Version preservation (non-destructive).** `update-skill` preserves the prior version at `{skill_group}/{baseline_version}/` unchanged and writes the new skill to `{skill_group}/{audit_version}/` (see `skf-update-skill/steps-c/step-04-merge.md` §6b, which creates the new version directory and leaves the previous one on disk). The `active` symlink at `{skill_group}/active` repoints to the new version (see `skf-update-skill/steps-c/step-06-write.md` §5b). On the next export, the prior version's export-manifest entry transitions to `status: archived` — files retained for rollback (see `skf-export-skill/steps-c/step-04-update-context.md`). Do **not** recommend `skf-drop-skill` + `skf-create-skill` for a version bump — that destroys the prior version's artifacts.
|
|
82
|
+
|
|
83
|
+
**Surface new entry points for the brief gate.** If the audit observed new top-level modules, renamed package trees, or new public entry points (new `__init__.py`, `index.ts`, `lib.rs`, or equivalent) that were not in the brief's original scope, call them out here. `update-skill` step-02 §1b detects new candidate files via heuristic and prompts `[P]romote` / `[S]kip` / `[U]pdate-brief`; surfacing them in advance makes that gate faster to resolve, or lets the user refine scope via `skf-brief-skill` before running update-skill.
|
|
84
|
+
|
|
80
85
|
{IF only MEDIUM or LOW findings:}
|
|
81
86
|
**Optional:** Minor drift detected. Manual updates sufficient, or run `[US] Update Skill` for automated remediation.
|
|
82
87
|
|
|
@@ -102,6 +107,9 @@ Append to {outputFile}:
|
|
|
102
107
|
| **Provenance Map** | {provenance_map_path} |
|
|
103
108
|
| **Provenance Age** | {days} days |
|
|
104
109
|
| **Mode** | {normal / degraded} |
|
|
110
|
+
| **Baseline Ref / Commit** | `{baseline_ref}` @ `{baseline_commit_short}` |
|
|
111
|
+
| **Audit Ref / Commit** | `{audit_ref}` @ `{audit_commit_short}` ({audit_ref_source}) |
|
|
112
|
+
| **Upstream Latest** | `{latest_tag or remote_head or "(not fetched)"}` |
|
|
105
113
|
|
|
106
114
|
**Confidence Legend:**
|
|
107
115
|
- **T1:** AST extraction — high reliability, structural truth
|