@softspark/ai-toolkit 4.29.0 → 4.29.1

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 CHANGED
@@ -7,6 +7,53 @@ Versioning follows [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ---
9
9
 
10
+ ## v4.29.1 — The guard stops blocking the safe branch delete (2026-08-21)
11
+
12
+ ### Fixed
13
+
14
+ - **`guard-destructive.sh` no longer folds `-d` onto `-D`.** Every pattern was
15
+ matched by a single `grep -qEi`, so the `git\s+branch\s+-D\b` pattern also
16
+ caught `git branch -d`. Those are different operations: `-D` discards an
17
+ unmerged branch, `-d` refuses to. The safe one is what
18
+ `.claude/rules/ai-toolkit-git-workflow.md` tells users to run after every
19
+ merge, and the guard blocked it — a false positive on the toolkit's own
20
+ advice, in the toolkit's own safety hook.
21
+ - **Patterns are matched in two passes, split by whether case carries meaning.**
22
+ Command names and flags go through a case-sensitive `grep -qE`; POSIX flags
23
+ that differ only in case are different flags, and folding them together can
24
+ only lose information. SQL keywords and the Windows `format` command go
25
+ through a case-insensitive `grep -qEi`, because their casing genuinely varies
26
+ in the wild — `drop table`, `Truncate`, and `delete from` all still block.
27
+ The `-i` was presumably there for the SQL patterns all along; it was the
28
+ flag patterns that paid for it.
29
+
30
+ - **A cross-file race in the test suite.** `doctor --fix regenerates missing
31
+ llms-full.txt` deleted the artifact from the shared checkout and asserted on
32
+ doctor's `FIXED` line. `npm test` runs `bats --jobs 4
33
+ --no-parallelize-within-files`, so files run concurrently, and
34
+ `test_doctor_plugin_double_load.bats` also runs `doctor --fix` — which
35
+ regenerates that artifact. When it won, the assertion saw a present file, no
36
+ `FIXED` line, and a red suite; the test also left a `llms-full.txt.test-bak`
37
+ in the repo, because the restoring `mv` never ran. v4.29.0 added a second
38
+ `doctor --fix` call to the plugin test file, which is what made a latent race
39
+ start firing. The test now runs doctor against a private copy of the toolkit,
40
+ so it mutates no shared state at all.
41
+
42
+ ### Changed
43
+
44
+ - `kb/reference/hooks-catalog.md` documents the two-pass matching and lists the
45
+ safe branch delete among the guard's exemptions.
46
+ - Test count: 1666 → 1671. The new cases pin both directions: the safe delete
47
+ and an uppercase non-flag pass, lowercase and mixed-case SQL block.
48
+
49
+ ### Known gap (not addressed here)
50
+
51
+ - The guard matches `git branch -D` but not its long form, `git branch --delete
52
+ --force`. That gap predates this fix and closing it is a coverage change
53
+ rather than a case-sensitivity one, so it is left for a separate decision.
54
+
55
+ ---
56
+
10
57
  ## v4.29.0 — Stale plugin uploads stop hiding (2026-08-21)
11
58
 
12
59
  ### Added
package/README.md CHANGED
@@ -6,24 +6,21 @@
6
6
  [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
7
7
  [![Skills](https://img.shields.io/badge/skills-109-brightgreen)](app/skills/)
8
8
  [![Agents](https://img.shields.io/badge/agents-44-blue)](app/agents/)
9
- [![Tests](https://img.shields.io/badge/tests-1666%20passing-success)](tests/)
10
-
11
- ## What's New in v4.29.0
12
-
13
- **v4.29.0** stops a stale Claude app upload from passing as healthy:
14
-
15
- - The plugin ZIP is a point-in-time snapshot. Once the toolkit moves on, Chat and
16
- Cowork keep running the skills, agents, hooks, and rules from whenever you
17
- exported it, with nothing anywhere saying so.
18
- - `ai-toolkit doctor` now compares the version recorded in
19
- `~/.claude/plugins/installed_plugins.json` against the installed toolkit and
20
- warns when they differ -- including when the plugin is disabled for Claude
21
- Code, since Chat and Cowork still load it.
22
- - `--fix` cannot clear that warning. It can regenerate the export; the upload
23
- itself is manual, so the check names both steps instead of pretending.
24
- - `ai-toolkit install` now re-asserts the plugin as disabled for Claude Code.
25
- Uploading the ZIP re-enables it every time, which had left the double-load fix
26
- to whoever remembered to re-run `doctor --fix`.
9
+ [![Tests](https://img.shields.io/badge/tests-1671%20passing-success)](tests/)
10
+
11
+ ## What's New in v4.29.1
12
+
13
+ **v4.29.1** stops the destructive-command guard from blocking a safe branch delete:
14
+
15
+ - `guard-destructive.sh` matched every pattern with one case-insensitive grep, so
16
+ the force-delete pattern also caught the lowercase safe delete -- the variant
17
+ that refuses to drop an unmerged branch, and exactly the post-merge cleanup the
18
+ toolkit's own git-workflow rules prescribe.
19
+ - Patterns are now matched in two passes. Command names and flags are matched
20
+ case-sensitively, because short flags that differ only in case are different
21
+ flags. SQL keywords and the Windows `format` command stay case-insensitive, so
22
+ lowercase SQL still blocks.
23
+ - Force delete still blocks. Test count: 1666 -> 1671.
27
24
 
28
25
  ## Table of Contents
29
26
 
@@ -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.29.0",
6
+ "version": "4.29.1",
7
7
  "author": {
8
8
  "name": "SoftSpark",
9
9
  "url": "https://github.com/softspark"
@@ -40,7 +40,15 @@ fi
40
40
  # --force or -f left behind still blocks.
41
41
  SAFE_STRIPPED=$(printf '%s' "$NORMALIZED" | sed -E 's/--force-with-lease(=[^ ]*)?//g; s/--force-if-includes//g')
42
42
 
43
- # Destructive patterns — word-boundary aware where possible
43
+ # Destructive patterns — word-boundary aware where possible.
44
+ #
45
+ # Two buckets, matched by two greps, because case sensitivity is not a uniform
46
+ # property of these patterns. POSIX command names and flags are case-SIGNIFICANT:
47
+ # `-d` and `-D` are different flags, and folding them together made the guard
48
+ # block `git branch -d` — the safe delete that refuses unmerged branches — as if
49
+ # it were `-D`. SQL keywords carry no such distinction and are written in every
50
+ # casing in the wild, so they need folding. One case-insensitive grep over both
51
+ # sets cannot express that, and the flag bucket is the one that loses.
44
52
  DESTRUCTIVE_PATTERNS=(
45
53
  # rm variants (short flags, long flags, separated flags, sudo, xargs/find piped)
46
54
  'rm\s+(-[rRf]{2,}|-r\s+-f|-f\s+-r)'
@@ -54,18 +62,13 @@ DESTRUCTIVE_PATTERNS=(
54
62
  'find\s+.*-delete'
55
63
  'find\s+.*-exec\s+rm\b'
56
64
 
57
- # SQL destructive operations
58
- 'DROP\s+(TABLE|DATABASE|SCHEMA|INDEX)'
59
- 'TRUNCATE\s+'
60
- 'DELETE\s+FROM\s+\S+\s*(;|$|WHERE\s+1)'
61
-
62
65
  # Disk/filesystem destructive
63
- 'format\s+/'
64
66
  'dd\s+if='
65
67
  'mkfs\b'
66
68
  'shred\b'
67
69
 
68
- # Git destructive operations
70
+ # Git destructive operations. `-D` only: `git branch -d` refuses to delete an
71
+ # unmerged branch and is the documented post-merge cleanup, not a hazard.
69
72
  'git\s+push\s+(--force|-f)\b'
70
73
  'git\s+push\s+.*--force'
71
74
  'git\s+reset\s+--hard'
@@ -88,10 +91,25 @@ DESTRUCTIVE_PATTERNS=(
88
91
  '>\s*/dev/sd[a-z]'
89
92
  )
90
93
 
91
- # Build combined regex
94
+ # Case-insensitive bucket: patterns whose real-world casing genuinely varies.
95
+ # SQL is written DROP TABLE, drop table, and Drop Table with equal frequency;
96
+ # `format` is a Windows command and Windows command names are case-insensitive.
97
+ DESTRUCTIVE_PATTERNS_NOCASE=(
98
+ # SQL destructive operations
99
+ 'DROP\s+(TABLE|DATABASE|SCHEMA|INDEX)'
100
+ 'TRUNCATE\s+'
101
+ 'DELETE\s+FROM\s+\S+\s*(;|$|WHERE\s+1)'
102
+
103
+ # Disk/filesystem destructive
104
+ 'format\s+/'
105
+ )
106
+
107
+ # Build combined regexes
92
108
  REGEX=$(IFS='|'; echo "${DESTRUCTIVE_PATTERNS[*]}")
109
+ REGEX_NOCASE=$(IFS='|'; echo "${DESTRUCTIVE_PATTERNS_NOCASE[*]}")
93
110
 
94
- if echo "$SAFE_STRIPPED" | grep -qEi "($REGEX)"; then
111
+ if echo "$SAFE_STRIPPED" | grep -qE "($REGEX)" \
112
+ || echo "$SAFE_STRIPPED" | grep -qEi "($REGEX_NOCASE)"; then
95
113
  echo "WARNING: Potentially destructive command detected. Please verify." >&2
96
114
  exit 2
97
115
  fi
@@ -95,8 +95,15 @@ for debugging; `AI_TOOLKIT_HOOK_QUIET=1` keeps it silent explicitly.
95
95
  - `git push --force`
96
96
  - `chmod -R 777`
97
97
 
98
+ **Case sensitivity:** patterns are matched in two passes. Command names and flags
99
+ are matched case-**sensitively**, because `-d` and `-D` are different flags —
100
+ `git branch -D` blocks, `git branch -d` does not. SQL keywords and the Windows
101
+ `format` command are matched case-**insensitively**, so `drop table` blocks the
102
+ same as `DROP TABLE`.
103
+
98
104
  **Exemptions (avoid false positives):**
99
105
  - `git push --force-with-lease` / `--force-if-includes` — the safe force-push variants are allowed.
106
+ - `git branch -d` — the safe delete refuses unmerged branches and is the post-merge cleanup the git-workflow rules prescribe. `git branch -D` still blocks.
100
107
  - A single, non-chained `echo`/`printf`/`git commit`/`git tag` carrying a destructive token as *data* (e.g. a commit message mentioning `DROP TABLE`) is allowed. Chained commands (`&&`, `;`, `|`) are still inspected in full.
101
108
 
102
109
  ### PreToolUse (file ops) — `guard-path.sh`
package/llms-full.txt CHANGED
@@ -12244,8 +12244,15 @@ for debugging; `AI_TOOLKIT_HOOK_QUIET=1` keeps it silent explicitly.
12244
12244
  - `git push --force`
12245
12245
  - `chmod -R 777`
12246
12246
 
12247
+ **Case sensitivity:** patterns are matched in two passes. Command names and flags
12248
+ are matched case-**sensitively**, because `-d` and `-D` are different flags —
12249
+ `git branch -D` blocks, `git branch -d` does not. SQL keywords and the Windows
12250
+ `format` command are matched case-**insensitively**, so `drop table` blocks the
12251
+ same as `DROP TABLE`.
12252
+
12247
12253
  **Exemptions (avoid false positives):**
12248
12254
  - `git push --force-with-lease` / `--force-if-includes` — the safe force-push variants are allowed.
12255
+ - `git branch -d` — the safe delete refuses unmerged branches and is the post-merge cleanup the git-workflow rules prescribe. `git branch -D` still blocks.
12249
12256
  - A single, non-chained `echo`/`printf`/`git commit`/`git tag` carrying a destructive token as *data* (e.g. a commit message mentioning `DROP TABLE`) is allowed. Chained commands (`&&`, `;`, `|`) are still inspected in full.
12250
12257
 
12251
12258
  ### PreToolUse (file ops) — `guard-path.sh`
package/manifest.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.29.0",
2
+ "version": "4.29.1",
3
3
  "components": {
4
4
  "agents": {
5
5
  "description": "44 specialized agents (orchestrator, backend, frontend, security, devops, etc.)",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softspark/ai-toolkit",
3
- "version": "4.29.0",
3
+ "version": "4.29.1",
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",