@softspark/ai-toolkit 4.30.2 → 4.30.3
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/CHANGELOG.md +23 -0
- package/README.md +21 -22
- package/app/.claude-plugin/plugin.json +1 -1
- package/kb/procedures/release-preparation-sop.md +81 -20
- package/llms-full.txt +80 -19
- package/manifest.json +1 -1
- package/package.json +1 -1
- package/scripts/doctor.py +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,29 @@ Versioning follows [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## v4.30.3 - Copilot health-check compatibility (2026-09-02)
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **`doctor` accepts sentence punctuation after runtime SemVer.** The official
|
|
15
|
+
Copilot CLI output `GitHub Copilot CLI 1.0.80.` now reports version `1.0.80`
|
|
16
|
+
instead of an invalid-SemVer warning.
|
|
17
|
+
- **Complete-token validation remains strict.** Extra version segments, invalid
|
|
18
|
+
prerelease identifiers, and leading-zero numeric fields are still rejected.
|
|
19
|
+
- **DSH cold-add timing gate is runner-safe.** The regression still proves a
|
|
20
|
+
cold package add can outlive the legacy scaled timeout while leaving enough
|
|
21
|
+
headroom for macOS CI process startup.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **Test count.** Increased from 1920 to 1921 with the exact Copilot output
|
|
26
|
+
regression.
|
|
27
|
+
- **Release tags require green cross-platform branch CI.** The preparation SOP
|
|
28
|
+
now binds the gate to the exact release commit and requires both Ubuntu and
|
|
29
|
+
macOS Bats matrix jobs before creating or pushing a tag.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
10
33
|
## v4.30.2 - Portable Linux release gates (2026-09-02)
|
|
11
34
|
|
|
12
35
|
### Fixed
|
package/README.md
CHANGED
|
@@ -6,28 +6,27 @@
|
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](app/skills/)
|
|
8
8
|
[](app/agents/)
|
|
9
|
-
[](tests/)
|
|
10
|
+
|
|
11
|
+
## What's New in v4.30.3
|
|
12
|
+
|
|
13
|
+
**v4.30.3** corrects the post-release health check for the managed DSH and
|
|
14
|
+
plugin-owned MCP release:
|
|
15
|
+
|
|
16
|
+
- `ai-toolkit doctor` now extracts `1.0.80` from the official Copilot CLI output
|
|
17
|
+
`GitHub Copilot CLI 1.0.80.` instead of treating sentence punctuation as an
|
|
18
|
+
invalid SemVer suffix.
|
|
19
|
+
- Complete-token validation remains fail closed for malformed versions such as
|
|
20
|
+
`1.2.3.4`, invalid prerelease identifiers, and leading-zero numeric fields.
|
|
21
|
+
- The DSH cold-add regression keeps its legacy-timeout coverage with macOS CI
|
|
22
|
+
process-startup headroom, removing the release-blocking timing flake.
|
|
23
|
+
- Release tags now require green Ubuntu and macOS branch CI for the exact commit
|
|
24
|
+
before the publish workflow can start.
|
|
25
|
+
- The release retains the explicit DSH lifecycle, plugin-owned MCP/rules, portable
|
|
26
|
+
recovery gates, and the exact DSH package set published in v4.30.2. Test count:
|
|
27
|
+
1920 -> 1921.
|
|
28
|
+
|
|
29
|
+
See [CHANGELOG.md](CHANGELOG.md) for full history.
|
|
31
30
|
|
|
32
31
|
## Table of Contents
|
|
33
32
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "ai-toolkit",
|
|
4
4
|
"displayName": "AI Toolkit",
|
|
5
5
|
"description": "Professional-grade engineering skills, agents, rules, and lifecycle guardrails for Claude Code, Claude Chat, and Cowork.",
|
|
6
|
-
"version": "4.30.
|
|
6
|
+
"version": "4.30.3",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "SoftSpark",
|
|
9
9
|
"url": "https://github.com/softspark"
|
|
@@ -3,10 +3,10 @@ title: "SOP: Release Preparation"
|
|
|
3
3
|
category: procedures
|
|
4
4
|
service: ai-toolkit
|
|
5
5
|
tags: [sop, release, version, publish, changelog, semver, provenance, sarif, ecosystem, shellcheck]
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.15.0"
|
|
7
7
|
created: "2026-04-10"
|
|
8
|
-
last_updated: "2026-
|
|
9
|
-
description: "Step-by-step checklist for preparing a new ai-toolkit release — ecosystem-sync drift check, version sync, changelog, artifact regeneration, validation, and tagging. Run BEFORE every git tag. Includes mandatory Provenance, SARIF,
|
|
8
|
+
last_updated: "2026-09-02"
|
|
9
|
+
description: "Step-by-step checklist for preparing a new ai-toolkit release — ecosystem-sync drift check, version sync, changelog, artifact regeneration, validation, branch CI, and tagging. Run BEFORE every git tag. Includes mandatory Provenance, SARIF, checksum-pin, ShellCheck, licensing, exact-tag assertions, and a green Ubuntu/macOS branch-CI gate before any release tag is created."
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
# SOP: Release Preparation
|
|
@@ -68,16 +68,38 @@ python3 scripts/ecosystem_doctor.py --offline --check || { echo "STALE ecosystem
|
|
|
68
68
|
# 5c. Licensing gate — SPDX headers, LICENSE, NOTICE, manifest consistency
|
|
69
69
|
npx bats tests/test_licensing.bats || { echo "LICENSING GATE FAILED"; exit 1; }
|
|
70
70
|
|
|
71
|
-
# 6. Commit
|
|
71
|
+
# 6. Commit, push branch, and wait for the exact commit's full CI
|
|
72
72
|
git add -A && git commit -m "chore: release vX.Y.Z"
|
|
73
|
-
git
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
RELEASE_SHA=$(git rev-parse HEAD)
|
|
74
|
+
git push origin main || { echo "FAIL: release commit push failed"; exit 1; }
|
|
75
|
+
RUN_ID=""
|
|
76
|
+
for ATTEMPT in 1 2 3 4 5; do
|
|
77
|
+
RUN_ID=$(gh run list --workflow ci.yml --event push --commit "$RELEASE_SHA" \
|
|
78
|
+
--limit 1 --json databaseId --jq '.[0].databaseId')
|
|
79
|
+
[ -n "$RUN_ID" ] && break
|
|
80
|
+
echo "Waiting for CI run registration ($ATTEMPT/5)" >&2
|
|
81
|
+
[ "$ATTEMPT" -eq 5 ] || sleep 60
|
|
82
|
+
done
|
|
83
|
+
test -n "$RUN_ID" || { echo "FAIL: CI run not found for release commit"; exit 1; }
|
|
84
|
+
gh run watch "$RUN_ID" --exit-status \
|
|
85
|
+
|| { echo "FAIL: release commit CI failed"; exit 1; }
|
|
86
|
+
for OS in ubuntu-latest macos-latest; do
|
|
87
|
+
gh run view "$RUN_ID" --json jobs \
|
|
88
|
+
--jq ".jobs[] | select(.name == \"Bats test suite ($OS)\") | .conclusion" \
|
|
89
|
+
| grep -qx success || { echo "FAIL: $OS test job not green"; exit 1; }
|
|
90
|
+
done
|
|
91
|
+
test "$(git rev-parse HEAD)" = "$RELEASE_SHA" || { echo "FAIL: local HEAD changed during CI"; exit 1; }
|
|
92
|
+
git fetch origin main || { echo "FAIL: origin/main refresh failed"; exit 1; }
|
|
93
|
+
test "$(git rev-parse origin/main)" = "$RELEASE_SHA" || { echo "FAIL: origin/main changed during CI"; exit 1; }
|
|
94
|
+
|
|
95
|
+
# 6a. Only green branch CI authorizes tag creation
|
|
96
|
+
git tag vX.Y.Z "$RELEASE_SHA"
|
|
97
|
+
|
|
98
|
+
# 6b. Assert the tag before pushing it (v4.19.0 postmortem, Phase 7)
|
|
99
|
+
test "$(git rev-parse vX.Y.Z)" = "$RELEASE_SHA" || { echo "FAIL: tag not on tested release commit"; exit 1; }
|
|
77
100
|
git show --no-patch --format=%s vX.Y.Z | grep -qx "chore: release vX.Y.Z" || { echo "FAIL: tag not on release commit"; exit 1; }
|
|
78
101
|
|
|
79
|
-
#
|
|
80
|
-
git push origin main
|
|
102
|
+
# 6c. Push the single tag by full ref. Never --tags.
|
|
81
103
|
git push origin refs/tags/vX.Y.Z
|
|
82
104
|
```
|
|
83
105
|
|
|
@@ -493,23 +515,60 @@ git commit -m "chore: release vX.Y.Z"
|
|
|
493
515
|
|
|
494
516
|
---
|
|
495
517
|
|
|
496
|
-
## Phase 7: Tag and Push
|
|
518
|
+
## Phase 7: Push Branch, Verify CI, Tag, and Push Tag
|
|
497
519
|
|
|
498
520
|
```bash
|
|
499
|
-
git
|
|
521
|
+
RELEASE_SHA=$(git rev-parse HEAD)
|
|
522
|
+
git push origin main || { echo "FAIL: release commit push failed"; exit 1; }
|
|
523
|
+
|
|
524
|
+
# Bind the gate to the exact release commit. GitHub run registration is
|
|
525
|
+
# asynchronous, so retry at most five times and log every attempt.
|
|
526
|
+
RUN_ID=""
|
|
527
|
+
for ATTEMPT in 1 2 3 4 5; do
|
|
528
|
+
RUN_ID=$(gh run list --workflow ci.yml --event push --commit "$RELEASE_SHA" \
|
|
529
|
+
--limit 1 --json databaseId --jq '.[0].databaseId')
|
|
530
|
+
[ -n "$RUN_ID" ] && break
|
|
531
|
+
echo "Waiting for CI run registration ($ATTEMPT/5)" >&2
|
|
532
|
+
[ "$ATTEMPT" -eq 5 ] || sleep 60
|
|
533
|
+
done
|
|
534
|
+
test -n "$RUN_ID" || { echo "FAIL: CI run not found for release commit"; exit 1; }
|
|
535
|
+
gh run watch "$RUN_ID" --exit-status \
|
|
536
|
+
|| { echo "FAIL: release commit CI failed"; exit 1; }
|
|
537
|
+
|
|
538
|
+
# publish.yml is Ubuntu-only. Require both full CI matrix jobs before creating
|
|
539
|
+
# the tag so a green publish job cannot bypass a red macOS test.
|
|
540
|
+
for OS in ubuntu-latest macos-latest; do
|
|
541
|
+
gh run view "$RUN_ID" --json jobs \
|
|
542
|
+
--jq ".jobs[] | select(.name == \"Bats test suite ($OS)\") | .conclusion" \
|
|
543
|
+
| grep -qx success || { echo "FAIL: $OS test job not green"; exit 1; }
|
|
544
|
+
done
|
|
545
|
+
|
|
546
|
+
# Refuse to tag if either local or remote main moved while CI was running.
|
|
547
|
+
test "$(git rev-parse HEAD)" = "$RELEASE_SHA" \
|
|
548
|
+
|| { echo "FAIL: local HEAD changed during CI"; exit 1; }
|
|
549
|
+
git fetch origin main || { echo "FAIL: origin/main refresh failed"; exit 1; }
|
|
550
|
+
test "$(git rev-parse origin/main)" = "$RELEASE_SHA" \
|
|
551
|
+
|| { echo "FAIL: origin/main changed during CI"; exit 1; }
|
|
552
|
+
|
|
553
|
+
git tag vX.Y.Z "$RELEASE_SHA"
|
|
500
554
|
|
|
501
555
|
# Assert the tag before pushing it. Both checks are one line each and both
|
|
502
556
|
# have caught a real broken release.
|
|
503
|
-
test "$(git rev-parse vX.Y.Z)" = "$
|
|
504
|
-
|| { echo "FAIL: tag is not on
|
|
557
|
+
test "$(git rev-parse vX.Y.Z)" = "$RELEASE_SHA" \
|
|
558
|
+
|| { echo "FAIL: tag is not on the tested release commit"; exit 1; }
|
|
505
559
|
git show --no-patch --format=%s vX.Y.Z | grep -qx "chore: release vX.Y.Z" \
|
|
506
560
|
|| { echo "FAIL: tag is not on the chore: release commit"; exit 1; }
|
|
507
561
|
|
|
508
|
-
# Push the
|
|
509
|
-
git push origin main
|
|
562
|
+
# Push the single release tag by its full ref.
|
|
510
563
|
git push origin refs/tags/vX.Y.Z
|
|
511
564
|
```
|
|
512
565
|
|
|
566
|
+
**Why branch CI comes before the tag (v4.30.2 postmortem).** The publish
|
|
567
|
+
workflow runs only on Ubuntu and can publish while the separate macOS matrix job
|
|
568
|
+
is red. `v4.30.2` exposed this with a macOS-only DSH timing failure. A release
|
|
569
|
+
commit must therefore pass the complete Ubuntu/macOS branch workflow before its
|
|
570
|
+
tag exists; a successful publish workflow is not a substitute for green CI.
|
|
571
|
+
|
|
513
572
|
**Why the assertions (v4.19.0 postmortem).** v4.19.0 was tagged on a commit
|
|
514
573
|
that contained only a KB document and still carried `package.json` version
|
|
515
574
|
`4.18.0`; the actual release sat in the commit above it under a recycled
|
|
@@ -580,7 +639,9 @@ git push origin --delete vX.Y.Z
|
|
|
580
639
|
| 15a | Licensing gate | `npx bats tests/test_licensing.bats` | 7/7 — SPDX headers, LICENSE, NOTICE, npm `files`, manifest consistency |
|
|
581
640
|
| 16 | Tests | `git add -A kb/` if the KB changed, then `npm test` | All pass |
|
|
582
641
|
| 17 | Commit | `git commit` | Clean working tree |
|
|
583
|
-
| 18 |
|
|
584
|
-
| 18a |
|
|
585
|
-
|
|
|
586
|
-
|
|
|
642
|
+
| 18 | Push branch | `git push origin main` | Exact release commit is on `origin/main` |
|
|
643
|
+
| 18a | Full branch CI | `gh run watch "$RUN_ID" --exit-status` plus matrix job assertions | Ubuntu and macOS Bats jobs both conclude `success` |
|
|
644
|
+
| 19 | Tag | `git tag vX.Y.Z` | Tag exists only after green branch CI |
|
|
645
|
+
| 19a | Tag is on tested SHA | `test "$(git rev-parse vX.Y.Z)" = "$RELEASE_SHA"` | Exit 0 |
|
|
646
|
+
| 19b | Tag is on the release commit | `git show --no-patch --format=%s vX.Y.Z` | Reads `chore: release vX.Y.Z` |
|
|
647
|
+
| 20 | Push the single tag | `git push origin refs/tags/vX.Y.Z` | Publish CI triggered with `id-token: write`. Never `--tags`. |
|
package/llms-full.txt
CHANGED
|
@@ -8032,10 +8032,10 @@ title: "SOP: Release Preparation"
|
|
|
8032
8032
|
category: procedures
|
|
8033
8033
|
service: ai-toolkit
|
|
8034
8034
|
tags: [sop, release, version, publish, changelog, semver, provenance, sarif, ecosystem, shellcheck]
|
|
8035
|
-
version: "1.
|
|
8035
|
+
version: "1.15.0"
|
|
8036
8036
|
created: "2026-04-10"
|
|
8037
|
-
last_updated: "2026-
|
|
8038
|
-
description: "Step-by-step checklist for preparing a new ai-toolkit release — ecosystem-sync drift check, version sync, changelog, artifact regeneration, validation, and tagging. Run BEFORE every git tag. Includes mandatory Provenance, SARIF,
|
|
8037
|
+
last_updated: "2026-09-02"
|
|
8038
|
+
description: "Step-by-step checklist for preparing a new ai-toolkit release — ecosystem-sync drift check, version sync, changelog, artifact regeneration, validation, branch CI, and tagging. Run BEFORE every git tag. Includes mandatory Provenance, SARIF, checksum-pin, ShellCheck, licensing, exact-tag assertions, and a green Ubuntu/macOS branch-CI gate before any release tag is created."
|
|
8039
8039
|
---
|
|
8040
8040
|
|
|
8041
8041
|
# SOP: Release Preparation
|
|
@@ -8097,16 +8097,38 @@ python3 scripts/ecosystem_doctor.py --offline --check || { echo "STALE ecosystem
|
|
|
8097
8097
|
# 5c. Licensing gate — SPDX headers, LICENSE, NOTICE, manifest consistency
|
|
8098
8098
|
npx bats tests/test_licensing.bats || { echo "LICENSING GATE FAILED"; exit 1; }
|
|
8099
8099
|
|
|
8100
|
-
# 6. Commit
|
|
8100
|
+
# 6. Commit, push branch, and wait for the exact commit's full CI
|
|
8101
8101
|
git add -A && git commit -m "chore: release vX.Y.Z"
|
|
8102
|
-
git
|
|
8102
|
+
RELEASE_SHA=$(git rev-parse HEAD)
|
|
8103
|
+
git push origin main || { echo "FAIL: release commit push failed"; exit 1; }
|
|
8104
|
+
RUN_ID=""
|
|
8105
|
+
for ATTEMPT in 1 2 3 4 5; do
|
|
8106
|
+
RUN_ID=$(gh run list --workflow ci.yml --event push --commit "$RELEASE_SHA" \
|
|
8107
|
+
--limit 1 --json databaseId --jq '.[0].databaseId')
|
|
8108
|
+
[ -n "$RUN_ID" ] && break
|
|
8109
|
+
echo "Waiting for CI run registration ($ATTEMPT/5)" >&2
|
|
8110
|
+
[ "$ATTEMPT" -eq 5 ] || sleep 60
|
|
8111
|
+
done
|
|
8112
|
+
test -n "$RUN_ID" || { echo "FAIL: CI run not found for release commit"; exit 1; }
|
|
8113
|
+
gh run watch "$RUN_ID" --exit-status \
|
|
8114
|
+
|| { echo "FAIL: release commit CI failed"; exit 1; }
|
|
8115
|
+
for OS in ubuntu-latest macos-latest; do
|
|
8116
|
+
gh run view "$RUN_ID" --json jobs \
|
|
8117
|
+
--jq ".jobs[] | select(.name == \"Bats test suite ($OS)\") | .conclusion" \
|
|
8118
|
+
| grep -qx success || { echo "FAIL: $OS test job not green"; exit 1; }
|
|
8119
|
+
done
|
|
8120
|
+
test "$(git rev-parse HEAD)" = "$RELEASE_SHA" || { echo "FAIL: local HEAD changed during CI"; exit 1; }
|
|
8121
|
+
git fetch origin main || { echo "FAIL: origin/main refresh failed"; exit 1; }
|
|
8122
|
+
test "$(git rev-parse origin/main)" = "$RELEASE_SHA" || { echo "FAIL: origin/main changed during CI"; exit 1; }
|
|
8123
|
+
|
|
8124
|
+
# 6a. Only green branch CI authorizes tag creation
|
|
8125
|
+
git tag vX.Y.Z "$RELEASE_SHA"
|
|
8103
8126
|
|
|
8104
|
-
#
|
|
8105
|
-
test "$(git rev-parse vX.Y.Z)" = "$
|
|
8127
|
+
# 6b. Assert the tag before pushing it (v4.19.0 postmortem, Phase 7)
|
|
8128
|
+
test "$(git rev-parse vX.Y.Z)" = "$RELEASE_SHA" || { echo "FAIL: tag not on tested release commit"; exit 1; }
|
|
8106
8129
|
git show --no-patch --format=%s vX.Y.Z | grep -qx "chore: release vX.Y.Z" || { echo "FAIL: tag not on release commit"; exit 1; }
|
|
8107
8130
|
|
|
8108
|
-
#
|
|
8109
|
-
git push origin main
|
|
8131
|
+
# 6c. Push the single tag by full ref. Never --tags.
|
|
8110
8132
|
git push origin refs/tags/vX.Y.Z
|
|
8111
8133
|
```
|
|
8112
8134
|
|
|
@@ -8522,23 +8544,60 @@ git commit -m "chore: release vX.Y.Z"
|
|
|
8522
8544
|
|
|
8523
8545
|
---
|
|
8524
8546
|
|
|
8525
|
-
## Phase 7: Tag and Push
|
|
8547
|
+
## Phase 7: Push Branch, Verify CI, Tag, and Push Tag
|
|
8526
8548
|
|
|
8527
8549
|
```bash
|
|
8528
|
-
git
|
|
8550
|
+
RELEASE_SHA=$(git rev-parse HEAD)
|
|
8551
|
+
git push origin main || { echo "FAIL: release commit push failed"; exit 1; }
|
|
8552
|
+
|
|
8553
|
+
# Bind the gate to the exact release commit. GitHub run registration is
|
|
8554
|
+
# asynchronous, so retry at most five times and log every attempt.
|
|
8555
|
+
RUN_ID=""
|
|
8556
|
+
for ATTEMPT in 1 2 3 4 5; do
|
|
8557
|
+
RUN_ID=$(gh run list --workflow ci.yml --event push --commit "$RELEASE_SHA" \
|
|
8558
|
+
--limit 1 --json databaseId --jq '.[0].databaseId')
|
|
8559
|
+
[ -n "$RUN_ID" ] && break
|
|
8560
|
+
echo "Waiting for CI run registration ($ATTEMPT/5)" >&2
|
|
8561
|
+
[ "$ATTEMPT" -eq 5 ] || sleep 60
|
|
8562
|
+
done
|
|
8563
|
+
test -n "$RUN_ID" || { echo "FAIL: CI run not found for release commit"; exit 1; }
|
|
8564
|
+
gh run watch "$RUN_ID" --exit-status \
|
|
8565
|
+
|| { echo "FAIL: release commit CI failed"; exit 1; }
|
|
8566
|
+
|
|
8567
|
+
# publish.yml is Ubuntu-only. Require both full CI matrix jobs before creating
|
|
8568
|
+
# the tag so a green publish job cannot bypass a red macOS test.
|
|
8569
|
+
for OS in ubuntu-latest macos-latest; do
|
|
8570
|
+
gh run view "$RUN_ID" --json jobs \
|
|
8571
|
+
--jq ".jobs[] | select(.name == \"Bats test suite ($OS)\") | .conclusion" \
|
|
8572
|
+
| grep -qx success || { echo "FAIL: $OS test job not green"; exit 1; }
|
|
8573
|
+
done
|
|
8574
|
+
|
|
8575
|
+
# Refuse to tag if either local or remote main moved while CI was running.
|
|
8576
|
+
test "$(git rev-parse HEAD)" = "$RELEASE_SHA" \
|
|
8577
|
+
|| { echo "FAIL: local HEAD changed during CI"; exit 1; }
|
|
8578
|
+
git fetch origin main || { echo "FAIL: origin/main refresh failed"; exit 1; }
|
|
8579
|
+
test "$(git rev-parse origin/main)" = "$RELEASE_SHA" \
|
|
8580
|
+
|| { echo "FAIL: origin/main changed during CI"; exit 1; }
|
|
8581
|
+
|
|
8582
|
+
git tag vX.Y.Z "$RELEASE_SHA"
|
|
8529
8583
|
|
|
8530
8584
|
# Assert the tag before pushing it. Both checks are one line each and both
|
|
8531
8585
|
# have caught a real broken release.
|
|
8532
|
-
test "$(git rev-parse vX.Y.Z)" = "$
|
|
8533
|
-
|| { echo "FAIL: tag is not on
|
|
8586
|
+
test "$(git rev-parse vX.Y.Z)" = "$RELEASE_SHA" \
|
|
8587
|
+
|| { echo "FAIL: tag is not on the tested release commit"; exit 1; }
|
|
8534
8588
|
git show --no-patch --format=%s vX.Y.Z | grep -qx "chore: release vX.Y.Z" \
|
|
8535
8589
|
|| { echo "FAIL: tag is not on the chore: release commit"; exit 1; }
|
|
8536
8590
|
|
|
8537
|
-
# Push the
|
|
8538
|
-
git push origin main
|
|
8591
|
+
# Push the single release tag by its full ref.
|
|
8539
8592
|
git push origin refs/tags/vX.Y.Z
|
|
8540
8593
|
```
|
|
8541
8594
|
|
|
8595
|
+
**Why branch CI comes before the tag (v4.30.2 postmortem).** The publish
|
|
8596
|
+
workflow runs only on Ubuntu and can publish while the separate macOS matrix job
|
|
8597
|
+
is red. `v4.30.2` exposed this with a macOS-only DSH timing failure. A release
|
|
8598
|
+
commit must therefore pass the complete Ubuntu/macOS branch workflow before its
|
|
8599
|
+
tag exists; a successful publish workflow is not a substitute for green CI.
|
|
8600
|
+
|
|
8542
8601
|
**Why the assertions (v4.19.0 postmortem).** v4.19.0 was tagged on a commit
|
|
8543
8602
|
that contained only a KB document and still carried `package.json` version
|
|
8544
8603
|
`4.18.0`; the actual release sat in the commit above it under a recycled
|
|
@@ -8609,10 +8668,12 @@ git push origin --delete vX.Y.Z
|
|
|
8609
8668
|
| 15a | Licensing gate | `npx bats tests/test_licensing.bats` | 7/7 — SPDX headers, LICENSE, NOTICE, npm `files`, manifest consistency |
|
|
8610
8669
|
| 16 | Tests | `git add -A kb/` if the KB changed, then `npm test` | All pass |
|
|
8611
8670
|
| 17 | Commit | `git commit` | Clean working tree |
|
|
8612
|
-
| 18 |
|
|
8613
|
-
| 18a |
|
|
8614
|
-
|
|
|
8615
|
-
|
|
|
8671
|
+
| 18 | Push branch | `git push origin main` | Exact release commit is on `origin/main` |
|
|
8672
|
+
| 18a | Full branch CI | `gh run watch "$RUN_ID" --exit-status` plus matrix job assertions | Ubuntu and macOS Bats jobs both conclude `success` |
|
|
8673
|
+
| 19 | Tag | `git tag vX.Y.Z` | Tag exists only after green branch CI |
|
|
8674
|
+
| 19a | Tag is on tested SHA | `test "$(git rev-parse vX.Y.Z)" = "$RELEASE_SHA"` | Exit 0 |
|
|
8675
|
+
| 19b | Tag is on the release commit | `git show --no-patch --format=%s vX.Y.Z` | Reads `chore: release vX.Y.Z` |
|
|
8676
|
+
| 20 | Push the single tag | `git push origin refs/tags/vX.Y.Z` | Publish CI triggered with `id-token: write`. Never `--tags`. |
|
|
8616
8677
|
|
|
8617
8678
|
---
|
|
8618
8679
|
|
package/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softspark/ai-toolkit",
|
|
3
|
-
"version": "4.30.
|
|
3
|
+
"version": "4.30.3",
|
|
4
4
|
"description": "AI coding toolkit: 109 skills, 44 agents, 14 developer-tool integrations, recoverable native tool-output filtering, Claude Chat/Cowork export, safety constitution, SARIF audit, and signed npm provenance.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
package/scripts/doctor.py
CHANGED
|
@@ -124,7 +124,7 @@ SEMVER_OUTPUT = re.compile(
|
|
|
124
124
|
rf"(?:\.{_SEMVER_PRERELEASE_IDENTIFIER})*)?"
|
|
125
125
|
rf"(?:\+{_SEMVER_BUILD_IDENTIFIER}"
|
|
126
126
|
rf"(?:\.{_SEMVER_BUILD_IDENTIFIER})*)?)"
|
|
127
|
-
r"(?![0-9A-Za-z
|
|
127
|
+
r"(?![0-9A-Za-z+-]|\.(?!\s|$))"
|
|
128
128
|
)
|
|
129
129
|
VERSION_LIKE_OUTPUT = re.compile(r"(?<![0-9])[0-9]+\.[0-9]+\.[^\s,;()]+")
|
|
130
130
|
|