@softspark/ai-toolkit 4.25.0 → 4.26.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/CHANGELOG.md +75 -0
- package/README.md +15 -12
- package/app/.claude-plugin/plugin.json +1 -1
- package/app/skills/cve-scan/scripts/cve_scan.py +16 -2
- package/benchmarks/ecosystem-doctor-snapshot.json +14 -14
- package/bin/ai-toolkit.js +60 -0
- package/kb/best-practices/README.md +1 -0
- package/kb/howto/README.md +1 -0
- package/kb/procedures/post-release-testing-sop.md +20 -11
- package/kb/reference/enterprise-config-guide.md +1 -1
- package/kb/troubleshooting/README.md +1 -0
- package/llms-full.txt +24 -12
- package/manifest.json +1 -1
- package/package.json +1 -1
- package/scripts/_common.py +27 -0
- package/scripts/check_deps.py +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,81 @@ Versioning follows [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## v4.26.0 — Python floor is declared and enforced (2026-08-21)
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Python preflight in the CLI.** `bin/ai-toolkit.js` now verifies `python3`
|
|
15
|
+
exists and reports at least 3.11 before spawning any script, and prints a
|
|
16
|
+
platform-specific fix (`brew install python@3.13` on macOS) instead of a
|
|
17
|
+
traceback from deep inside `scripts/`. The check is lazy and memoized, so
|
|
18
|
+
`help` and `--version` still run without a Python interpreter.
|
|
19
|
+
- **Matching floor check in `scripts/_common.py`.** Every entry point imports
|
|
20
|
+
`_common` first, so `python3 scripts/install.py` run directly fails with the
|
|
21
|
+
same message rather than a `TypeError` from whichever module happens to use
|
|
22
|
+
3.11+ syntax.
|
|
23
|
+
- **CI import sweep.** The `python-syntax` job now runs on a `['3.11', '3.13']`
|
|
24
|
+
matrix and imports every module under `scripts/` on each. `py_compile` only
|
|
25
|
+
catches syntax, which is exactly why a 3.10-only construct shipped: version-
|
|
26
|
+
gated runtime features surface on import, not on compile.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- **`ai-toolkit update --local` crashed on macOS system Python.** `/usr/bin/python3`
|
|
31
|
+
is 3.9 on every Mac, and `scripts/mcp_editors.py` uses
|
|
32
|
+
`@dataclass(frozen=True, slots=True)` (3.10+), so the install path died with
|
|
33
|
+
`TypeError: dataclass() got an unexpected keyword argument 'slots'` while
|
|
34
|
+
importing `install_steps/ai_tools.py`. The interpreter is now rejected up
|
|
35
|
+
front with instructions.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- **`scripts/check_deps.py` declares Python >= 3.11**, up from a `min_version`
|
|
40
|
+
of `3.8` that never matched what the scripts actually needed, and its reason
|
|
41
|
+
string calls out the macOS 3.9 trap.
|
|
42
|
+
- **Requirements are documented.** README gained a Requirements note above the
|
|
43
|
+
install snippet; `CLAUDE.md` records the three places the floor is declared
|
|
44
|
+
(`bin/ai-toolkit.js`, `scripts/_common.py`, `scripts/check_deps.py`) and the
|
|
45
|
+
CI matrix that guards it.
|
|
46
|
+
|
|
47
|
+
### Ecosystem
|
|
48
|
+
|
|
49
|
+
- Snapshot refreshed: 11 tools drifted, all class A (content reworded, no
|
|
50
|
+
heading delta). Claude Code 2.1.235 → 2.1.238 and Codex CLI 0.147.0 → 0.148.0
|
|
51
|
+
are upstream patch bumps with no new surface, so no generator changed.
|
|
52
|
+
|
|
53
|
+
### Tests
|
|
54
|
+
|
|
55
|
+
- Three CLI regression tests: a stale `python3` shim exits 1 with the version
|
|
56
|
+
message, a missing `python3` exits 1 instead of crashing, and `help` still
|
|
57
|
+
works with no interpreter on PATH. Test count: 1637 → 1640.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## v4.25.1 — npm advisories count again (2026-08-19)
|
|
62
|
+
|
|
63
|
+
### Fixed
|
|
64
|
+
|
|
65
|
+
- **`cve-scan` reported zero findings for a vulnerable npm project.** npm audit
|
|
66
|
+
can return the legacy `advisories` object as well as the current
|
|
67
|
+
`vulnerabilities` object. The scanner parsed only the latter, so five real
|
|
68
|
+
lodash advisories remained trapped in `raw_output` while `total_findings` was
|
|
69
|
+
zero and the process exited successfully. Both formats are now normalized,
|
|
70
|
+
and HIGH advisories restore the documented non-zero exit code.
|
|
71
|
+
|
|
72
|
+
### Changed
|
|
73
|
+
|
|
74
|
+
- **The published-package scanner smoke uses real per-scanner fixtures and
|
|
75
|
+
flags.** It now includes healthcare patterns and a deliberately vulnerable
|
|
76
|
+
locked npm dependency, invokes `cve-scan` with `--json`, and treats raw npm
|
|
77
|
+
advisories with no normalized findings as a parser failure.
|
|
78
|
+
|
|
79
|
+
### Tests
|
|
80
|
+
|
|
81
|
+
- Added a public-CLI regression test with a stubbed legacy npm audit response;
|
|
82
|
+
it asserts normalized severity, installed version, CVE, fixed range, finding
|
|
83
|
+
count, and exit status.
|
|
84
|
+
|
|
10
85
|
## v4.25.0 — editor-native integrations catch up (2026-08-19)
|
|
11
86
|
|
|
12
87
|
### Added
|
package/README.md
CHANGED
|
@@ -6,20 +6,19 @@
|
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](app/skills/)
|
|
8
8
|
[](app/agents/)
|
|
9
|
-
[](tests/)
|
|
10
10
|
|
|
11
|
-
## What's New in v4.
|
|
11
|
+
## What's New in v4.26.0
|
|
12
12
|
|
|
13
|
-
**v4.
|
|
13
|
+
**v4.26.0** declares and enforces the Python floor the scripts already needed:
|
|
14
14
|
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
and
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
plugin contracts, with transactional symlink protections across new writers.
|
|
15
|
+
- `ai-toolkit` now checks `python3` before running anything and requires 3.11+.
|
|
16
|
+
- macOS `/usr/bin/python3` is 3.9, which used to crash `update --local` with a
|
|
17
|
+
raw `dataclass() got an unexpected keyword argument 'slots'` traceback. You
|
|
18
|
+
now get the version, the requirement, and `brew install python@3.13`.
|
|
19
|
+
- `python3 scripts/*.py` run directly fails the same way, via `_common.py`.
|
|
20
|
+
- CI runs the syntax check plus a full import sweep on both 3.11 and 3.13, so a
|
|
21
|
+
version-gated runtime feature cannot slip through `py_compile` again.
|
|
23
22
|
|
|
24
23
|
See [CHANGELOG.md](CHANGELOG.md) for full history.
|
|
25
24
|
|
|
@@ -42,6 +41,10 @@ See [CHANGELOG.md](CHANGELOG.md) for full history.
|
|
|
42
41
|
|
|
43
42
|
## Install
|
|
44
43
|
|
|
44
|
+
**Requirements:** Node.js >= 18 and Python >= 3.11.
|
|
45
|
+
|
|
46
|
+
> **macOS:** `/usr/bin/python3` is Python 3.9 and will not run the toolkit. Install a supported one with `brew install python@3.13` and make sure `which python3` no longer points at `/usr/bin/python3`.
|
|
47
|
+
|
|
45
48
|
```bash
|
|
46
49
|
# Option A: install globally (once per machine)
|
|
47
50
|
npm install -g @softspark/ai-toolkit
|
|
@@ -185,7 +188,7 @@ ai-toolkit/
|
|
|
185
188
|
│ └── ARCHITECTURE.md # Full system design
|
|
186
189
|
├── kb/ # Reference docs, procedures, plans
|
|
187
190
|
├── scripts/ # Validation, install, evaluation scripts
|
|
188
|
-
├── tests/ # Bats and Python test suite (
|
|
191
|
+
├── tests/ # Bats and Python test suite (1640 tests)
|
|
189
192
|
└── CHANGELOG.md
|
|
190
193
|
```
|
|
191
194
|
|
|
@@ -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.
|
|
6
|
+
"version": "4.26.0",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "SoftSpark",
|
|
9
9
|
"url": "https://github.com/softspark"
|
|
@@ -9,7 +9,6 @@ Stdlib only. No external dependencies.
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
import json
|
|
12
|
-
import os
|
|
13
12
|
import shutil
|
|
14
13
|
import subprocess
|
|
15
14
|
import sys
|
|
@@ -141,7 +140,7 @@ def run_audit(eco: dict, root: Path, fix: bool = False) -> dict:
|
|
|
141
140
|
except FileNotFoundError:
|
|
142
141
|
result["error"] = f"Tool '{eco['tool']}' not found in PATH"
|
|
143
142
|
except subprocess.TimeoutExpired:
|
|
144
|
-
result["error"] =
|
|
143
|
+
result["error"] = "Audit command timed out after 120s"
|
|
145
144
|
|
|
146
145
|
return result
|
|
147
146
|
|
|
@@ -168,6 +167,21 @@ def parse_npm_audit(raw: str) -> list[dict]:
|
|
|
168
167
|
"url": via.get("url", ""),
|
|
169
168
|
"fixed_in": info.get("fixAvailable", {}).get("version", "unknown") if isinstance(info.get("fixAvailable"), dict) else "unknown",
|
|
170
169
|
})
|
|
170
|
+
|
|
171
|
+
for advisory in data.get("advisories", {}).values():
|
|
172
|
+
installed_versions = sorted({
|
|
173
|
+
finding.get("version", "unknown")
|
|
174
|
+
for finding in advisory.get("findings", [])
|
|
175
|
+
})
|
|
176
|
+
findings.append({
|
|
177
|
+
"severity": advisory.get("severity", "unknown").upper(),
|
|
178
|
+
"package": advisory.get("module_name", "unknown"),
|
|
179
|
+
"installed": ", ".join(installed_versions) or "unknown",
|
|
180
|
+
"cve": advisory.get("cves", []) or [advisory.get("github_advisory_id", "N/A")],
|
|
181
|
+
"title": advisory.get("title", "Unknown"),
|
|
182
|
+
"url": advisory.get("url", ""),
|
|
183
|
+
"fixed_in": advisory.get("patched_versions", "unknown"),
|
|
184
|
+
})
|
|
171
185
|
return findings
|
|
172
186
|
|
|
173
187
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"last_run": "2026-08-
|
|
2
|
+
"last_run": "2026-08-21T08:34:52Z",
|
|
3
3
|
"schema_version": 1,
|
|
4
4
|
"tools": {
|
|
5
5
|
"aider": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"augment": {
|
|
27
|
-
"docs_hash": "
|
|
27
|
+
"docs_hash": "516d8db28cb3ec63",
|
|
28
28
|
"headings": [
|
|
29
29
|
"Admin",
|
|
30
30
|
"Auggie CLI",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
}
|
|
67
67
|
},
|
|
68
68
|
"claude-app": {
|
|
69
|
-
"docs_hash": "
|
|
69
|
+
"docs_hash": "7e06a1985d5bb822",
|
|
70
70
|
"headings": [
|
|
71
71
|
"Add global and folder instructions",
|
|
72
72
|
"Availability",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
}
|
|
108
108
|
},
|
|
109
109
|
"claude-code": {
|
|
110
|
-
"docs_hash": "
|
|
110
|
+
"docs_hash": "2b3d6b11c4be766f",
|
|
111
111
|
"headings": [
|
|
112
112
|
"Core concepts",
|
|
113
113
|
"Documentation Index",
|
|
@@ -173,10 +173,10 @@
|
|
|
173
173
|
"userConfig": false,
|
|
174
174
|
"workflows": true
|
|
175
175
|
},
|
|
176
|
-
"version": "2.1.
|
|
176
|
+
"version": "2.1.238 (Claude Code)"
|
|
177
177
|
},
|
|
178
178
|
"cline": {
|
|
179
|
-
"docs_hash": "
|
|
179
|
+
"docs_hash": "f93d3a8437c1165f",
|
|
180
180
|
"headings": [
|
|
181
181
|
"API Reference",
|
|
182
182
|
"Best Practices",
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
}
|
|
224
224
|
},
|
|
225
225
|
"codex-cli": {
|
|
226
|
-
"docs_hash": "
|
|
226
|
+
"docs_hash": "fc1c7e43bec9f748",
|
|
227
227
|
"headings": [
|
|
228
228
|
"API",
|
|
229
229
|
"API Reference",
|
|
@@ -362,10 +362,10 @@
|
|
|
362
362
|
"plugin marketplace": false,
|
|
363
363
|
"sandbox": true
|
|
364
364
|
},
|
|
365
|
-
"version": "codex-cli 0.
|
|
365
|
+
"version": "codex-cli 0.148.0"
|
|
366
366
|
},
|
|
367
367
|
"cursor": {
|
|
368
|
-
"docs_hash": "
|
|
368
|
+
"docs_hash": "2abfadb030c12d07",
|
|
369
369
|
"headings": [
|
|
370
370
|
"Agent",
|
|
371
371
|
"CLI",
|
|
@@ -397,7 +397,7 @@
|
|
|
397
397
|
}
|
|
398
398
|
},
|
|
399
399
|
"gemini-cli": {
|
|
400
|
-
"docs_hash": "
|
|
400
|
+
"docs_hash": "a2c9759e0296670d",
|
|
401
401
|
"headings": [
|
|
402
402
|
"Breadcrumbs",
|
|
403
403
|
"Directory actions",
|
|
@@ -438,7 +438,7 @@
|
|
|
438
438
|
"version": "0.55.1"
|
|
439
439
|
},
|
|
440
440
|
"github-copilot": {
|
|
441
|
-
"docs_hash": "
|
|
441
|
+
"docs_hash": "ab9b7f5b4b692e05",
|
|
442
442
|
"headings": [
|
|
443
443
|
"About Copilot auto model selection",
|
|
444
444
|
"About Copilot automations",
|
|
@@ -475,7 +475,7 @@
|
|
|
475
475
|
}
|
|
476
476
|
},
|
|
477
477
|
"google-antigravity": {
|
|
478
|
-
"docs_hash": "
|
|
478
|
+
"docs_hash": "9fe532d247c3e361",
|
|
479
479
|
"headings": [],
|
|
480
480
|
"markers": {
|
|
481
481
|
"AGENTS.md": false,
|
|
@@ -502,7 +502,7 @@
|
|
|
502
502
|
}
|
|
503
503
|
},
|
|
504
504
|
"opencode": {
|
|
505
|
-
"docs_hash": "
|
|
505
|
+
"docs_hash": "4287f7d767dda4a8",
|
|
506
506
|
"headings": [
|
|
507
507
|
"Add features",
|
|
508
508
|
"Ask questions",
|
|
@@ -564,7 +564,7 @@
|
|
|
564
564
|
}
|
|
565
565
|
},
|
|
566
566
|
"windsurf": {
|
|
567
|
-
"docs_hash": "
|
|
567
|
+
"docs_hash": "60e25f8cb4c381be",
|
|
568
568
|
"headings": [
|
|
569
569
|
"Accounts",
|
|
570
570
|
"Advanced",
|
package/bin/ai-toolkit.js
CHANGED
|
@@ -12,6 +12,9 @@ const fs = require('fs');
|
|
|
12
12
|
const TOOLKIT_DIR = path.dirname(__dirname);
|
|
13
13
|
const CWD = process.cwd();
|
|
14
14
|
|
|
15
|
+
/** Minimum Python the toolkit scripts require: [major, minor]. */
|
|
16
|
+
const PYTHON_MIN = [3, 11];
|
|
17
|
+
|
|
15
18
|
if (!process.env.HOME) {
|
|
16
19
|
console.error('Error: HOME environment variable is not set');
|
|
17
20
|
process.exit(1);
|
|
@@ -139,6 +142,60 @@ function scriptPath(scriptName) {
|
|
|
139
142
|
return path.join(TOOLKIT_DIR, 'scripts', scriptName);
|
|
140
143
|
}
|
|
141
144
|
|
|
145
|
+
/** Memoized result of requirePython(); null until the first check runs. */
|
|
146
|
+
let pythonOk = null;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Verify `python3` exists and is >= PYTHON_MIN before any script is spawned.
|
|
150
|
+
* Without this the caller sees a raw traceback from deep inside scripts/
|
|
151
|
+
* (e.g. `dataclass() got an unexpected keyword argument 'slots'` on Python
|
|
152
|
+
* 3.9, which is what macOS ships as /usr/bin/python3).
|
|
153
|
+
* Exits with an actionable message when the interpreter is missing or too old.
|
|
154
|
+
*/
|
|
155
|
+
function requirePython() {
|
|
156
|
+
if (pythonOk) return;
|
|
157
|
+
const probe = spawnSync('python3', ['-c', 'import sys; sys.stdout.write("%d.%d.%d" % sys.version_info[:3])'], {
|
|
158
|
+
encoding: 'utf8',
|
|
159
|
+
});
|
|
160
|
+
const want = PYTHON_MIN.join('.');
|
|
161
|
+
|
|
162
|
+
if (probe.error || probe.status !== 0) {
|
|
163
|
+
console.error(`Error: python3 not found on PATH — ai-toolkit requires Python >= ${want}`);
|
|
164
|
+
console.error(pythonHint());
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const found = probe.stdout.trim();
|
|
169
|
+
const [major, minor] = found.split('.').map(Number);
|
|
170
|
+
if (major < PYTHON_MIN[0] || (major === PYTHON_MIN[0] && minor < PYTHON_MIN[1])) {
|
|
171
|
+
console.error(`Error: ai-toolkit requires Python >= ${want}, found ${found}`);
|
|
172
|
+
console.error(pythonHint());
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
pythonOk = true;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Platform-specific instructions for installing a supported Python.
|
|
180
|
+
* @returns {string} Multi-line hint text
|
|
181
|
+
*/
|
|
182
|
+
function pythonHint() {
|
|
183
|
+
const lines = [];
|
|
184
|
+
if (process.platform === 'darwin') {
|
|
185
|
+
lines.push('macOS ships Python 3.9 as /usr/bin/python3. Install a newer one:');
|
|
186
|
+
lines.push(' brew install python@3.13');
|
|
187
|
+
lines.push('Then make sure it comes first on PATH (`which python3` should not be /usr/bin/python3).');
|
|
188
|
+
} else if (process.platform === 'win32') {
|
|
189
|
+
lines.push('Install Python 3.11+ and make sure `python3` resolves to it:');
|
|
190
|
+
lines.push(' winget install Python.Python.3.13');
|
|
191
|
+
} else {
|
|
192
|
+
lines.push('Install Python 3.11+ via your package manager, e.g.:');
|
|
193
|
+
lines.push(' sudo apt install python3.13 # Debian/Ubuntu');
|
|
194
|
+
lines.push(' sudo dnf install python3.13 # Fedora/RHEL');
|
|
195
|
+
}
|
|
196
|
+
return lines.join('\n');
|
|
197
|
+
}
|
|
198
|
+
|
|
142
199
|
/**
|
|
143
200
|
* Execute a generator script synchronously via python3, returning its stdout.
|
|
144
201
|
* Exits the process on failure.
|
|
@@ -147,6 +204,7 @@ function scriptPath(scriptName) {
|
|
|
147
204
|
* @returns {Buffer} stdout output
|
|
148
205
|
*/
|
|
149
206
|
function runGenerator(scriptName, extraArgs = []) {
|
|
207
|
+
requirePython();
|
|
150
208
|
try {
|
|
151
209
|
return execFileSync('python3', [scriptPath(scriptName), ...extraArgs], { cwd: TOOLKIT_DIR });
|
|
152
210
|
} catch (err) {
|
|
@@ -162,6 +220,7 @@ function runGenerator(scriptName, extraArgs = []) {
|
|
|
162
220
|
* @param {{ cwd?: string }} [opts={}] - Options (cwd override)
|
|
163
221
|
*/
|
|
164
222
|
function run(script, args = [], opts = {}) {
|
|
223
|
+
requirePython();
|
|
165
224
|
const result = spawnSync('python3', [script, ...args], {
|
|
166
225
|
stdio: 'inherit',
|
|
167
226
|
cwd: opts.cwd || CWD,
|
|
@@ -178,6 +237,7 @@ function run(script, args = [], opts = {}) {
|
|
|
178
237
|
* @param {...string} flags - Flags to pass: --rules, --hooks, --mcp
|
|
179
238
|
*/
|
|
180
239
|
function propagateGlobal(...flags) {
|
|
240
|
+
requirePython();
|
|
181
241
|
const result = spawnSync('python3', [scriptPath('propagate_global.py'), ...flags], {
|
|
182
242
|
stdio: 'inherit',
|
|
183
243
|
cwd: CWD,
|
|
@@ -4,6 +4,7 @@ service: ai-toolkit
|
|
|
4
4
|
category: best-practices
|
|
5
5
|
tags: [best-practices, guidelines]
|
|
6
6
|
last_updated: "2026-03-25"
|
|
7
|
+
description: "Section index for ai-toolkit best-practices. No documents are filed here yet; new ones follow the best-practices template."
|
|
7
8
|
---
|
|
8
9
|
|
|
9
10
|
# Best Practices
|
package/kb/howto/README.md
CHANGED
|
@@ -3,9 +3,9 @@ title: "SOP: Post-Release Testing"
|
|
|
3
3
|
category: procedures
|
|
4
4
|
service: ai-toolkit
|
|
5
5
|
tags: [sop, post-release, smoke-test, npm, sandbox, plugin-pack, provenance, isolation]
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.2.0"
|
|
7
7
|
created: "2026-07-26"
|
|
8
|
-
last_updated: "2026-08-
|
|
8
|
+
last_updated: "2026-08-19"
|
|
9
9
|
description: "Smoke-test a published @softspark/ai-toolkit release from npm in an isolated HOME and npm prefix, without touching the maintainer's real install. Covers provenance, CLI, doctor, per-skill script resolution, scanner wiring, and the full plugin-pack lifecycle including the degraded-install path. Written for v4.18.0 and not run; v4.18.0 shipped a pack that broke every command it touched. First actually run on v4.22.0, which added Phases 4b and 4c after that release fixed four skills whose documented script path had never resolved and two that shipped a scanner nothing invoked."
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -159,21 +159,30 @@ cat > "$FX/index.html" <<'EOF'
|
|
|
159
159
|
<!DOCTYPE html><html><head><title>t</title></head>
|
|
160
160
|
<body><h1>A</h1><h3>skipped h2</h3><img src="x.png"><input type="text"><div onclick="go()">click</div></body></html>
|
|
161
161
|
EOF
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
162
|
+
cat > "$FX/patient.py" <<'EOF'
|
|
163
|
+
patient = {"ssn": "123-45-6789", "diagnosis": "fixture"}
|
|
164
|
+
endpoint = "http://example.com/patient"
|
|
165
|
+
encrypt = False
|
|
166
|
+
EOF
|
|
167
|
+
printf '{"name":"fx","dependencies":{"lodash":"4.17.20","react":"18"}}\n' > "$FX/package.json"
|
|
168
|
+
npm install --package-lock-only --ignore-scripts --prefix "$FX"
|
|
169
|
+
|
|
170
|
+
D="$HOME/.claude/skills/a11y-validate"
|
|
171
|
+
CLAUDE_SKILL_DIR="$D" timeout 60 python3 "$D/scripts/a11y-scanner.py" "$FX" --output json </dev/null
|
|
172
|
+
D="$HOME/.claude/skills/seo-validate"
|
|
173
|
+
CLAUDE_SKILL_DIR="$D" timeout 60 python3 "$D/scripts/seo-scanner.py" "$FX" --output json </dev/null
|
|
174
|
+
D="$HOME/.claude/skills/hipaa-validate"
|
|
175
|
+
CLAUDE_SKILL_DIR="$D" timeout 60 python3 "$D/scripts/hipaa_scan.py" "$FX" --output json </dev/null
|
|
176
|
+
D="$HOME/.claude/skills/cve-scan"
|
|
177
|
+
CLAUDE_SKILL_DIR="$D" timeout 60 python3 "$D/scripts/cve_scan.py" "$FX" --json </dev/null
|
|
171
178
|
```
|
|
172
179
|
|
|
173
180
|
**Verify:**
|
|
174
181
|
- [ ] The scanner returns findings, not an empty set — the fixture has real defects
|
|
175
182
|
- [ ] Findings span more than one category, proving the whole check set ran
|
|
176
183
|
- [ ] A scanner that exits non-zero on findings is doing its job, not failing
|
|
184
|
+
- [ ] CVE output has `total_findings > 0`; raw npm advisories with an empty
|
|
185
|
+
normalized `findings` array are a parser failure, not a clean scan
|
|
177
186
|
|
|
178
187
|
`a11y-validate` and `seo-validate` shipped working scanners that **no step in
|
|
179
188
|
either skill invoked** for their entire life before v4.22.0. The model was told to
|
|
@@ -11,7 +11,7 @@ tags:
|
|
|
11
11
|
doc_type: reference
|
|
12
12
|
created: "2026-04-11"
|
|
13
13
|
last_updated: "2026-07-26"
|
|
14
|
-
description: "
|
|
14
|
+
description: "Configuration inheritance for ai-toolkit projects extends base settings from npm packages, Git URLs, or local paths. Defines merge semantics, enforcement rules, and CLI commands for validating and diffing configurations."
|
|
15
15
|
---
|
|
16
16
|
|
|
17
17
|
# Enterprise Config Inheritance Guide
|
|
@@ -4,6 +4,7 @@ service: ai-toolkit
|
|
|
4
4
|
category: troubleshooting
|
|
5
5
|
tags: [troubleshooting, debugging]
|
|
6
6
|
last_updated: "2026-03-25"
|
|
7
|
+
description: "Section index for ai-toolkit troubleshooting. No documents are filed here yet; new ones follow the troubleshooting template."
|
|
7
8
|
---
|
|
8
9
|
|
|
9
10
|
# Troubleshooting
|
package/llms-full.txt
CHANGED
|
@@ -243,6 +243,7 @@ service: ai-toolkit
|
|
|
243
243
|
category: best-practices
|
|
244
244
|
tags: [best-practices, guidelines]
|
|
245
245
|
last_updated: "2026-03-25"
|
|
246
|
+
description: "Section index for ai-toolkit best-practices. No documents are filed here yet; new ones follow the best-practices template."
|
|
246
247
|
---
|
|
247
248
|
|
|
248
249
|
# Best Practices
|
|
@@ -5081,6 +5082,7 @@ service: ai-toolkit
|
|
|
5081
5082
|
category: howto
|
|
5082
5083
|
tags: [howto, guides]
|
|
5083
5084
|
last_updated: "2026-03-25"
|
|
5085
|
+
description: "Section index for ai-toolkit howto. No documents are filed here yet; new ones follow the howto template."
|
|
5084
5086
|
---
|
|
5085
5087
|
|
|
5086
5088
|
# How-To Guides
|
|
@@ -7041,9 +7043,9 @@ title: "SOP: Post-Release Testing"
|
|
|
7041
7043
|
category: procedures
|
|
7042
7044
|
service: ai-toolkit
|
|
7043
7045
|
tags: [sop, post-release, smoke-test, npm, sandbox, plugin-pack, provenance, isolation]
|
|
7044
|
-
version: "1.
|
|
7046
|
+
version: "1.2.0"
|
|
7045
7047
|
created: "2026-07-26"
|
|
7046
|
-
last_updated: "2026-08-
|
|
7048
|
+
last_updated: "2026-08-19"
|
|
7047
7049
|
description: "Smoke-test a published @softspark/ai-toolkit release from npm in an isolated HOME and npm prefix, without touching the maintainer's real install. Covers provenance, CLI, doctor, per-skill script resolution, scanner wiring, and the full plugin-pack lifecycle including the degraded-install path. Written for v4.18.0 and not run; v4.18.0 shipped a pack that broke every command it touched. First actually run on v4.22.0, which added Phases 4b and 4c after that release fixed four skills whose documented script path had never resolved and two that shipped a scanner nothing invoked."
|
|
7048
7050
|
---
|
|
7049
7051
|
|
|
@@ -7197,21 +7199,30 @@ cat > "$FX/index.html" <<'EOF'
|
|
|
7197
7199
|
<!DOCTYPE html><html><head><title>t</title></head>
|
|
7198
7200
|
<body><h1>A</h1><h3>skipped h2</h3><img src="x.png"><input type="text"><div onclick="go()">click</div></body></html>
|
|
7199
7201
|
EOF
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7208
|
-
|
|
7202
|
+
cat > "$FX/patient.py" <<'EOF'
|
|
7203
|
+
patient = {"ssn": "123-45-6789", "diagnosis": "fixture"}
|
|
7204
|
+
endpoint = "http://example.com/patient"
|
|
7205
|
+
encrypt = False
|
|
7206
|
+
EOF
|
|
7207
|
+
printf '{"name":"fx","dependencies":{"lodash":"4.17.20","react":"18"}}\n' > "$FX/package.json"
|
|
7208
|
+
npm install --package-lock-only --ignore-scripts --prefix "$FX"
|
|
7209
|
+
|
|
7210
|
+
D="$HOME/.claude/skills/a11y-validate"
|
|
7211
|
+
CLAUDE_SKILL_DIR="$D" timeout 60 python3 "$D/scripts/a11y-scanner.py" "$FX" --output json </dev/null
|
|
7212
|
+
D="$HOME/.claude/skills/seo-validate"
|
|
7213
|
+
CLAUDE_SKILL_DIR="$D" timeout 60 python3 "$D/scripts/seo-scanner.py" "$FX" --output json </dev/null
|
|
7214
|
+
D="$HOME/.claude/skills/hipaa-validate"
|
|
7215
|
+
CLAUDE_SKILL_DIR="$D" timeout 60 python3 "$D/scripts/hipaa_scan.py" "$FX" --output json </dev/null
|
|
7216
|
+
D="$HOME/.claude/skills/cve-scan"
|
|
7217
|
+
CLAUDE_SKILL_DIR="$D" timeout 60 python3 "$D/scripts/cve_scan.py" "$FX" --json </dev/null
|
|
7209
7218
|
```
|
|
7210
7219
|
|
|
7211
7220
|
**Verify:**
|
|
7212
7221
|
- [ ] The scanner returns findings, not an empty set — the fixture has real defects
|
|
7213
7222
|
- [ ] Findings span more than one category, proving the whole check set ran
|
|
7214
7223
|
- [ ] A scanner that exits non-zero on findings is doing its job, not failing
|
|
7224
|
+
- [ ] CVE output has `total_findings > 0`; raw npm advisories with an empty
|
|
7225
|
+
normalized `findings` array are a parser failure, not a clean scan
|
|
7215
7226
|
|
|
7216
7227
|
`a11y-validate` and `seo-validate` shipped working scanners that **no step in
|
|
7217
7228
|
either skill invoked** for their entire life before v4.22.0. The model was told to
|
|
@@ -11046,7 +11057,7 @@ tags:
|
|
|
11046
11057
|
doc_type: reference
|
|
11047
11058
|
created: "2026-04-11"
|
|
11048
11059
|
last_updated: "2026-07-26"
|
|
11049
|
-
description: "
|
|
11060
|
+
description: "Configuration inheritance for ai-toolkit projects extends base settings from npm packages, Git URLs, or local paths. Defines merge semantics, enforcement rules, and CLI commands for validating and diffing configurations."
|
|
11050
11061
|
---
|
|
11051
11062
|
|
|
11052
11063
|
# Enterprise Config Inheritance Guide
|
|
@@ -16120,6 +16131,7 @@ service: ai-toolkit
|
|
|
16120
16131
|
category: troubleshooting
|
|
16121
16132
|
tags: [troubleshooting, debugging]
|
|
16122
16133
|
last_updated: "2026-03-25"
|
|
16134
|
+
description: "Section index for ai-toolkit troubleshooting. No documents are filed here yet; new ones follow the troubleshooting template."
|
|
16123
16135
|
---
|
|
16124
16136
|
|
|
16125
16137
|
# Troubleshooting
|
package/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softspark/ai-toolkit",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.26.0",
|
|
4
4
|
"description": "AI coding toolkit: 109 skills, 44 agents, 12 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/_common.py
CHANGED
|
@@ -20,8 +20,35 @@ from __future__ import annotations
|
|
|
20
20
|
import os
|
|
21
21
|
import platform
|
|
22
22
|
import shutil
|
|
23
|
+
import sys
|
|
23
24
|
from pathlib import Path
|
|
24
25
|
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
# Python version floor
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
# Kept in sync with PYTHON_MIN in bin/ai-toolkit.js and the python3 entry in
|
|
30
|
+
# scripts/check_deps.py. Checked here because _common is imported first by
|
|
31
|
+
# every entry point, so a stale interpreter fails with this message instead of
|
|
32
|
+
# a traceback from whichever module happens to use 3.11+ syntax.
|
|
33
|
+
PYTHON_MIN = (3, 11)
|
|
34
|
+
|
|
35
|
+
if sys.version_info < PYTHON_MIN:
|
|
36
|
+
_want = ".".join(str(n) for n in PYTHON_MIN)
|
|
37
|
+
_found = ".".join(str(n) for n in sys.version_info[:3])
|
|
38
|
+
sys.stderr.write(
|
|
39
|
+
"Error: ai-toolkit requires Python >= {}, found {} ({})\n".format(
|
|
40
|
+
_want, _found, sys.executable
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
if sys.platform == "darwin":
|
|
44
|
+
sys.stderr.write(
|
|
45
|
+
"macOS ships Python 3.9 as /usr/bin/python3. Install a newer one:\n"
|
|
46
|
+
" brew install python@3.13\n"
|
|
47
|
+
)
|
|
48
|
+
else:
|
|
49
|
+
sys.stderr.write("Install Python 3.11+ via your package manager.\n")
|
|
50
|
+
sys.exit(1)
|
|
51
|
+
|
|
25
52
|
# ---------------------------------------------------------------------------
|
|
26
53
|
# Re-exports from frontmatter module
|
|
27
54
|
# ---------------------------------------------------------------------------
|
package/scripts/check_deps.py
CHANGED
|
@@ -33,7 +33,7 @@ REQUIRED = [
|
|
|
33
33
|
{
|
|
34
34
|
"name": "python3",
|
|
35
35
|
"check": "python3",
|
|
36
|
-
"min_version": "3.
|
|
36
|
+
"min_version": "3.11",
|
|
37
37
|
"packages": {
|
|
38
38
|
"brew": "python3",
|
|
39
39
|
"apt": "python3",
|
|
@@ -45,7 +45,7 @@ REQUIRED = [
|
|
|
45
45
|
"choco": "python",
|
|
46
46
|
"scoop": "python",
|
|
47
47
|
},
|
|
48
|
-
"reason": "All toolkit scripts run on Python 3 (stdlib only, no pip needed)",
|
|
48
|
+
"reason": "All toolkit scripts run on Python 3.11+ (stdlib only, no pip needed). macOS /usr/bin/python3 is 3.9 and will not work.",
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
"name": "git",
|