@softspark/ai-toolkit 4.16.0 → 4.16.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,15 @@ Versioning follows [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ---
9
9
 
10
+ ## v4.16.1 — Copilot skill remnant recovery (2026-07-24)
11
+
12
+ ### Fixed
13
+
14
+ - **Legacy Copilot skill remnants no longer abort local updates** — `.github/skills/ai-toolkit-*` directories left behind by pre-manifest cleanups (assets without `SKILL.md`) are rebuilt in place instead of raising `Refusing user-owned Copilot skill collision`, which aborted the entire `install --local` / `update` run on affected projects. User files inside a remnant that do not collide with generated output are preserved; any directory that still contains a `SKILL.md` stays protected and is never reclaimed.
15
+ - **Readable installer errors** — `scripts/install.py` reports fail-closed `RuntimeError` conditions as a single `ERROR:` line instead of a raw traceback.
16
+
17
+ Test count: 1477 → 1479.
18
+
10
19
  ## v4.16.0 — Native tool-output filtering (2026-07-24)
11
20
 
12
21
  Minor release. Adds a dependency-free, opt-in native tool-output filter for Claude Code and hardens the enterprise configuration, session-isolation, and editor-adapter surfaces around it. The filter ships disabled; `observe` and `safe` are per-project opt-ins. No source catalog count change (44 agents, 108 skills).
package/README.md CHANGED
@@ -6,17 +6,18 @@
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
7
  [![Skills](https://img.shields.io/badge/skills-108-brightgreen)](app/skills/)
8
8
  [![Agents](https://img.shields.io/badge/agents-44-blue)](app/agents/)
9
- [![Tests](https://img.shields.io/badge/tests-1477%20passing-success)](tests/)
9
+ [![Tests](https://img.shields.io/badge/tests-1479%20passing-success)](tests/)
10
10
 
11
- ## What's New in v4.16.0
11
+ ## What's New in v4.16.1
12
12
 
13
- v4.16.0 adds a dependency-free, opt-in native tool-output filter for Claude Code and hardens the enterprise configuration surface around it.
13
+ v4.16.1 ships the native tool-output filter introduced in v4.16.0 and fixes local updates crashing on legacy Copilot skill remnants.
14
14
 
15
15
  - **Native tool-output filter**: opt-in `PostToolUse` filter with `off`, `observe`, and `safe` modes; ships disabled, handles only allowlisted successful Bash test/validation output.
16
16
  - **Exact ephemeral recovery**: every safe replacement keeps a private, bounded, session-scoped copy of the original response, recoverable via `ai-toolkit output-filter recover`.
17
17
  - **Output-filter CLI**: `ai-toolkit output-filter status|inspect|recover|clean` plus a deterministic benchmark for the built-in profiles.
18
18
  - **Stricter config validation**: unknown top-level config keys are rejected, plugin manifests must declare `requires`, and lock files go stale on toolkit version bumps.
19
19
  - **GitHub Copilot compatibility reference**: new `kb/reference/copilot-compatibility.md` documenting the Copilot integration surface.
20
+ - **Copilot remnant recovery**: asset-only `.github/skills/ai-toolkit-*` leftovers from older cleanups are rebuilt in place instead of aborting `install --local` / `update`.
20
21
 
21
22
  See [CHANGELOG.md](CHANGELOG.md) for full history.
22
23
 
@@ -126,7 +127,7 @@ See [CLI Reference](kb/reference/cli-reference.md) for all commands and options.
126
127
  | Gemini CLI | `~/.gemini/GEMINI.md` | ✅ | global |
127
128
  | GitHub Copilot | Project: `AGENTS.md` + `.github/copilot-instructions.md` + `.github/{instructions,prompts,agents,skills,hooks}/` + `.github/mcp.json`; user: `$COPILOT_HOME/copilot-instructions.md` + `$COPILOT_HOME/{instructions,agents,skills,hooks}/` + `$COPILOT_HOME/mcp-config.json` | ✅ | project + user |
128
129
  | Cline | `~/Documents/Cline/Rules/*.md` + `~/.cline/skills/*` + `.clinerules/*.md` | — | global + project |
129
- | Roo Code | `~/.roo/rules/*.md` + `.roomodes` + `.roo/rules/*.md` | — | global rules + project |
130
+ | Roo Code / [Zoo Code](https://zoocode.dev/) | `~/.roo/rules/*.md` + `.roomodes` + `.roo/rules/*.md` | — | global rules + project |
130
131
  | Aider | `~/.aider.conf.yml` + `.aider.conf.yml` + `CONVENTIONS.md` | — | global + project |
131
132
  | Augment | `~/.augment/rules/*.md` + `.augment/rules/ai-toolkit-*.md` | ✅ | global + project |
132
133
  | Google Antigravity | `.agents/rules/*.md` + `.agents/workflows/*.md` + skill pointer in `.agent/skills/*` (IDE) and `.agents/skills/*` (CLI) | — | project |
@@ -169,7 +170,7 @@ ai-toolkit/
169
170
  │ └── ARCHITECTURE.md # Full system design
170
171
  ├── kb/ # Reference docs, procedures, plans
171
172
  ├── scripts/ # Validation, install, evaluation scripts
172
- ├── tests/ # Bats and Python test suite (1477 tests)
173
+ ├── tests/ # Bats and Python test suite (1479 tests)
173
174
  └── CHANGELOG.md
174
175
  ```
175
176
 
@@ -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.16.0",
6
+ "version": "4.16.1",
7
7
  "author": {
8
8
  "name": "SoftSpark",
9
9
  "url": "https://github.com/softspark"
package/manifest.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.16.0",
2
+ "version": "4.16.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.16.0",
3
+ "version": "4.16.1",
4
4
  "description": "AI coding toolkit: 108 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",
@@ -974,6 +974,23 @@ def _is_managed_skill_dir(path: Path) -> bool:
974
974
  return path.is_dir() and not path.is_symlink() and _is_managed(skill_file)
975
975
 
976
976
 
977
+ def _is_skill_remnant(path: Path) -> bool:
978
+ """Asset-only leftover of a legacy managed skill.
979
+
980
+ Pre-manifest toolkit versions tracked only SKILL.md as managed, so their
981
+ cleanup removed SKILL.md and left reference/ and scripts/ assets behind.
982
+ Without SKILL.md the directory is not a functional Copilot skill, so it is
983
+ safe to rebuild in place; a directory that still has any SKILL.md (managed
984
+ or not) is never classified as a remnant.
985
+ """
986
+ return (
987
+ path.is_dir()
988
+ and not path.is_symlink()
989
+ and not (path / "SKILL.md").exists()
990
+ and not (path / "SKILL.md").is_symlink()
991
+ )
992
+
993
+
977
994
  def _managed_skill_paths(path: Path) -> set[Path]:
978
995
  manifest = path / SKILL_MANIFEST
979
996
  if not manifest.is_file() or manifest.is_symlink():
@@ -999,7 +1016,8 @@ def _has_user_skill_extras(path: Path) -> bool:
999
1016
 
1000
1017
 
1001
1018
  def _copy_user_skill_extras(existing: Path, staging: Path,
1002
- generated_paths: set[Path]) -> None:
1019
+ generated_paths: set[Path],
1020
+ *, skip_stale_assets: bool = False) -> None:
1003
1021
  """Preserve files a user added inside a previously managed skill."""
1004
1022
  old_managed = _managed_skill_paths(existing)
1005
1023
  for source in sorted(existing.rglob("*")):
@@ -1011,6 +1029,8 @@ def _copy_user_skill_extras(existing: Path, staging: Path,
1011
1029
  if not source.is_file():
1012
1030
  continue
1013
1031
  if relative in generated_paths:
1032
+ if skip_stale_assets:
1033
+ continue
1014
1034
  raise RuntimeError(
1015
1035
  f"Copilot skill update would overwrite a user asset: {source}"
1016
1036
  )
@@ -1046,7 +1066,10 @@ def _stage_skill(skills_root: Path, source_dir: Path,
1046
1066
  encoding="utf-8",
1047
1067
  )
1048
1068
  if existing is not None:
1049
- _copy_user_skill_extras(existing, staging, generated_paths)
1069
+ _copy_user_skill_extras(
1070
+ existing, staging, generated_paths,
1071
+ skip_stale_assets=_is_skill_remnant(existing),
1072
+ )
1050
1073
  return staging, name
1051
1074
  except Exception:
1052
1075
  shutil.rmtree(staging, ignore_errors=True)
@@ -1058,7 +1081,10 @@ def _replace_skill_dir(staging: Path, destination: Path) -> None:
1058
1081
  backup: Path | None = None
1059
1082
  try:
1060
1083
  if destination.exists():
1061
- if destination.is_symlink() or not _is_managed_skill_dir(destination):
1084
+ if destination.is_symlink() or not (
1085
+ _is_managed_skill_dir(destination)
1086
+ or _is_skill_remnant(destination)
1087
+ ):
1062
1088
  raise RuntimeError(
1063
1089
  f"Refusing user-owned Copilot skill collision: {destination}"
1064
1090
  )
@@ -1125,7 +1151,12 @@ def _sync_copilot_skills(customization_root: Path, *, label: str) -> None:
1125
1151
  expected_dirs.add(destination_name)
1126
1152
  existing = destination if destination.exists() else None
1127
1153
  if existing is not None and not _is_managed_skill_dir(existing):
1128
- raise RuntimeError(f"Refusing user-owned Copilot skill collision: {destination}")
1154
+ if not _is_skill_remnant(existing):
1155
+ raise RuntimeError(f"Refusing user-owned Copilot skill collision: {destination}")
1156
+ print(
1157
+ f"Note: rebuilding asset-only Copilot skill remnant '{destination}'",
1158
+ file=sys.stderr,
1159
+ )
1129
1160
  staging, rendered_name = _stage_skill(skill_root, source_dir, existing)
1130
1161
  if rendered_name != logical_name:
1131
1162
  shutil.rmtree(staging, ignore_errors=True)
@@ -841,4 +841,8 @@ def _infer_modules_from_legacy(profile: str, only: str) -> list[str]:
841
841
 
842
842
 
843
843
  if __name__ == "__main__":
844
- main()
844
+ try:
845
+ main()
846
+ except RuntimeError as error:
847
+ print(f"ERROR: {error}", file=sys.stderr)
848
+ sys.exit(1)