Skip to content

Commit e55a86b

Browse files
authored
Merge pull request #68 from ColdBox/copilot/fix-coldbox-ai-skills-remove
fix: prevent auto-reinstall of explicitly removed skills on refresh
2 parents ca7d030 + 029efb4 commit e55a86b

2 files changed

Lines changed: 36 additions & 0 deletions

File tree

‎changelog.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616
- `AIService.diagnose()` now uses the `static.AI_DIR` constant (`.agents`) instead of the hardcoded `/.ai` path
1717
- `coldbox ai uninstall` now correctly checks, removes, and references the `.agents` directory
1818
- `coldbox ai skills add slug --list` was not working.
19+
- **`coldbox ai skills remove` reinstalling removed skills during refresh**
20+
- When a skill was removed via `coldbox ai skills remove`, the subsequent agent config regeneration step (`refresh()`) would detect the skill as "missing" (because its module dependency was still present in `box.json`) and immediately reinstall it
21+
- Removed skills are now tracked in a new `manifest.excludes[]` array so that `refresh()` will never auto-reinstall them
22+
- Explicitly re-installing a previously excluded skill via `coldbox ai skills install` lifts the exclusion and restores normal auto-management
1923

2024
### Added
2125

‎models/SkillManager.cfc‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ component singleton {
186186
// Ensure customSkills key exists (backwards compatibility with old manifests)
187187
ensureCustomSkillsSection( arguments.manifest )
188188

189+
// Ensure excludes key exists (backwards compatibility with old manifests)
190+
ensureExcludesSection( arguments.manifest )
191+
189192
// ------------------------------------------------------------------
190193
// 0. Install missing desired skills (core + module) not yet in manifest
191194
// ------------------------------------------------------------------
@@ -195,6 +198,10 @@ component singleton {
195198
);
196199

197200
var missingDesiredSkills = desiredTargets.filter( ( t ) => {
201+
// Skip skills the user has explicitly excluded
202+
if ( arguments.manifest.excludes.findNoCase( t.name ) ) {
203+
return false;
204+
}
198205
return !manifest.skills
199206
.filter( ( s ) => {
200207
return ( s.owner == t.owner && s.repo == t.repo && s.slug == t.slug );
@@ -828,6 +835,13 @@ component singleton {
828835
if ( structKeyExists( manifest, "customSkills" ) ) {
829836
manifest.customSkills = manifest.customSkills.filter( ( s ) => s.name != name )
830837
}
838+
839+
// Track the explicit exclusion so refresh() does not auto-reinstall it
840+
ensureExcludesSection( manifest )
841+
if ( !manifest.excludes.findNoCase( arguments.name ) ) {
842+
manifest.excludes.append( arguments.name )
843+
}
844+
831845
variables.aiService.saveManifest( arguments.directory, manifest )
832846

833847
return true
@@ -1345,6 +1359,10 @@ component singleton {
13451359
arguments.manifest.skills.append( entry )
13461360
}
13471361

1362+
// If this skill was previously excluded, lift the exclusion now that it is being explicitly installed
1363+
ensureExcludesSection( arguments.manifest )
1364+
arguments.manifest.excludes = arguments.manifest.excludes.filter( ( excludedName ) => !excludedName.equalsIgnoreCase( resolvedName ) )
1365+
13481366
return resolvedName
13491367
}
13501368

@@ -1397,6 +1415,20 @@ component singleton {
13971415
}
13981416
}
13991417

1418+
/**
1419+
* Ensure manifest has an excludes array (backwards compatibility).
1420+
* The excludes array holds skill names that the user explicitly removed and
1421+
* should never be auto-reinstalled by refresh().
1422+
* Mutates manifest in place.
1423+
*
1424+
* @manifest The manifest struct to ensure has an excludes key
1425+
*/
1426+
private function ensureExcludesSection( required struct manifest ){
1427+
if ( !structKeyExists( arguments.manifest, "excludes" ) ) {
1428+
arguments.manifest[ "excludes" ] = []
1429+
}
1430+
}
1431+
14001432
/**
14011433
* Delete a skill directory under .ai/skills/ if it exists.
14021434
*

0 commit comments

Comments
 (0)