@softspark/ai-toolkit 2.7.3 → 2.9.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/AGENTS.md +30 -30
- package/CHANGELOG.md +30 -0
- package/README.md +4 -2
- package/app/.claude-plugin/plugin.json +1 -1
- package/app/hooks/commit-quality.sh +11 -8
- package/app/hooks/quality-check.sh +5 -1
- package/app/hooks/session-start.sh +7 -3
- package/app/skills/api-patterns/SKILL.md +1 -1
- package/app/skills/app-builder/SKILL.md +1 -1
- package/app/skills/architecture-decision/SKILL.md +1 -1
- package/app/skills/ci-cd-patterns/SKILL.md +1 -1
- package/app/skills/clean-code/SKILL.md +1 -1
- package/app/skills/csharp-patterns/SKILL.md +1 -1
- package/app/skills/database-patterns/SKILL.md +1 -1
- package/app/skills/debugging-tactics/SKILL.md +1 -1
- package/app/skills/design-engineering/SKILL.md +1 -1
- package/app/skills/docker-devops/SKILL.md +1 -1
- package/app/skills/documentation-standards/SKILL.md +1 -1
- package/app/skills/ecommerce-patterns/SKILL.md +1 -1
- package/app/skills/flutter-patterns/SKILL.md +1 -1
- package/app/skills/git-mastery/SKILL.md +1 -1
- package/app/skills/hive-mind/SKILL.md +1 -1
- package/app/skills/java-patterns/SKILL.md +1 -1
- package/app/skills/kotlin-patterns/SKILL.md +1 -1
- package/app/skills/mcp-patterns/SKILL.md +1 -1
- package/app/skills/migration-patterns/SKILL.md +1 -1
- package/app/skills/observability-patterns/SKILL.md +1 -1
- package/app/skills/performance-profiling/SKILL.md +1 -1
- package/app/skills/plan-writing/SKILL.md +1 -1
- package/app/skills/rag-patterns/SKILL.md +1 -1
- package/app/skills/research-mastery/SKILL.md +1 -1
- package/app/skills/ruby-patterns/SKILL.md +1 -1
- package/app/skills/rust-patterns/SKILL.md +1 -1
- package/app/skills/security-patterns/SKILL.md +1 -1
- package/app/skills/swift-patterns/SKILL.md +1 -1
- package/app/skills/testing-patterns/SKILL.md +1 -1
- package/app/skills/typescript-patterns/SKILL.md +1 -1
- package/bin/ai-toolkit.js +1 -1
- package/kb/procedures/release-preparation-sop.md +72 -15
- package/kb/procedures/release-verification-sop.md +82 -7
- package/llms-full.txt +184 -52
- package/manifest.json +1 -1
- package/package.json +3 -4
- package/scripts/add_rule.py +1 -1
- package/scripts/audit_skills.py +246 -6
- package/scripts/config_resolver.py +8 -2
- package/scripts/hook_sources.py +30 -3
- package/scripts/inject_hook_cli.py +1 -1
- package/scripts/install_steps/ai_tools.py +10 -2
- package/scripts/install_steps/hooks.py +1 -1
- package/scripts/install_steps/markers.py +2 -2
- package/scripts/rule_sources.py +30 -3
package/bin/ai-toolkit.js
CHANGED
|
@@ -368,11 +368,11 @@ function handleAddRule(args) {
|
|
|
368
368
|
process.exit(1);
|
|
369
369
|
}
|
|
370
370
|
// Pass URLs through directly (don't resolve as filesystem path)
|
|
371
|
-
const isUrl = ruleFile.startsWith('https://') || ruleFile.startsWith('http://');
|
|
372
371
|
if (ruleFile.startsWith('http://')) {
|
|
373
372
|
console.error('Error: only HTTPS URLs are supported. Use https:// for security.');
|
|
374
373
|
process.exit(1);
|
|
375
374
|
}
|
|
375
|
+
const isUrl = ruleFile.startsWith('https://');
|
|
376
376
|
const absRuleFile = isUrl ? ruleFile : path.resolve(CWD, ruleFile);
|
|
377
377
|
const ruleName = args[1];
|
|
378
378
|
run(scriptPath('add_rule.py'), ruleName ? [absRuleFile, ruleName] : [absRuleFile]);
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
title: "SOP: Release Preparation"
|
|
3
3
|
category: procedures
|
|
4
4
|
service: ai-toolkit
|
|
5
|
-
tags: [sop, release, version, publish, changelog, semver]
|
|
6
|
-
version: "1.
|
|
5
|
+
tags: [sop, release, version, publish, changelog, semver, provenance, sarif]
|
|
6
|
+
version: "1.7.0"
|
|
7
7
|
created: "2026-04-10"
|
|
8
|
-
last_updated: "2026-04-
|
|
9
|
-
description: "Step-by-step checklist for preparing a new ai-toolkit release — version sync, changelog, artifact regeneration, validation, and tagging. Run BEFORE every git tag."
|
|
8
|
+
last_updated: "2026-04-18"
|
|
9
|
+
description: "Step-by-step checklist for preparing a new ai-toolkit release — version sync, changelog, artifact regeneration, validation, and tagging. Run BEFORE every git tag. Includes mandatory Provenance, SARIF, and checksum-pin checks added in v2.8.0."
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
# SOP: Release Preparation
|
|
@@ -42,8 +42,13 @@ python3 scripts/generate_codex_rules.py .
|
|
|
42
42
|
python3 scripts/generate_llms_txt.py > llms.txt
|
|
43
43
|
python3 scripts/generate_llms_txt.py --full > llms-full.txt
|
|
44
44
|
|
|
45
|
-
# 5. Validate + audit + test
|
|
46
|
-
python3 scripts/validate.py --strict && python3 scripts/audit_skills.py --ci && npm test
|
|
45
|
+
# 5. Validate + audit + SARIF + test
|
|
46
|
+
python3 scripts/validate.py --strict && python3 scripts/audit_skills.py --ci && python3 scripts/audit_skills.py --sarif > /tmp/audit.sarif && npm test
|
|
47
|
+
|
|
48
|
+
# 5a. Supply-chain standard (v2.8.0+) — non-negotiable
|
|
49
|
+
grep -q -- '--provenance' .github/workflows/publish.yml || { echo "MISSING --provenance"; exit 1; }
|
|
50
|
+
grep -q 'id-token: write' .github/workflows/publish.yml || { echo "MISSING id-token: write"; exit 1; }
|
|
51
|
+
python3 scripts/audit_skills.py --permissions # review Bash/Write/Edit footprint
|
|
47
52
|
|
|
48
53
|
# 6. Commit + tag + push
|
|
49
54
|
git add -A && git commit -m "chore: release vX.Y.Z"
|
|
@@ -200,17 +205,21 @@ Run the full quality gate:
|
|
|
200
205
|
```bash
|
|
201
206
|
python3 scripts/validate.py --strict
|
|
202
207
|
python3 scripts/audit_skills.py --ci
|
|
208
|
+
python3 scripts/audit_skills.py --sarif > audit.sarif # MANDATORY — GHAS ingest
|
|
209
|
+
python3 scripts/audit_skills.py --permissions # review Bash/Write/Edit footprint
|
|
203
210
|
npm test
|
|
204
211
|
```
|
|
205
212
|
|
|
206
213
|
**Expected results:**
|
|
207
214
|
- `validate.py`: `Errors: 0 | Warnings: 0 | VALIDATION PASSED`
|
|
208
|
-
- `audit_skills.py`: `HIGH: 0 | WARN: 0` (INFO is acceptable)
|
|
215
|
+
- `audit_skills.py --ci`: `HIGH: 0 | WARN: 0` (INFO is acceptable)
|
|
216
|
+
- `audit_skills.py --sarif`: valid JSON, non-empty `runs[0].tool.driver.rules`
|
|
217
|
+
- `audit_skills.py --permissions`: review `Skills with Bash + Write + Edit` list — any newly-added skill with broad access MUST be justified in the CHANGELOG entry
|
|
209
218
|
- `npm test`: `1..N` with zero `not ok`
|
|
210
219
|
|
|
211
220
|
**One-liner:**
|
|
212
221
|
```bash
|
|
213
|
-
python3 scripts/validate.py --strict && python3 scripts/audit_skills.py --ci && npm test
|
|
222
|
+
python3 scripts/validate.py --strict && python3 scripts/audit_skills.py --ci && python3 scripts/audit_skills.py --sarif > audit.sarif && npm test
|
|
214
223
|
```
|
|
215
224
|
|
|
216
225
|
**If tests fail:** Fix the issue, do NOT skip. Common failures:
|
|
@@ -218,6 +227,48 @@ python3 scripts/validate.py --strict && python3 scripts/audit_skills.py --ci &&
|
|
|
218
227
|
- Missing frontmatter → add to new KB docs
|
|
219
228
|
- Broken symlink → `ai-toolkit doctor --fix`
|
|
220
229
|
|
|
230
|
+
### Phase 5a: Supply-Chain Hardening Verification (v2.8.0+)
|
|
231
|
+
|
|
232
|
+
These checks enforce the security standard introduced in v2.8.0. Do NOT tag a release until all pass.
|
|
233
|
+
|
|
234
|
+
**1. Publish workflow emits provenance:**
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
grep -E '\-\-provenance|id-token: write' .github/workflows/publish.yml
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
- [ ] Both markers present (`--provenance` flag + `id-token: write` permission)
|
|
241
|
+
- [ ] Any PR that changes `publish.yml` REQUIRES an approved security review
|
|
242
|
+
|
|
243
|
+
**2. URL-sourced rules and hooks are checksum-pinned:**
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
# On a machine that has consumed URL rules/hooks at least once:
|
|
247
|
+
jq 'to_entries | map(select(.value.url != null and (.value.sha256 // "" | length) == 0))' ~/.softspark/ai-toolkit/rules/sources.json
|
|
248
|
+
jq 'to_entries | map(select(.value.url != null and (.value.sha256 // "" | length) == 0))' ~/.softspark/ai-toolkit/hooks/external/sources.json
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
- [ ] Both queries return empty arrays (every URL entry has a `sha256`)
|
|
252
|
+
- [ ] If not, run `ai-toolkit update` to backfill missing hashes before tagging
|
|
253
|
+
|
|
254
|
+
**3. Audit SARIF output is well-formed:**
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
python3 scripts/audit_skills.py --sarif | python3 -c "import json, sys; d=json.load(sys.stdin); assert d['version']=='2.1.0' and d['runs'][0]['tool']['driver']['name']; print('SARIF OK')"
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
- [ ] Prints `SARIF OK`
|
|
261
|
+
- [ ] If the script ever grows new rule classes, extend the SARIF `rules[]` coverage before releasing
|
|
262
|
+
|
|
263
|
+
**4. Strict-pin mode passes on CI** (optional, recommended for stable branches):
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
AI_TOOLKIT_STRICT_PIN=1 ai-toolkit update --dry-run
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
- [ ] Exit 0, no `CHECKSUM CHANGED` line
|
|
270
|
+
- [ ] Any unexpected upstream change blocks the release until explicitly approved
|
|
271
|
+
|
|
221
272
|
---
|
|
222
273
|
|
|
223
274
|
## Phase 6: Commit
|
|
@@ -250,10 +301,12 @@ git push origin main --tags
|
|
|
250
301
|
This triggers `.github/workflows/publish.yml` which:
|
|
251
302
|
1. Runs `validate.py --strict`
|
|
252
303
|
2. Runs `npm test`
|
|
253
|
-
3. Publishes to npm as `@softspark/ai-toolkit@X.Y.Z`
|
|
304
|
+
3. Publishes to npm as `@softspark/ai-toolkit@X.Y.Z` with `--provenance` (SLSA v1 build attestation)
|
|
305
|
+
|
|
306
|
+
**Provenance is non-negotiable.** If `id-token: write` permission or the `--provenance` flag is missing from `publish.yml`, fix it BEFORE tagging — an unsigned release is a regression against the v2.8.0 standard.
|
|
254
307
|
|
|
255
308
|
**After CI completes:** Run the [Release Verification SOP](release-verification-sop.md)
|
|
256
|
-
to smoke-test the published package.
|
|
309
|
+
to smoke-test the published package AND verify the provenance attestation landed on npm.
|
|
257
310
|
|
|
258
311
|
---
|
|
259
312
|
|
|
@@ -288,8 +341,12 @@ git push origin --delete vX.Y.Z
|
|
|
288
341
|
| 7 | CHANGELOG.md | Add release entry | Entry exists for vX.Y.Z |
|
|
289
342
|
| 8 | Regenerate artifacts | `generate_agents_md.py`, `generate_codex_rules.py`, `generate_llms_txt.py` | No unexpected diff |
|
|
290
343
|
| 9 | Validate | `validate.py --strict` | 0 errors, 0 warnings |
|
|
291
|
-
| 10 | Security audit | `audit_skills.py --ci` | 0 HIGH |
|
|
292
|
-
| 11 |
|
|
293
|
-
| 12 |
|
|
294
|
-
| 13 |
|
|
295
|
-
| 14 |
|
|
344
|
+
| 10 | Security audit (CI mode) | `audit_skills.py --ci` | 0 HIGH |
|
|
345
|
+
| 11 | Security audit (SARIF) | `audit_skills.py --sarif` | Valid SARIF 2.1.0 JSON |
|
|
346
|
+
| 12 | Per-skill permissions | `audit_skills.py --permissions` | New broad-access skills justified in CHANGELOG |
|
|
347
|
+
| 13 | Provenance flag check | `grep -- '--provenance' .github/workflows/publish.yml` | Present |
|
|
348
|
+
| 14 | Checksum-pin backfill | `sources.json` entries all have `sha256` | No unpinned URL sources |
|
|
349
|
+
| 15 | Tests | `npm test` | All pass |
|
|
350
|
+
| 16 | Commit | `git commit` | Clean working tree |
|
|
351
|
+
| 17 | Tag | `git tag vX.Y.Z` | Tag exists |
|
|
352
|
+
| 18 | Push | `git push origin main --tags` | CI triggered with `id-token: write` |
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
title: "SOP: Release Verification"
|
|
3
3
|
category: procedures
|
|
4
4
|
service: ai-toolkit
|
|
5
|
-
tags: [sop, verification, release, smoke-test, install, update, qa]
|
|
6
|
-
version: "1.
|
|
5
|
+
tags: [sop, verification, release, smoke-test, install, update, qa, provenance, sarif]
|
|
6
|
+
version: "1.2.0"
|
|
7
7
|
created: "2026-04-08"
|
|
8
|
-
last_updated: "2026-04-
|
|
9
|
-
description: "End-to-end smoke test after installing or updating @softspark/ai-toolkit — verifies CLI, install, doctor, validation, tests, and
|
|
8
|
+
last_updated: "2026-04-18"
|
|
9
|
+
description: "End-to-end smoke test after installing or updating @softspark/ai-toolkit — verifies CLI, install, doctor, validation, tests, eject, npm provenance attestation, SARIF audit, and per-skill permissions. Reflects the v2.8.0 supply-chain standard."
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
# SOP: Release Verification
|
|
@@ -31,7 +31,7 @@ Verifies all critical paths from the user's perspective.
|
|
|
31
31
|
|
|
32
32
|
## Quick Checklist (TL;DR)
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
13 commands — if all pass, the release is ready:
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
37
|
# Pre-commit (Phase 0)
|
|
@@ -47,6 +47,11 @@ ai-toolkit status # 7. Status OK?
|
|
|
47
47
|
ai-toolkit doctor # 8. Health check passed?
|
|
48
48
|
ai-toolkit install --dry-run # 9. Global install OK?
|
|
49
49
|
python3 scripts/audit_skills.py --ci # 10. Security audit clean?
|
|
50
|
+
|
|
51
|
+
# Supply-chain verification (Phase 8, v2.8.0+)
|
|
52
|
+
python3 scripts/audit_skills.py --sarif | python3 -c "import json,sys; assert json.load(sys.stdin)['version']=='2.1.0'; print('SARIF OK')" # 11. SARIF 2.1.0 well-formed?
|
|
53
|
+
python3 scripts/audit_skills.py --permissions | head -30 # 12. Broad-access skills reviewed?
|
|
54
|
+
npm view @softspark/ai-toolkit@X.Y.Z --json | python3 -c "import json,sys; d=json.load(sys.stdin); assert d['dist']['attestations']['provenance']['predicateType']=='https://slsa.dev/provenance/v1'; print('PROVENANCE OK')" # 13. Provenance attested on npm?
|
|
50
55
|
```
|
|
51
56
|
|
|
52
57
|
---
|
|
@@ -230,6 +235,72 @@ cd - && rm -rf /tmp/ai-toolkit-eject-test
|
|
|
230
235
|
- [ ] Skills copied as real directories
|
|
231
236
|
- [ ] Rules inlined into CLAUDE.md
|
|
232
237
|
- [ ] constitution.md and ARCHITECTURE.md copied
|
|
238
|
+
- [ ] `output-styles/` directory present (v2.7.1+)
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Phase 8: Supply-Chain Verification (2 min, v2.8.0+)
|
|
243
|
+
|
|
244
|
+
These checks enforce the v2.8.0 security standard on a freshly-published release. Run AFTER the `publish.yml` workflow completes on the tag.
|
|
245
|
+
|
|
246
|
+
### 8.1 Provenance attestation on npm
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
VERSION="X.Y.Z" # the tag just published
|
|
250
|
+
npm view "@softspark/ai-toolkit@${VERSION}" --json \
|
|
251
|
+
| python3 -c "import json, sys; d=json.load(sys.stdin); att=d['dist'].get('attestations', {}); assert att.get('provenance', {}).get('predicateType') == 'https://slsa.dev/provenance/v1', f'NO PROVENANCE for {d[\"version\"]}'; print(f'PROVENANCE OK: {att[\"url\"]}')"
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Verify:**
|
|
255
|
+
- [ ] Exit 0 and prints `PROVENANCE OK: https://registry.npmjs.org/...`
|
|
256
|
+
- [ ] `https://www.npmjs.com/package/@softspark/ai-toolkit/v/${VERSION}` shows the green "Provenance" badge
|
|
257
|
+
|
|
258
|
+
**If provenance is missing:** the `publish.yml` ran without `id-token: write` or `--provenance`. Restore them and cut a patch release — a silently unsigned publish is a regression against the v2.8.0 standard.
|
|
259
|
+
|
|
260
|
+
### 8.2 Audit SARIF output (for GHAS ingest)
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
python3 scripts/audit_skills.py --sarif > /tmp/audit.sarif
|
|
264
|
+
python3 -c "import json; d=json.load(open('/tmp/audit.sarif')); assert d['version']=='2.1.0' and d['runs'][0]['tool']['driver']['name']=='ai-toolkit-audit-skills'; print(f'SARIF OK: {len(d[\"runs\"][0][\"results\"])} results across {len(d[\"runs\"][0][\"tool\"][\"driver\"][\"rules\"])} rules')"
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Verify:**
|
|
268
|
+
- [ ] Valid SARIF 2.1.0
|
|
269
|
+
- [ ] In the publishing repo, the CI job uploads `audit.sarif` via `github/codeql-action/upload-sarif@v3` so findings appear in the Security tab
|
|
270
|
+
|
|
271
|
+
### 8.3 Per-skill permissions report
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
python3 scripts/audit_skills.py --permissions | head -40
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
**Verify:**
|
|
278
|
+
- [ ] Bash skill count has NOT jumped unexpectedly since the previous release
|
|
279
|
+
- [ ] Any newly added entry under `Skills with Bash + Write + Edit` matches a CHANGELOG bullet that justifies the broad scope
|
|
280
|
+
- [ ] JSON form (`--permissions --json`) is available for automated drift dashboards
|
|
281
|
+
|
|
282
|
+
### 8.4 URL-sourced rules/hooks are checksum-pinned
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
jq '.rules // .hooks // {}' ~/.softspark/ai-toolkit/rules/sources.json 2>/dev/null \
|
|
286
|
+
| python3 -c "import json, sys; d=json.load(sys.stdin) or {}; bad=[n for n,v in d.items() if v.get('url') and not v.get('sha256')]; assert not bad, f'UNPINNED: {bad}'; print(f'RULE PIN OK: {len(d)} URL rules, all with sha256')"
|
|
287
|
+
jq '.hooks // {}' ~/.softspark/ai-toolkit/hooks/external/sources.json 2>/dev/null \
|
|
288
|
+
| python3 -c "import json, sys; d=json.load(sys.stdin) or {}; bad=[n for n,v in d.items() if v.get('url') and not v.get('sha256')]; assert not bad, f'UNPINNED: {bad}'; print(f'HOOK PIN OK: {len(d)} URL hooks, all with sha256')"
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**Verify:**
|
|
292
|
+
- [ ] Both commands print `... PIN OK`
|
|
293
|
+
- [ ] If any entry is unpinned, the `register_url_source()` call missed passing `content=` — fix the call-site and retag
|
|
294
|
+
|
|
295
|
+
### 8.5 Strict-pin smoke test (optional but recommended)
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
AI_TOOLKIT_STRICT_PIN=1 ai-toolkit update --dry-run
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
**Verify:**
|
|
302
|
+
- [ ] Exit 0, no `CHECKSUM CHANGED` line
|
|
303
|
+
- [ ] If a checksum change was intentional (e.g. upstream rule update), document it in the CHANGELOG entry before tagging
|
|
233
304
|
|
|
234
305
|
---
|
|
235
306
|
|
|
@@ -279,7 +350,11 @@ ai-toolkit eject /tmp/test # retry
|
|
|
279
350
|
| Health | `doctor`: 0 errors, 0 warnings, PASSED |
|
|
280
351
|
| Install | `--dry-run` correct counts, `--local` all configs |
|
|
281
352
|
| Quality | `validate.py --strict`: PASSED |
|
|
282
|
-
| Security | `audit_skills.py --ci`: 0 HIGH |
|
|
353
|
+
| Security (baseline) | `audit_skills.py --ci`: 0 HIGH |
|
|
354
|
+
| Security (SARIF) | `audit_skills.py --sarif`: valid SARIF 2.1.0 with non-empty rules array |
|
|
355
|
+
| Security (permissions) | `audit_skills.py --permissions`: broad-access skills unchanged or justified in CHANGELOG |
|
|
356
|
+
| Supply chain | `dist.attestations.provenance.predicateType == https://slsa.dev/provenance/v1` on npm |
|
|
357
|
+
| Supply chain | All `sources.json` URL entries carry a `sha256`; `AI_TOOLKIT_STRICT_PIN=1 ai-toolkit update --dry-run` passes |
|
|
283
358
|
| Tests | `npm test`: N/N passed, 0 failures |
|
|
284
|
-
| Eject | Standalone
|
|
359
|
+
| Eject | Standalone `.claude/` with real files AND `output-styles/` directory |
|
|
285
360
|
| Guards | Destructive commands blocked |
|