@softspark/ai-toolkit 4.31.0 → 4.32.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 +121 -0
- package/README.md +21 -19
- package/app/.claude-plugin/plugin.json +1 -1
- package/app/claude-app/hooks/hooks.json +4 -2
- package/app/claude-app/skills/ai-toolkit-rules/SKILL.md +30 -16
- package/app/hooks/quality-gate.sh +9 -2
- package/app/hooks.json +4 -2
- package/app/rules/common/git-team.md +33 -0
- package/app/rules/common/git-workflow.md +6 -20
- package/app/rules/common/performance.md +25 -1
- package/app/rules/common/testing.md +7 -1
- package/app/skills/analyze/scripts/complexity.py +3 -0
- package/app/skills/deploy/scripts/pre_deploy_check.py +13 -6
- package/app/skills/docs/scripts/doc-inventory.py +3 -0
- package/app/skills/explain/scripts/dependency-graph.py +3 -0
- package/app/skills/migrate/scripts/migration-status.py +3 -0
- package/app/skills/refactor/scripts/refactor-scan.py +3 -0
- package/benchmarks/ecosystem-doctor-snapshot.json +17 -15
- package/bin/ai-toolkit.js +2 -0
- package/kb/procedures/sop-maintenance.md +6 -3
- package/kb/reference/cli-reference.md +3 -2
- package/kb/reference/global-install-model.md +16 -3
- package/kb/reference/hooks-catalog.md +5 -3
- package/kb/reference/language-rules.md +28 -10
- package/kb/reference/plugin-pack-conventions.md +3 -3
- package/kb/reference/unique-features.md +2 -1
- package/llms-full.txt +63 -25
- package/manifest.json +2 -2
- package/package.json +5 -2
- package/scripts/benchmark_ecosystem.py +0 -1
- package/scripts/check_split.py +11 -9
- package/scripts/claude_app.py +5 -7
- package/scripts/codex_skill_adapter.py +4 -12
- package/scripts/compile_slm.py +10 -26
- package/scripts/doctor.py +322 -0
- package/scripts/evaluate_skills.py +1 -1
- package/scripts/frontmatter.py +452 -29
- package/scripts/generate_augment_rules.py +4 -4
- package/scripts/generate_cursor_mdc.py +2 -3
- package/scripts/generate_language_rules_skills.py +8 -14
- package/scripts/generate_llms_txt.py +1 -15
- package/scripts/generate_opencode_agents.py +0 -1
- package/scripts/generate_opencode_skills.py +2 -20
- package/scripts/generate_windsurf_rules.py +0 -1
- package/scripts/generator_base.py +0 -1
- package/scripts/inject_hook_cli.py +15 -2
- package/scripts/inject_mcp_cli.py +1 -2
- package/scripts/install.py +32 -1
- package/scripts/install_git_hooks.py +0 -1
- package/scripts/install_steps/ai_tools.py +65 -25
- package/scripts/install_steps/markers.py +6 -6
- package/scripts/install_steps/skill_scope.py +188 -0
- package/scripts/instruction_core.py +5 -8
- package/scripts/merge-hooks.py +13 -3
- package/scripts/pack_codebase.py +1 -1
- package/scripts/plugin.py +128 -16
- package/scripts/surface_manifest.py +6 -7
- package/scripts/validate.py +180 -11
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,127 @@ Versioning follows [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## v4.32.1 - Plugin removal leaves nothing behind (2026-09-04)
|
|
11
|
+
|
|
12
|
+
Both fixes come from running the post-release SOPs on v4.32.0 in an isolated
|
|
13
|
+
sandbox; both defects predate that release (identical on v4.31.0).
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **`plugin remove` deletes the hooks and scripts a pack installed.** The
|
|
18
|
+
Claude and Codex install paths copied `hooks/plugin-<pack>-*` and
|
|
19
|
+
`plugin-scripts/<pack>/*` into `~/.softspark/ai-toolkit` but never recorded
|
|
20
|
+
them in `shared_asset_ownership`, so removal found no owner and preserved
|
|
21
|
+
every file as "untracked": each pack left 4-5 files behind. Install now
|
|
22
|
+
records sha256/mode/inode for what it copied; removal deletes only entries
|
|
23
|
+
this editor consumes that no other editor still uses and that are unchanged
|
|
24
|
+
on disk, preserves an edited file with a `WARN preserved changed plugin
|
|
25
|
+
asset` line, and drops the empty `plugin-scripts/<pack>/` directory.
|
|
26
|
+
`tests/test_plugin_asset_removal.bats` covers install, zero-residue removal,
|
|
27
|
+
user-edited preservation, two-editor sharing, and reinstall.
|
|
28
|
+
- **Five skill scripts answer `--help`.** `doc-inventory.py`,
|
|
29
|
+
`dependency-graph.py`, `migration-status.py`, `refactor-scan.py`, and
|
|
30
|
+
`complexity.py` treated `--help` as a path and returned a JSON error.
|
|
31
|
+
`tests/test_skill_scripts_help.bats` now probes every documented
|
|
32
|
+
`${CLAUDE_SKILL_DIR}` invocation with `--help` (exit 0, no traceback), the
|
|
33
|
+
same check as post-release SOP Phase 4b. The probe uses `perl alarm` as its
|
|
34
|
+
hang guard, not GNU `timeout`, which the macOS CI runner does not have.
|
|
35
|
+
- **`pre_deploy_check.py` no longer crashes on Linux.** It probed for docker
|
|
36
|
+
by running the shell builtin `command -v` through `subprocess`, which only
|
|
37
|
+
works on macOS (a `/usr/bin/command` binary exists there); on Linux it raised
|
|
38
|
+
`FileNotFoundError` before any check ran. Now `shutil.which`. Caught by the
|
|
39
|
+
new `--help` probe on the Ubuntu CI runner, which is the point of that test.
|
|
40
|
+
- **Test count.** Bats increased from 1966 to 1972.
|
|
41
|
+
|
|
42
|
+
## v4.32.0 - Context budget: scoped rules, scoped language skills, doctor budget checks (2026-09-04)
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
- **`install --language-skills detected|all`.** Language knowledge skills
|
|
47
|
+
(`<lang>-rules`, `<lang>-patterns`) for languages no registered project uses
|
|
48
|
+
are turned off through `skillOverrides` in `~/.claude/settings.json`. The
|
|
49
|
+
entries the toolkit wrote are tracked in `state.json` and restored when a
|
|
50
|
+
newly registered project brings the language back; a user's own override is
|
|
51
|
+
never touched; with no registered project on disk nothing is disabled. `all`
|
|
52
|
+
restores everything and persists the choice.
|
|
53
|
+
- **`doctor` check 12, Context Budget.** Estimated resident tokens of the
|
|
54
|
+
model-visible skill listing (against `skillListingBudgetFraction`), the agent
|
|
55
|
+
listing, and always-loaded user memory, plus skills with zero recorded use in
|
|
56
|
+
both Claude Code's counters and the toolkit's `stats.json`. Read-only; prints
|
|
57
|
+
the `skillOverrides` key to paste.
|
|
58
|
+
- **`doctor` check 13, Permission Rules.** Warns on `permissions.allow`
|
|
59
|
+
wildcards that pre-approve execution or writes: interpreters, task runners,
|
|
60
|
+
package installs, `gh api`, `curl`/`wget`, `git fetch`/`pull`, destructive
|
|
61
|
+
commands, `find -exec`. Never edits.
|
|
62
|
+
- **`validate.py` skill description budget.** Error over 1024 characters (the
|
|
63
|
+
Agent Skills cap), warning over 400, and an error for an unquoted description
|
|
64
|
+
containing `: ` or ` #` (strict YAML drops every field, `allowed-tools`
|
|
65
|
+
included). Applied to plugin-pack skills too.
|
|
66
|
+
- **`git-team` common rule.** Branching, pull-request, and review conventions
|
|
67
|
+
moved out of `git-workflow` into a rule that ships with `--profile strict`
|
|
68
|
+
only, via a new `profiles:` frontmatter gate. See `DECISIONS.md`.
|
|
69
|
+
- **One frontmatter parser.** `scripts/frontmatter.py` now parses the whole
|
|
70
|
+
toolkit subset (scalars, quoted scalars, `>-`/`|` blocks, block and flow
|
|
71
|
+
lists, nested maps) strictly and is the only parser; twelve private
|
|
72
|
+
strip/parse copies in `validate.py`, `doctor.py`, `install_steps/ai_tools.py`,
|
|
73
|
+
`claude_app.py`, `compile_slm.py`, `surface_manifest.py`, `instruction_core.py`,
|
|
74
|
+
`check_split.py`, `codex_skill_adapter.py`, `generate_opencode_skills.py`, and
|
|
75
|
+
`generate_language_rules_skills.py` are gone. Every shipped `app/` and `kb/`
|
|
76
|
+
Markdown file parses under the strict grammar (pytest corpus test).
|
|
77
|
+
- **Repo dev tooling, stdlib runtime.** `requirements-dev.txt` + `pytest.ini`
|
|
78
|
+
+ `mypy.ini` (pytest, ruff, mypy) and a `python-quality` CI job:
|
|
79
|
+
`npm run test:py` (348 pytest tests under `tests/python/`), `npm run lint:py`
|
|
80
|
+
(ruff `E,F`, rule set in `package.json`), `npm run typecheck:py` (mypy
|
|
81
|
+
`--strict` over an allowlist). No `pyproject.toml`: the toolkit's own
|
|
82
|
+
`quality-gate.sh` reads one as "Python project, run `ruff check .`", which
|
|
83
|
+
is not what an npm-first repo wants. Nothing is added to the published
|
|
84
|
+
package or to user machines. See `DECISIONS.md` for why no runtime
|
|
85
|
+
dependency.
|
|
86
|
+
|
|
87
|
+
### Changed
|
|
88
|
+
|
|
89
|
+
- **Common rules are path-scoped from their source.** `app/rules/common/*.md`
|
|
90
|
+
may declare `paths:`; the generated `.claude/rules/ai-toolkit-*.md` copies it.
|
|
91
|
+
`testing` and `performance` load only for matching files; `coding-style`,
|
|
92
|
+
`git-workflow`, and `security` stay always-on. The `.claude/CLAUDE.md` index
|
|
93
|
+
now lists which rules are always-on and which are path-scoped instead of
|
|
94
|
+
claiming lazy loading for all of them.
|
|
95
|
+
- **Stop hooks `quality-check.sh` and `save-session.sh` run with
|
|
96
|
+
`"async": true`.** Both are advisory and always exit 0; the linter was the
|
|
97
|
+
bulk of a 3.3 s median Stop chain. `quality-gate.sh` (exit 2) and
|
|
98
|
+
`stop-search-check.sh` stay synchronous.
|
|
99
|
+
- **`git-workflow` is the solo-safe core** (commit format, no secrets, `main`
|
|
100
|
+
deployable, tags, recovery). Version 2.0.0.
|
|
101
|
+
|
|
102
|
+
### Fixed
|
|
103
|
+
|
|
104
|
+
- **`quality-gate.sh` runs ruff only for projects that configured it.** A bare
|
|
105
|
+
`pyproject.toml` (build metadata, pytest/mypy tables) used to trigger
|
|
106
|
+
`ruff check .` on every Stop under whatever ruff configuration the machine
|
|
107
|
+
resolves; found when this repository's own gate went red on 348 unrelated
|
|
108
|
+
findings. Ruff now needs `ruff.toml`, `.ruff.toml`, or a `[tool.ruff]` table.
|
|
109
|
+
- **Codex/DSH skill sync no longer flattens nested frontmatter.** Native
|
|
110
|
+
(non-adapted) skills had their frontmatter re-rendered line by line, which
|
|
111
|
+
turned a `hooks:` block into stray top-level `PreToolUse:` / `- matcher:`
|
|
112
|
+
lines. The frontmatter now passes through verbatim.
|
|
113
|
+
- **Hook merge de-duplicates legacy untagged toolkit hooks by command identity.**
|
|
114
|
+
Scheduling fields (`async`, `timeout`, `statusMessage`, ...) no longer defeat
|
|
115
|
+
the match, so adding one in `app/hooks.json` does not leave existing installs
|
|
116
|
+
running the old and the new copy side by side. Fixed in both
|
|
117
|
+
`scripts/merge-hooks.py` and `scripts/inject_hook_cli.py`.
|
|
118
|
+
- **Test count.** Bats increased from 1931 to 1966; 348 pytest tests added under
|
|
119
|
+
`tests/python/` (run by the new `python-quality` CI job).
|
|
120
|
+
|
|
121
|
+
### Ecosystem
|
|
122
|
+
|
|
123
|
+
- Ecosystem doctor run for this minor release: 12 tools drifted since the
|
|
124
|
+
v4.30.3 snapshot, all class A (content edits with no heading delta) or class
|
|
125
|
+
C (Cline gained a "Resources" heading, Codex CLI a "ChatGPT Work" heading;
|
|
126
|
+
neither adds a surface the toolkit integrates). Tracked versions moved:
|
|
127
|
+
Claude Code 2.1.252 -> 2.1.260 (its hooks documentation now lists the
|
|
128
|
+
`async` command-hook field this release relies on), Codex CLI 0.151.0 ->
|
|
129
|
+
0.153.2. No generator changed; snapshot refreshed.
|
|
130
|
+
|
|
10
131
|
## v4.31.0 - Toolkit rules reach every editor (2026-09-03)
|
|
11
132
|
|
|
12
133
|
### Added
|
package/README.md
CHANGED
|
@@ -6,25 +6,25 @@
|
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](app/skills/)
|
|
8
8
|
[](app/agents/)
|
|
9
|
-
[](tests/)
|
|
10
|
+
|
|
11
|
+
## What's New in v4.32.1
|
|
12
|
+
|
|
13
|
+
**v4.32.1** fixes two defects the post-release SOPs found on v4.32.0 (both
|
|
14
|
+
older than that release):
|
|
15
|
+
|
|
16
|
+
- `ai-toolkit plugin remove` now deletes the hooks and scripts a pack
|
|
17
|
+
installed under `~/.softspark/ai-toolkit`. Install records what it copied;
|
|
18
|
+
removal deletes only unchanged, unshared files and names anything it
|
|
19
|
+
preserves. Every pack used to leave 4-5 files behind.
|
|
20
|
+
- Five skill scripts (`doc-inventory`, `dependency-graph`, `migration-status`,
|
|
21
|
+
`refactor-scan`, `complexity`) answer `--help` instead of treating it as a
|
|
22
|
+
path; a new test probes every documented skill script with `--help`.
|
|
23
|
+
- Still in this train from v4.32.0: path-scoped common rules, language skills
|
|
24
|
+
scoped to your registered projects (`--language-skills`), `doctor` Context
|
|
25
|
+
Budget and Permission Rules checks, one strict frontmatter parser, and the
|
|
26
|
+
`git-team` rule for `--profile strict`. Test count: 1966 -> 1972 bats +
|
|
27
|
+
348 pytest.
|
|
28
28
|
|
|
29
29
|
See [CHANGELOG.md](CHANGELOG.md) for full history.
|
|
30
30
|
|
|
@@ -62,6 +62,8 @@ npx @softspark/ai-toolkit install
|
|
|
62
62
|
|
|
63
63
|
**That's it.** Claude Code picks up 114 skills, 44 agents, quality hooks, and the safety constitution automatically.
|
|
64
64
|
|
|
65
|
+
Language knowledge skills (`rust-rules`, `kotlin-patterns`, ...) are scoped to the languages your registered projects use: once you have run `ai-toolkit install --local` in at least one project, the global install turns the other languages' skills off through `skillOverrides` in `~/.claude/settings.json` so their descriptions stop loading into every session. A new project in a new language turns its skills back on. `ai-toolkit install --language-skills all` keeps every language skill on and remembers that choice; `ai-toolkit doctor` shows the resulting context budget.
|
|
66
|
+
|
|
65
67
|
**Windows:** WSL is the recommended runtime. Native Windows works when Git Bash is available for hook scripts; dependency hints cover `winget`, Chocolatey, and Scoop. See [Windows Support](kb/reference/windows-support.md).
|
|
66
68
|
|
|
67
69
|
### Update
|
|
@@ -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.32.1",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "SoftSpark",
|
|
9
9
|
"url": "https://github.com/softspark"
|
|
@@ -151,7 +151,8 @@
|
|
|
151
151
|
"hooks": [
|
|
152
152
|
{
|
|
153
153
|
"type": "command",
|
|
154
|
-
"command": "AI_TOOLKIT_DIR=\"${CLAUDE_PLUGIN_ROOT}\" \"${CLAUDE_PLUGIN_ROOT}/hooks/quality-check.sh\""
|
|
154
|
+
"command": "AI_TOOLKIT_DIR=\"${CLAUDE_PLUGIN_ROOT}\" \"${CLAUDE_PLUGIN_ROOT}/hooks/quality-check.sh\"",
|
|
155
|
+
"async": true
|
|
155
156
|
}
|
|
156
157
|
]
|
|
157
158
|
},
|
|
@@ -160,7 +161,8 @@
|
|
|
160
161
|
"hooks": [
|
|
161
162
|
{
|
|
162
163
|
"type": "command",
|
|
163
|
-
"command": "AI_TOOLKIT_DIR=\"${CLAUDE_PLUGIN_ROOT}\" \"${CLAUDE_PLUGIN_ROOT}/hooks/save-session.sh\""
|
|
164
|
+
"command": "AI_TOOLKIT_DIR=\"${CLAUDE_PLUGIN_ROOT}\" \"${CLAUDE_PLUGIN_ROOT}/hooks/save-session.sh\"",
|
|
165
|
+
"async": true
|
|
164
166
|
}
|
|
165
167
|
]
|
|
166
168
|
},
|
|
@@ -207,27 +207,22 @@ Default response mode for this project is **concise**. The `brand-voice` skill (
|
|
|
207
207
|
- Magic numbers/strings: use named constants.
|
|
208
208
|
- Mutable global state: use dependency injection instead.
|
|
209
209
|
|
|
210
|
-
## Source: `app/rules/common/git-
|
|
211
|
-
|
|
212
|
-
# Git Workflow Rules
|
|
210
|
+
## Source: `app/rules/common/git-team.md`
|
|
213
211
|
|
|
214
|
-
|
|
215
|
-
- Use conventional commits: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`.
|
|
216
|
-
- First line: imperative mood, max 72 chars (`feat: add user registration endpoint`).
|
|
217
|
-
- Body (optional): explain *why*, not *what*. The diff shows what.
|
|
218
|
-
- Reference tickets: `fix: prevent duplicate orders (PROJ-456)`.
|
|
212
|
+
# Git Team Workflow Rules
|
|
219
213
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
-
|
|
214
|
+
These rules assume more than one person merges into `main`. They ship only with
|
|
215
|
+
the `strict` profile; a solo maintainer who commits straight to `main` is not
|
|
216
|
+
doing anything wrong, and a reviewer that keeps flagging "use a feature branch"
|
|
217
|
+
in that setting is noise. The solo-safe core (commit format, no secrets, no
|
|
218
|
+
force-push) lives in `git-workflow`.
|
|
225
219
|
|
|
226
220
|
## Branching
|
|
227
|
-
- `main`
|
|
228
|
-
-
|
|
221
|
+
- Protect `main` with required reviews and CI. Never commit broken code to it.
|
|
222
|
+
- Work on feature branches: `feat/user-registration`, `fix/order-total-calc`.
|
|
223
|
+
- Rebase feature branches on `main` before opening a PR to keep linear history.
|
|
224
|
+
- Squash fixup commits before merging to keep history clean.
|
|
229
225
|
- Delete branches after merge. Stale branches are clutter.
|
|
230
|
-
- Rebase feature branches on main before PR to keep linear history.
|
|
231
226
|
|
|
232
227
|
## Pull Requests
|
|
233
228
|
- Keep PRs small: <400 lines changed. Split large features into stacked PRs.
|
|
@@ -240,6 +235,25 @@ Default response mode for this project is **concise**. The `brand-voice` skill (
|
|
|
240
235
|
- Approve with comments if nits only. Block for: bugs, security, missing tests.
|
|
241
236
|
- Respond to reviews within 24 hours. Do not let PRs rot.
|
|
242
237
|
|
|
238
|
+
## Source: `app/rules/common/git-workflow.md`
|
|
239
|
+
|
|
240
|
+
# Git Workflow Rules
|
|
241
|
+
|
|
242
|
+
Solo-safe core: everything here holds whether one person or twenty merge into
|
|
243
|
+
`main`. Branching, pull-request, and review conventions for teams live in
|
|
244
|
+
`git-team` and ship only with the `strict` profile.
|
|
245
|
+
|
|
246
|
+
## Commit Messages
|
|
247
|
+
- Use conventional commits: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`.
|
|
248
|
+
- First line: imperative mood, max 72 chars (`feat: add user registration endpoint`).
|
|
249
|
+
- Body (optional): explain *why*, not *what*. The diff shows what.
|
|
250
|
+
- Reference tickets: `fix: prevent duplicate orders (PROJ-456)`.
|
|
251
|
+
|
|
252
|
+
## Commit Practices
|
|
253
|
+
- Commit small, atomic changes. One commit = one logical change.
|
|
254
|
+
- Never commit: secrets, `.env` files, build artifacts, large binaries.
|
|
255
|
+
- `main` is always deployable: run the project's gates before every commit that lands there.
|
|
256
|
+
|
|
243
257
|
## Tags and Releases
|
|
244
258
|
- Use semantic versioning: MAJOR.MINOR.PATCH.
|
|
245
259
|
- Tag releases: `git tag v1.2.3`. Automate changelog from commits.
|
|
@@ -98,8 +98,15 @@ if [ -f .claude/test-cohesion-map.json ] || \
|
|
|
98
98
|
fi
|
|
99
99
|
|
|
100
100
|
if [ -f pyproject.toml ] || [ -f setup.py ]; then
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
# Lint only what the project itself configured. A bare pyproject.toml
|
|
102
|
+
# (build metadata, pytest/mypy tables) says nothing about ruff, and running
|
|
103
|
+
# `ruff check .` under whatever config the machine resolves turns the Stop
|
|
104
|
+
# gate red on findings the project never signed up for (v4.32.0 postmortem:
|
|
105
|
+
# 348 findings in a repo whose ruff rule set lives in a package.json script).
|
|
106
|
+
if [ -f ruff.toml ] || [ -f .ruff.toml ] || grep -qs '^\[tool\.ruff' pyproject.toml; then
|
|
107
|
+
if require_command ruff; then
|
|
108
|
+
run_required "ruff found errors" "head -30" ruff check .
|
|
109
|
+
fi
|
|
103
110
|
fi
|
|
104
111
|
if [ -d src ] && [ "$PROFILE" = "strict" ]; then
|
|
105
112
|
if require_command mypy; then
|
package/app/hooks.json
CHANGED
|
@@ -167,7 +167,8 @@
|
|
|
167
167
|
"hooks": [
|
|
168
168
|
{
|
|
169
169
|
"type": "command",
|
|
170
|
-
"command": "\"$HOME/.softspark/ai-toolkit/hooks/quality-check.sh\""
|
|
170
|
+
"command": "\"$HOME/.softspark/ai-toolkit/hooks/quality-check.sh\"",
|
|
171
|
+
"async": true
|
|
171
172
|
}
|
|
172
173
|
]
|
|
173
174
|
},
|
|
@@ -177,7 +178,8 @@
|
|
|
177
178
|
"hooks": [
|
|
178
179
|
{
|
|
179
180
|
"type": "command",
|
|
180
|
-
"command": "\"$HOME/.softspark/ai-toolkit/hooks/save-session.sh\""
|
|
181
|
+
"command": "\"$HOME/.softspark/ai-toolkit/hooks/save-session.sh\"",
|
|
182
|
+
"async": true
|
|
181
183
|
}
|
|
182
184
|
]
|
|
183
185
|
},
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
language: common
|
|
3
|
+
category: git-team
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
profiles:
|
|
6
|
+
- "strict"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Git Team Workflow Rules
|
|
10
|
+
|
|
11
|
+
These rules assume more than one person merges into `main`. They ship only with
|
|
12
|
+
the `strict` profile; a solo maintainer who commits straight to `main` is not
|
|
13
|
+
doing anything wrong, and a reviewer that keeps flagging "use a feature branch"
|
|
14
|
+
in that setting is noise. The solo-safe core (commit format, no secrets, no
|
|
15
|
+
force-push) lives in `git-workflow`.
|
|
16
|
+
|
|
17
|
+
## Branching
|
|
18
|
+
- Protect `main` with required reviews and CI. Never commit broken code to it.
|
|
19
|
+
- Work on feature branches: `feat/user-registration`, `fix/order-total-calc`.
|
|
20
|
+
- Rebase feature branches on `main` before opening a PR to keep linear history.
|
|
21
|
+
- Squash fixup commits before merging to keep history clean.
|
|
22
|
+
- Delete branches after merge. Stale branches are clutter.
|
|
23
|
+
|
|
24
|
+
## Pull Requests
|
|
25
|
+
- Keep PRs small: <400 lines changed. Split large features into stacked PRs.
|
|
26
|
+
- PR title follows conventional commit format.
|
|
27
|
+
- Include: summary, test plan, and screenshots/recordings for UI changes.
|
|
28
|
+
- Require at least one approval before merge.
|
|
29
|
+
|
|
30
|
+
## Code Review
|
|
31
|
+
- Review for: correctness, security, performance, readability.
|
|
32
|
+
- Approve with comments if nits only. Block for: bugs, security, missing tests.
|
|
33
|
+
- Respond to reviews within 24 hours. Do not let PRs rot.
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
language: common
|
|
3
3
|
category: git-workflow
|
|
4
|
-
version: "
|
|
4
|
+
version: "2.0.0"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Git Workflow Rules
|
|
8
8
|
|
|
9
|
+
Solo-safe core: everything here holds whether one person or twenty merge into
|
|
10
|
+
`main`. Branching, pull-request, and review conventions for teams live in
|
|
11
|
+
`git-team` and ship only with the `strict` profile.
|
|
12
|
+
|
|
9
13
|
## Commit Messages
|
|
10
14
|
- Use conventional commits: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`.
|
|
11
15
|
- First line: imperative mood, max 72 chars (`feat: add user registration endpoint`).
|
|
@@ -15,25 +19,7 @@ version: "1.0.0"
|
|
|
15
19
|
## Commit Practices
|
|
16
20
|
- Commit small, atomic changes. One commit = one logical change.
|
|
17
21
|
- Never commit: secrets, `.env` files, build artifacts, large binaries.
|
|
18
|
-
-
|
|
19
|
-
- Squash fixup commits before merging to keep history clean.
|
|
20
|
-
|
|
21
|
-
## Branching
|
|
22
|
-
- `main` is always deployable. Protect it with required reviews and CI.
|
|
23
|
-
- Feature branches: `feat/user-registration`, `fix/order-total-calc`.
|
|
24
|
-
- Delete branches after merge. Stale branches are clutter.
|
|
25
|
-
- Rebase feature branches on main before PR to keep linear history.
|
|
26
|
-
|
|
27
|
-
## Pull Requests
|
|
28
|
-
- Keep PRs small: <400 lines changed. Split large features into stacked PRs.
|
|
29
|
-
- PR title follows conventional commit format.
|
|
30
|
-
- Include: summary, test plan, and screenshots/recordings for UI changes.
|
|
31
|
-
- Require at least one approval before merge.
|
|
32
|
-
|
|
33
|
-
## Code Review
|
|
34
|
-
- Review for: correctness, security, performance, readability.
|
|
35
|
-
- Approve with comments if nits only. Block for: bugs, security, missing tests.
|
|
36
|
-
- Respond to reviews within 24 hours. Do not let PRs rot.
|
|
22
|
+
- `main` is always deployable: run the project's gates before every commit that lands there.
|
|
37
23
|
|
|
38
24
|
## Tags and Releases
|
|
39
25
|
- Use semantic versioning: MAJOR.MINOR.PATCH.
|
|
@@ -1,7 +1,31 @@
|
|
|
1
1
|
---
|
|
2
2
|
language: common
|
|
3
3
|
category: performance
|
|
4
|
-
version: "1.
|
|
4
|
+
version: "1.1.0"
|
|
5
|
+
paths:
|
|
6
|
+
- "**/*.py"
|
|
7
|
+
- "**/*.ts"
|
|
8
|
+
- "**/*.tsx"
|
|
9
|
+
- "**/*.js"
|
|
10
|
+
- "**/*.jsx"
|
|
11
|
+
- "**/*.mjs"
|
|
12
|
+
- "**/*.cjs"
|
|
13
|
+
- "**/*.go"
|
|
14
|
+
- "**/*.rs"
|
|
15
|
+
- "**/*.java"
|
|
16
|
+
- "**/*.kt"
|
|
17
|
+
- "**/*.kts"
|
|
18
|
+
- "**/*.swift"
|
|
19
|
+
- "**/*.dart"
|
|
20
|
+
- "**/*.cs"
|
|
21
|
+
- "**/*.php"
|
|
22
|
+
- "**/*.cpp"
|
|
23
|
+
- "**/*.cc"
|
|
24
|
+
- "**/*.cxx"
|
|
25
|
+
- "**/*.hpp"
|
|
26
|
+
- "**/*.h"
|
|
27
|
+
- "**/*.rb"
|
|
28
|
+
- "**/*.sql"
|
|
5
29
|
---
|
|
6
30
|
|
|
7
31
|
# Universal Performance Rules
|
|
@@ -125,6 +125,9 @@ def _summary(root: Path, all_files: list[Path]) -> tuple[int, int]:
|
|
|
125
125
|
|
|
126
126
|
def main() -> None:
|
|
127
127
|
"""Entry point: analyse directory and print text report to stdout."""
|
|
128
|
+
if len(sys.argv) > 1 and sys.argv[1] in ("-h", "--help"):
|
|
129
|
+
print("Usage: complexity.py [directory]\n\nReport per-file code complexity for directory (default: cwd).")
|
|
130
|
+
return
|
|
128
131
|
root = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else Path.cwd().resolve()
|
|
129
132
|
now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
130
133
|
|
|
@@ -16,6 +16,7 @@ Usage::
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
18
|
import json
|
|
19
|
+
import shutil
|
|
19
20
|
import subprocess
|
|
20
21
|
import sys
|
|
21
22
|
from datetime import datetime, timezone
|
|
@@ -50,12 +51,15 @@ def _git_branch() -> str:
|
|
|
50
51
|
|
|
51
52
|
|
|
52
53
|
def _docker_available() -> bool:
|
|
53
|
-
"""Return True if the ``docker`` command is on PATH.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
"""Return True if the ``docker`` command is on PATH.
|
|
55
|
+
|
|
56
|
+
``command -v`` is a shell builtin; running it through ``subprocess`` only
|
|
57
|
+
worked on macOS, which ships a ``/usr/bin/command`` binary. On Linux it
|
|
58
|
+
raised ``FileNotFoundError`` before any check ran (v4.32.1).
|
|
59
|
+
"""
|
|
60
|
+
if shutil.which("docker") is None:
|
|
61
|
+
return False
|
|
62
|
+
return _run(["docker", "--version"]).returncode == 0
|
|
59
63
|
|
|
60
64
|
|
|
61
65
|
def _docker_services_running() -> bool:
|
|
@@ -155,6 +159,9 @@ def _run_checks(env: str) -> _CheckCollector:
|
|
|
155
159
|
|
|
156
160
|
def main() -> None:
|
|
157
161
|
"""Entry point: run checks and print JSON result to stdout."""
|
|
162
|
+
if len(sys.argv) > 1 and sys.argv[1] in ("-h", "--help"):
|
|
163
|
+
print("Usage: pre_deploy_check.py [environment]\n\nRun pre-deployment checks for environment (default: staging) and print JSON.")
|
|
164
|
+
return
|
|
158
165
|
env = sys.argv[1] if len(sys.argv) > 1 else "staging"
|
|
159
166
|
branch = _git_branch()
|
|
160
167
|
collector = _run_checks(env)
|
|
@@ -130,6 +130,9 @@ def get_mtime(filepath: str) -> float:
|
|
|
130
130
|
|
|
131
131
|
|
|
132
132
|
def main():
|
|
133
|
+
if len(sys.argv) > 1 and sys.argv[1] in ("-h", "--help"):
|
|
134
|
+
print("Usage: doc-inventory.py [directory]\n\nInventory documentation files under directory (default: cwd) as JSON.")
|
|
135
|
+
return
|
|
133
136
|
root = os.path.abspath(sys.argv[1]) if len(sys.argv) > 1 else os.getcwd()
|
|
134
137
|
if not os.path.isdir(root):
|
|
135
138
|
print(json.dumps({"error": f"Not a directory: {root}"}))
|
|
@@ -159,6 +159,9 @@ def generate_mermaid(target_name: str, imports: list, imported_by: list) -> str:
|
|
|
159
159
|
|
|
160
160
|
|
|
161
161
|
def main():
|
|
162
|
+
if len(sys.argv) > 1 and sys.argv[1] in ("-h", "--help"):
|
|
163
|
+
print("Usage: dependency-graph.py <file_or_directory>\n\nPrint the import/dependency graph of a file or directory as JSON.")
|
|
164
|
+
return
|
|
162
165
|
if len(sys.argv) < 2:
|
|
163
166
|
print(json.dumps({"error": "Usage: dependency-graph.py <file_or_directory>"}))
|
|
164
167
|
sys.exit(1)
|
|
@@ -182,6 +182,9 @@ def detect(project_dir: Path) -> dict[str, object]:
|
|
|
182
182
|
|
|
183
183
|
def main() -> None:
|
|
184
184
|
"""Entry point: detect migration tool and print JSON result to stdout."""
|
|
185
|
+
if len(sys.argv) > 1 and sys.argv[1] in ("-h", "--help"):
|
|
186
|
+
print("Usage: migration-status.py [project_dir]\n\nDetect the migration tool in project_dir (default: cwd) and report its status as JSON.")
|
|
187
|
+
return
|
|
185
188
|
project_dir = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else Path.cwd()
|
|
186
189
|
if not project_dir.is_dir():
|
|
187
190
|
print(json.dumps({"error": f"Not a directory: {project_dir}"}))
|
|
@@ -154,6 +154,9 @@ def analyze_file(filepath: str, project_root: str) -> dict:
|
|
|
154
154
|
|
|
155
155
|
|
|
156
156
|
def main():
|
|
157
|
+
if len(sys.argv) > 1 and sys.argv[1] in ("-h", "--help"):
|
|
158
|
+
print("Usage: refactor-scan.py <file_or_directory>\n\nScan a file or directory for refactoring candidates and print JSON.")
|
|
159
|
+
return
|
|
157
160
|
if len(sys.argv) < 2:
|
|
158
161
|
print(json.dumps({"error": "Usage: refactor-scan.py <file_or_directory>"}))
|
|
159
162
|
sys.exit(1)
|