bmad-module-skill-forge 1.0.0-rc.3 → 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 +523 -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
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="website/public/img/skf-logo.svg" alt="Skill Forge Logo" width="120" />
|
|
3
|
+
<img src="website/public/img/skf-logo-animated.svg" alt="Skill Forge Logo" width="120" />
|
|
4
4
|
|
|
5
5
|
# Skill Forge (SKF)
|
|
6
6
|
|
|
@@ -181,11 +181,11 @@ Past releases are documented in [CHANGELOG.md](CHANGELOG.md).
|
|
|
181
181
|
|
|
182
182
|
## Versioning & Stability
|
|
183
183
|
|
|
184
|
-
The v1.0.0 public API contract is documented in [docs/STABILITY.md](docs/STABILITY.md).
|
|
184
|
+
The v1.0.0 public API contract is documented in [docs/_internal/STABILITY.md](docs/_internal/STABILITY.md).
|
|
185
185
|
|
|
186
186
|
## Release Process
|
|
187
187
|
|
|
188
|
-
Maintainers: see [docs/RELEASING.md](docs/RELEASING.md) for branch-protection rules, required status checks, the [`release` environment with required-reviewer gate](docs/RELEASING.md#release-environment), the [npm Trusted Publisher registration](docs/RELEASING.md#npm-trusted-publisher) (OIDC-backed publish, auto-provenance), and the [rollback playbook](docs/RELEASING.md#rollback-playbook) covering seven failure scenarios.
|
|
188
|
+
Maintainers: see [docs/_internal/RELEASING.md](docs/_internal/RELEASING.md) for branch-protection rules, required status checks, the [`release` environment with required-reviewer gate](docs/_internal/RELEASING.md#release-environment), the [npm Trusted Publisher registration](docs/_internal/RELEASING.md#npm-trusted-publisher) (OIDC-backed publish, auto-provenance), and the [rollback playbook](docs/_internal/RELEASING.md#rollback-playbook) covering seven failure scenarios.
|
|
189
189
|
|
|
190
190
|
## License
|
|
191
191
|
|
package/docs/_data/pinned.yaml
CHANGED
|
@@ -22,8 +22,11 @@
|
|
|
22
22
|
# File ignored by Astro/Starlight content collections because the parent
|
|
23
23
|
# directory starts with `_`. It is purely a build-time / CI-time anchor.
|
|
24
24
|
|
|
25
|
-
# SKF package version — matches the `version` field in package.json
|
|
26
|
-
|
|
25
|
+
# SKF package version — matches the `version` field in package.json.
|
|
26
|
+
# Enforced two ways: (1) release.yaml bumps this line in the same commit
|
|
27
|
+
# as package.json + marketplace.json on every release; (2) validate-docs-drift.js
|
|
28
|
+
# cross-checks this value against package.json.version and fails on mismatch.
|
|
29
|
+
skf_version: "1.1.0"
|
|
27
30
|
|
|
28
31
|
# Path to the oh-my-skills repo, resolved relative to this repo's root.
|
|
29
32
|
# Override at runtime with the OMS environment variable if oh-my-skills
|
|
@@ -77,12 +77,22 @@ The publish job is gated by a **GitHub [deployment environment](https://docs.git
|
|
|
77
77
|
| `prevent_self_review` | `false` — see rationale below |
|
|
78
78
|
| `reviewers` | `armelhbobdad` (user id `132626034`), 1 approver |
|
|
79
79
|
| `deployment_branch_policy` | `custom_branch_policies: true`, list: `main` only |
|
|
80
|
-
| Environment-scoped secrets | `0` (invariant — see
|
|
80
|
+
| Environment-scoped secrets | `0` (invariant — see "No secret is scoped to this environment" note below) |
|
|
81
81
|
| Cost | `$0` on public-repo tier (environments, required reviewers, and branch policies are [free for public repositories](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#about-environments)) |
|
|
82
82
|
|
|
83
83
|
**`prevent_self_review: false` — correctness constraint, not a loosened control.** Solo-maintainer setups cannot self-approve when this is `true`, so the gate would deadlock on any maintainer-triggered publish. The value flips to `true` the moment a second reviewer joins — do not leave it loose by inertia.
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
**No secret is scoped to this environment.** The repo no longer carries an `NPM_TOKEN` secret at any scope (removed in Story 6.3 post-v1.0.0 once OIDC trusted publishing was operationally proven by the v1.0.0 launch). The invariant: the `release` env must have zero environment-scoped secrets, and the repo must have zero `NPM_TOKEN`-shaped secrets at any scope. If a future change scopes any secret to this environment, or if an `NPM_TOKEN` secret is ever re-added at repo scope, re-audit whether the OIDC trusted-publisher path is still in force — the OIDC path SHOULD be self-sufficient and a re-added token is a signal that something has regressed off the canonical path.
|
|
86
|
+
|
|
87
|
+
**Audit command.** Both halves of the invariant are machine-checkable:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Repo-scope: expect 0
|
|
91
|
+
gh secret list --repo armelhbobdad/bmad-module-skill-forge | grep -ci npm_token
|
|
92
|
+
|
|
93
|
+
# Env-scope: expect {"total_count":0,"secrets":[]}
|
|
94
|
+
gh api repos/armelhbobdad/bmad-module-skill-forge/environments/release/secrets
|
|
95
|
+
```
|
|
86
96
|
|
|
87
97
|
**Coupling with npm trusted publishing (Story 1.3).** The npm trusted publisher binds on four fields — `organization=armelhbobdad`, `repository=bmad-module-skill-forge`, `workflow filename=release.yaml`, `environment=release`. The environment name above is load-bearing: any rename here must be accompanied by a matching npm-side update in the same change, or the next publish returns 404.
|
|
88
98
|
|
|
@@ -174,7 +184,7 @@ The future `release.yaml` workflow (Story 3.1) publishes to npm via **OIDC trust
|
|
|
174
184
|
|
|
175
185
|
**Pre-registration inversion.** This entry was registered **before** `release.yaml` was authored (Story 3.1). The first live validator of the full OIDC chain is Story 3.2's alpha cut. If that cut's publish step 404s, open a **three-way comparison**: (1) the npm Settings tab, (2) the workflow YAML's `name` / `on` / `jobs.<id>.environment` lines, and (3) the Registered table above. The table is the ground truth because it captured the values at npm-save time — compare both the npm record and the workflow header against the table, never the workflow against itself (verifying the workflow against its own header will silently confirm a typo).
|
|
176
186
|
|
|
177
|
-
**`NPM_TOKEN` is
|
|
187
|
+
**`NPM_TOKEN` is gone — OIDC is the only publish credential surface.** The token was removed from repo-level secrets in Story 6.3 (post-v1.0.0, once OIDC trusted publishing was operationally proven by the v1.0.0 launch). SKF's npm publish credential surface is now OIDC-only. Future incidents requiring credential revocation involve npmjs.com's trusted-publisher config, not a repo secret. `release.yaml` authenticates via Trusted Publisher OIDC and continues to set `NPM_TOKEN: ""` explicitly in both the pre-publish dry-run step and the final publish step as defense-in-depth against a stale token being auto-picked-up by npm from the runner env — those literal empty-string assignments are not `secrets.*` reads and stay load-bearing regardless of the secret's presence or absence. Both sites carry a `# DO NOT REMOVE — FR4 defense-in-depth` inline comment so a future cleanup pass does not silently delete them; audit with `grep -c 'NPM_TOKEN: ""' .github/workflows/release.yaml` (expect `2`). If a future OIDC incident forces a last-resort token-based re-publish path, re-adding `NPM_TOKEN` at repo scope is the exception-path, not the default — document the flip in the commit body, file an issue for the OIDC incident class that required it, and remove the token again the moment OIDC is restored.
|
|
178
188
|
|
|
179
189
|
**Fixing a bad registration.** The npm UI exposes both **Edit** and **Delete** on an existing Trusted Publisher entry (observed 2026-04-20). Prefer edit for a single-field typo; prefer delete-and-re-add if multiple fields are wrong or the edit form ever feels ambiguous. **Pre-Story 3.2**: there is no destructive side effect because no publish is attempted yet, and delete-and-re-add keeps the audit trail cleaner. **Post-Story 3.2**: a publish that fires during the delete-and-re-add window will 404 — gate any delete-and-re-add behind a manual publish freeze (pause any active `release.yaml` runs, confirm no tags are in-flight) before touching the entry.
|
|
180
190
|
|
|
@@ -423,8 +433,7 @@ Placeholder substitutions used throughout:
|
|
|
423
433
|
- **Post-incident reactivation.** After audit completes and root cause is identified and patched, re-register the Trusted Publisher via the npm UI with the four fields matching the table in `## npm Trusted Publisher` above (`organization=armelhbobdad`, `repository=bmad-module-skill-forge`, `workflow filename=release.yaml`, `environment=release`). Re-verify via an alpha cut (dispatch `release.yaml` from a temporarily-allowed feature branch per the `## Release Environment § Temporarily allowing a feature branch` procedure) before any stable release.
|
|
424
434
|
- **Pre-v1.0.0 context.** Trusted Publisher was pre-registered on 2026-04-20 (Story 1.3). A compromise discovered pre-v1.0.0 is recoverable via delete-and-re-register with no downstream-consumer blast radius (no stable release users yet). Post-v1.0.0, the incident has downstream blast radius and the `support@npmjs.com` coordination path is load-bearing.
|
|
425
435
|
- **Do-NOT clause — `NPM_TOKEN` rotation is not OIDC incident response.** Do NOT rotate `NPM_TOKEN` as a first response. The token is not on the OIDC path; rotating it does nothing to stop an OIDC compromise.
|
|
426
|
-
- If `NPM_TOKEN`
|
|
427
|
-
- `NPM_TOKEN` still exists at repo scope until Story 6.3 (post-v1.0.0). A compromised `NPM_TOKEN` is a **separate incident class** from OIDC compromise. During the window where OIDC is revoked _and_ `NPM_TOKEN` is also compromised, there is no valid publish path — the repo enters lockdown until Trusted Publisher is re-registered. Document the flip in the incident post-mortem; do not publish via any stale path.
|
|
436
|
+
- If an `NPM_TOKEN` exists at repo scope at the time of an incident (exception-path per § npm Trusted Publisher), revoke it at `https://www.npmjs.com` → **Access Tokens** AND remove it from the repo: `gh secret delete NPM_TOKEN --repo armelhbobdad/bmad-module-skill-forge`. A compromised `NPM_TOKEN` would be a **separate incident class** from OIDC compromise. **Expected outcomes of the delete command under incident pressure** — read the response before escalating: (a) `Secret deleted` = success, token revoked at repo-scope; (b) `could not find secret NPM_TOKEN` (exit 1, 404) = no-op SAFE, the token is already absent per the post-Story-6.3 default and this is the expected normal-operation state, not a broken scope or auth issue; (c) any `401` / `403` / scope-permission error = investigate before retrying, likely a `gh auth` or org-permissions issue unrelated to the token's presence. Story 6.3 removed the token in 2026-04 post-v1.0.0 so outcome (b) is the default; outcome (a) only applies during the exception-path window where a temporary token re-add has already happened. During a window where OIDC is revoked AND an exception-path token is also compromised, there is no valid publish path — the repo enters lockdown until Trusted Publisher is re-registered. Document the flip in the incident post-mortem; do not publish via any stale path.
|
|
428
437
|
|
|
429
438
|
### Scenario G — "release.yaml disabled, reverted, or missing from main"
|
|
430
439
|
|
|
@@ -465,29 +474,16 @@ Placeholder substitutions used throughout:
|
|
|
465
474
|
grep -l 'id-token: write' .github/workflows/*.{yaml,yml} 2>/dev/null
|
|
466
475
|
# expected set:
|
|
467
476
|
# - docs.yaml (GitHub Pages — orthogonal to release)
|
|
468
|
-
# - publish.yaml (DEPRECATED — kept until Story 6.1 deletes it; workflow_dispatch-only,
|
|
469
|
-
# surviving as the Scenario G emergency hatch)
|
|
470
477
|
# - release.yaml (canonical)
|
|
471
478
|
|
|
472
|
-
# No `v*` push trigger should exist in any workflow — release.yaml is workflow_dispatch-only
|
|
473
|
-
# and publish.yaml had its push:tags:v* trigger neutralized in Story 3.3 Patch A.
|
|
479
|
+
# No `v*` push trigger should exist in any workflow — release.yaml is workflow_dispatch-only.
|
|
474
480
|
# Scan the 3 lines following each `push:` block for a v* tag pattern.
|
|
475
481
|
grep -A3 -E '^\s*push:' .github/workflows/*.{yaml,yml} 2>/dev/null \
|
|
476
482
|
| grep -E "['\"]v\*['\"]"
|
|
477
483
|
# expected: zero matches.
|
|
478
484
|
```
|
|
479
485
|
|
|
480
|
-
- **Escalation path — emergency hatch
|
|
481
|
-
|
|
482
|
-
```bash
|
|
483
|
-
gh workflow run publish.yaml
|
|
484
|
-
```
|
|
485
|
-
|
|
486
|
-
Read the next two paragraphs **before** dispatching:
|
|
487
|
-
- **Auth vs. provenance — they are independent.** `publish.yaml` authenticates to npm with `NODE_AUTH_TOKEN=${{ secrets.NPM_TOKEN }}` (token-based; NOT OIDC trusted publishing — that path is `release.yaml`-only). However, the workflow also has `id-token: write` permission and calls `npm publish --provenance`, so npm WILL attach a SLSA-L2 provenance attestation derived from the GitHub Actions OIDC token. Provenance is independent of the auth-to-npm path. The trade-off is auth lineage (token vs. trusted-publisher OIDC), not attestation presence.
|
|
488
|
-
- **State divergence — `publish.yaml` does NOT bump version, push the `v*` tag, update `CHANGELOG.md`, or create a GitHub Release.** It only runs `npm publish` against whatever `package.json` is at HEAD of the dispatched ref. Every emergency-hatch use therefore leaves npm + git state diverged and requires a Scenario E-style reconciliation afterward: bump `package.json` manually on `main` (so the next release does not collide), then recreate the tag and GitHub Release per Scenario E.
|
|
489
|
-
|
|
490
|
-
Document every emergency-hatch use in an incident post-mortem, and re-enable `release.yaml` before the next release. This fallback disappears when Story 6.1 deletes `publish.yaml`.
|
|
486
|
+
- **Escalation path — PR-revert only.** There is no out-of-band emergency hatch. Recovery flows exclusively through the Case 2 PR-revert path above: revert the offending workflow change via `gh pr revert`, merge through branch protection, then retry the release via `release.yaml`. Every release threads through branch protection + code review + OIDC Trusted Publisher, matching NFR2 and NFR3.
|
|
491
487
|
|
|
492
488
|
- **Constraints.** Branch protection on `main` blocks direct pushes — recovery goes through a PR in every case. Do not attempt to sidestep branch protection to "fix" `release.yaml` faster; the cost of a bad release (NFR5 audit-trail breakage, NFR10 commit-trail breakage) far exceeds the cost of a normal-review PR.
|
|
493
489
|
|
|
@@ -556,61 +552,91 @@ The `POST` body needs the same `name`, `target`, `enforcement`, `conditions`, `r
|
|
|
556
552
|
|
|
557
553
|
For the `release` environment, a deletion+restore similarly uses the two-call pattern already documented at `## Release Environment § Restore / re-apply` — feed the environment-level baseline JSON to the `PUT .../environments/release` call, then re-POST each entry from the branch-policies baseline to `.../environments/release/deployment-branch-policies`.
|
|
558
554
|
|
|
559
|
-
### Cutting v1.0.0
|
|
555
|
+
### Cutting v1.0.0 under --tag latest
|
|
560
556
|
|
|
561
|
-
- **Trigger.**
|
|
557
|
+
- **Trigger.** The passing RC has survived a clean-environment smoke test (`release-audits/v1.0.0-launch-audit.md § Story 5.2 RC Cut + Smoke Test § Decision: PASS — cleared for Story 5.3 promotion to v1.0.0 under --tag latest with manual approval`); `npm view bmad-module-skill-forge@rc version` returns the passing RC (at Story 5.3 dispatch time: `1.0.0-rc.3`); Story 5.3 is ready to promote to `latest` under manual approval.
|
|
562
558
|
- **CLI.**
|
|
563
559
|
|
|
564
560
|
```bash
|
|
565
|
-
# Hand-bump main onto the 1.0.0 line. Do not tag; release.yaml owns tags.
|
|
566
561
|
git checkout main && git pull
|
|
567
|
-
|
|
568
|
-
#
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
#
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
#
|
|
576
|
-
#
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
562
|
+
|
|
563
|
+
# Pre-dispatch sanity check (read version from remote, not local clone).
|
|
564
|
+
gh api repos/armelhbobdad/bmad-module-skill-forge/contents/package.json \
|
|
565
|
+
--jq '.content' | base64 -d | jq -r .version
|
|
566
|
+
# expected: the passing RC (e.g., 1.0.0-rc.3)
|
|
567
|
+
|
|
568
|
+
# Dispatch the canonical release workflow. `version_bump: major` on
|
|
569
|
+
# 1.0.0-rc.N strips the prerelease suffix and produces 1.0.0 (node-semver
|
|
570
|
+
# inc(ver, 'major') behavior on a prerelease). `--ref main` is explicit
|
|
571
|
+
# (gh defaults to the repo's default branch, but any non-main ref takes
|
|
572
|
+
# the legacy tag-only path inside release.yaml, so pass it defensively).
|
|
573
|
+
gh workflow run release.yaml -f version_bump=major --ref main
|
|
574
|
+
|
|
575
|
+
# Capture the run id for monitoring + audit transcript.
|
|
576
|
+
RUN_ID=$(gh run list --workflow=release.yaml --limit 1 \
|
|
577
|
+
--json databaseId --jq '.[0].databaseId')
|
|
578
|
+
gh run watch $RUN_ID
|
|
581
579
|
```
|
|
582
580
|
|
|
583
|
-
|
|
581
|
+
The workflow pauses at **two** gates that the maintainer must clear in the browser. Gate 1 requires explicit approval; gate 2 accepts either approval or admin-bypass-merge:
|
|
582
|
+
|
|
583
|
+
1. The `release` environment deployment gate (at job start). Approve via "Review deployments" → "Approve and deploy" on the run page.
|
|
584
|
+
2. The bot PR review-decision gate (after the 7 required status checks pass). EITHER approve the bot PR via the review UI, OR admin-bypass-merge via the PR merge button — both paths are accepted by `release.yaml`'s `Wait for PR approval or admin-bypass merge` step. Admin-bypass-merge is the observed pattern for prior cuts (PRs #209 and #213).
|
|
585
|
+
|
|
586
|
+
Expected wall-clock: ~5–8 minutes end-to-end when both gates are approved promptly.
|
|
587
|
+
|
|
588
|
+
- **Expected outcome.** `main` tip advances by 2 commits (the `release: bump to v1.0.0` commit on the bot temp branch `release/bot/v1.0.0-<run_id>`, plus the merge commit from the auto-merged or admin-bypass-merged bot PR); `jq -r .version package.json` → `1.0.0`; `jq -r '.plugins[0].version' .claude-plugin/marketplace.json` → `1.0.0`; `npm view bmad-module-skill-forge dist-tags.latest` → `1.0.0` (flipped from the prior stable, e.g. `0.10.0`); `rc` dist-tag UNCHANGED at the prior RC; SLSA L2 provenance attached (NFR4); GitHub Release `v1.0.0` with `prerelease: false` (NFR6 threshold — `1.0.0` contains no `alpha|beta|rc` substring); tag `v1.0.0` anchors on the bot PR's merge commit per Story 3.4 P9 (the tag is annotated, so `git rev-parse 'v1.0.0^{}'` gives the commit SHA to compare against `main` tip).
|
|
589
|
+
|
|
584
590
|
- **Constraints.**
|
|
585
|
-
- Execute ONLY after
|
|
586
|
-
- The
|
|
587
|
-
-
|
|
588
|
-
-
|
|
589
|
-
- If
|
|
591
|
+
- Execute ONLY after the RC audit `§ Sign-off` is populated AND the smoke-test `Decision` is `PASS`.
|
|
592
|
+
- The cut is IRREVERSIBLE — once `npm publish --tag latest` succeeds for `1.0.0`, NFR6 forbids unpublish regardless of eligibility window. Rollback is `npm deprecate` + ship-forward (Scenarios A / B).
|
|
593
|
+
- The CHANGELOG reconciliation is a POST-workflow step (authored as a separate sign-off commit on `feat/v1-final-signoff`). Do NOT hand-edit the `## [1.0.0] - TBD` placeholder BEFORE dispatch — let the workflow auto-generate its `## [1.0.0]` block (which may be EMPTY when there are zero conventional-commit `feat:` / `fix:` entries between the RC and the final cut, which is the normal case), then merge the hand-curated prose into the auto-gen header's position and delete the stale placeholder in one commit.
|
|
594
|
+
- Do NOT pre-bump `package.json` or `.claude-plugin/marketplace.json` — the workflow's `Bump version` and `Update marketplace.json version` steps handle both atomically and own those files.
|
|
595
|
+
- If `npm version major` unexpectedly emits `2.0.0` instead of `1.0.0` on `1.0.0-rc.N`, the node-semver engine behavior has regressed. Abort the dispatch and investigate before retry — a workflow override (`npm version 1.0.0 --no-git-tag-version`) would be required in `release.yaml`.
|
|
596
|
+
|
|
590
597
|
- **Verification.**
|
|
591
598
|
|
|
592
599
|
```bash
|
|
593
|
-
# Confirm the
|
|
594
|
-
npm view bmad-module-skill-forge
|
|
595
|
-
# expected: 1.0.0-rc.
|
|
600
|
+
# Confirm the latest dist-tag flipped to 1.0.0.
|
|
601
|
+
npm view bmad-module-skill-forge dist-tags --json
|
|
602
|
+
# expected: {"latest":"1.0.0","alpha":"...","rc":"1.0.0-rc.N"}
|
|
603
|
+
|
|
604
|
+
npm view bmad-module-skill-forge@latest version
|
|
605
|
+
# expected: 1.0.0
|
|
606
|
+
|
|
607
|
+
# Confirm SLSA L2 provenance (NFR4 CRITICAL). A null attestation is a
|
|
608
|
+
# blocker — emergency-deprecate + cut 1.0.1 with provenance per Scenario B.
|
|
609
|
+
npm view bmad-module-skill-forge@1.0.0 --json | jq '.dist.attestations'
|
|
610
|
+
# expected: non-null object; .provenance.predicateType starts with
|
|
611
|
+
# "https://slsa.dev/provenance/"
|
|
612
|
+
|
|
613
|
+
# Confirm the GitHub Release exists and is NOT a prerelease (NFR6 threshold).
|
|
614
|
+
gh release view v1.0.0 --json tagName,isPrerelease
|
|
615
|
+
# expected: {"tagName":"v1.0.0","isPrerelease":false}
|
|
616
|
+
|
|
617
|
+
# Confirm the v1.0.0 tag is reachable from main (annotated tag — dereference with ^{}).
|
|
618
|
+
# Uses --is-ancestor so the check stays valid after subsequent commits land on main;
|
|
619
|
+
# pin to the recorded merge SHA if you need strict tag-anchor equivalence.
|
|
620
|
+
git fetch origin --tags
|
|
621
|
+
git merge-base --is-ancestor "$(git rev-parse 'v1.0.0^{}')" origin/main && echo OK
|
|
622
|
+
# expected: OK
|
|
623
|
+
|
|
624
|
+
# Confirm CHANGELOG reconciliation after the sign-off commit lands on main.
|
|
625
|
+
grep -c '^## \[1\.0\.0\] - TBD' CHANGELOG.md # expected: 0 (stale placeholder gone)
|
|
626
|
+
grep -cE '^## \[1\.0\.0\]' CHANGELOG.md # expected: 1 (one reconciled block)
|
|
627
|
+
grep -cE '^## \[1\.0\.0\]\(https' CHANGELOG.md # expected: 1 (compare-URL header survived)
|
|
628
|
+
```
|
|
596
629
|
|
|
597
|
-
npm
|
|
598
|
-
# expected: 1.0.0-rc.1
|
|
630
|
+
**NFR6 immutability activation** is the `npm publish --tag latest` success timestamp for `1.0.0`, recorded verbatim in `release-audits/v1.0.0-launch-audit.md § Story 5.3 v1.0.0 Final Cut § NFR6 v1.0.0 immutability activation`. For Story 5.3's dispatch, that instant was **2026-04-23T18:56:39Z**. From that moment, `v1.0.0` is forever-burned — `npm deprecate` + ship-forward is the only rollback path.
|
|
599
631
|
|
|
600
|
-
#
|
|
601
|
-
npm view bmad-module-skill-forge@1.0.0-rc.1 --json | jq '.dist.attestations'
|
|
602
|
-
# expected: non-null object containing a provenance url
|
|
632
|
+
The `release` environment + bot PR approval-or-admin-bypass-merge pattern is the canonical flow for all main-dispatched cuts since Story 3.4 ([GitHub issue #198](https://github.com/armelhbobdad/bmad-module-skill-forge/issues/198), [PR #199](https://github.com/armelhbobdad/bmad-module-skill-forge/pull/199)): the release commit is pushed to a temp branch `release/bot/vX.Y.Z-<run_id>`, a bot PR is opened against `main`, the 7 required status checks are force-triggered against the temp branch via `workflow_dispatch`, and the merge is gated behind maintainer approval at both the `release` environment gate and the PR review-decision gate. Non-main dispatches (feature-branch alpha cuts) skip the PR dance entirely and keep the legacy tag-only behavior.
|
|
603
633
|
|
|
604
|
-
|
|
605
|
-
gh release view v1.0.0-rc.1 --json tagName,isPrerelease
|
|
606
|
-
# expected: {"tagName":"v1.0.0-rc.1","isPrerelease":true}
|
|
634
|
+
#### Post-publish verification (NFR9)
|
|
607
635
|
|
|
608
|
-
|
|
609
|
-
# hand-curated v1.0.0 placeholder (Story 5.3 reconciles the placeholder).
|
|
610
|
-
grep -c '^## \[1.0.0-rc.1\]' CHANGELOG.md # expected: 1
|
|
611
|
-
grep -c '^## \[1.0.0\] - TBD' CHANGELOG.md # expected: 1
|
|
612
|
-
```
|
|
636
|
+
Cross-platform install verification for any cut is performed by the [`install-smoke.yaml`](../.github/workflows/install-smoke.yaml) workflow, not by `release.yaml` itself. Dispatch it within 1 hour of publish per NFR9:
|
|
613
637
|
|
|
614
|
-
|
|
638
|
+
```bash
|
|
639
|
+
gh workflow run install-smoke.yaml -f version=latest --ref main
|
|
640
|
+
```
|
|
615
641
|
|
|
616
|
-
|
|
642
|
+
The workflow fans a `workflow_dispatch` input over `ubuntu-latest`, `windows-latest`, and `macos-latest`, running `npx --yes bmad-module-skill-forge@<version> --version` on each runner. A clean three-leg run is the canonical post-publish evidence — its run URL + matrix table belong in the release audit artifact's `## Story <N> Post-Publish Verification` section. Any failing leg routes through the `Rollback Playbook § Scenario B` (deprecate + ship `vX.Y.Z+1`).
|
|
@@ -111,13 +111,13 @@ If a surface you depend on is NOT explicitly enumerated in [§ Covered Surfaces]
|
|
|
111
111
|
|
|
112
112
|
## Changes to This Contract
|
|
113
113
|
|
|
114
|
-
Shrinking the covered surface (removing a commitment) is a breaking change and requires a major-version bump. Expanding the covered surface (promoting an `@internal` surface to covered, or adding a new commitment) is additive and ships in a minor release. This document is versioned alongside the package; historical versions are visible via `git log docs/STABILITY.md`.
|
|
114
|
+
Shrinking the covered surface (removing a commitment) is a breaking change and requires a major-version bump. Expanding the covered surface (promoting an `@internal` surface to covered, or adding a new commitment) is additive and ships in a minor release. This document is versioned alongside the package; historical versions are visible via `git log -- docs/STABILITY.md docs/_internal/STABILITY.md`.
|
|
115
115
|
|
|
116
116
|
## References
|
|
117
117
|
|
|
118
118
|
- [agentskills.io spec](https://github.com/agentskills/agentskills) — external canonical source for the `SKILL.md` frontmatter grammar.
|
|
119
119
|
- [Semantic Versioning 2.0.0](https://semver.org/) — the SemVer semantics this contract commits to.
|
|
120
120
|
- [`CHANGELOG.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/CHANGELOG.md) — release-by-release history; breaking changes are called out there.
|
|
121
|
-
- [`docs/RELEASING.md`](RELEASING.md) — maintainer reference for the release pipeline (companion document: this file is about what ships, `RELEASING.md` is about how).
|
|
121
|
+
- [`docs/_internal/RELEASING.md`](RELEASING.md) — maintainer reference for the release pipeline (companion document: this file is about what ships, `RELEASING.md` is about how).
|
|
122
122
|
- [`tools/cli/lib/platform-codes.yaml`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/tools/cli/lib/platform-codes.yaml) — source of truth for the IDE → skills-directory mapping covered under [§ Installation Layout](#installation-layout).
|
|
123
123
|
- [`test/schema/agent.js`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/test/schema/agent.js) — zod schema definitions for `bmad-skill-manifest.yaml` covered under [§ Skill Manifest & Frontmatter Contract](#skill-manifest--frontmatter-contract).
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "bmad-module-skill-forge",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"description": "BMAD module — Turn code and docs into instructions AI agents can actually follow. Progressive capability tiers (Quick/Forge/Forge+/Deep).",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"bmad",
|
|
@@ -45,11 +45,6 @@
|
|
|
45
45
|
"lint:md": "markdownlint-cli2 \"**/*.md\"",
|
|
46
46
|
"prepare": "husky || exit 0",
|
|
47
47
|
"quality": "npm run format:check && npm run lint && npm run lint:md && npm run test:schemas && npm run test:install && npm run test:cli && npm run test:workflow && npm run test:python && npm run test:knowledge && npm run validate:schemas && npm run validate:skills && npm run validate:refs && npm run docs:validate-drift",
|
|
48
|
-
"release": "echo '[DEPRECATED] Use .github/workflows/release.yaml via GitHub Actions. See docs/RELEASING.md.' >&2 && exit 1 ; npm run release:patch",
|
|
49
|
-
"release:major": "echo '[DEPRECATED] Use .github/workflows/release.yaml via GitHub Actions. See docs/RELEASING.md.' >&2 && exit 1 ; npm version major && git push --follow-tags",
|
|
50
|
-
"release:minor": "echo '[DEPRECATED] Use .github/workflows/release.yaml via GitHub Actions. See docs/RELEASING.md.' >&2 && exit 1 ; npm version minor && git push --follow-tags",
|
|
51
|
-
"release:patch": "echo '[DEPRECATED] Use .github/workflows/release.yaml via GitHub Actions. See docs/RELEASING.md.' >&2 && exit 1 ; npm version patch && git push --follow-tags",
|
|
52
|
-
"release:prerelease": "echo '[DEPRECATED] Use .github/workflows/release.yaml via GitHub Actions. See docs/RELEASING.md.' >&2 && exit 1 ; npm version prerelease && git push --follow-tags",
|
|
53
48
|
"skf:install": "node tools/cli/skf-cli.js install",
|
|
54
49
|
"skf:status": "node tools/cli/skf-cli.js status",
|
|
55
50
|
"skf:uninstall": "node tools/cli/skf-cli.js uninstall",
|