@axiomatic-labs/claudeflow 2.50.5 → 2.51.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/lib/install.js +56 -1
- package/package.json +1 -1
package/lib/install.js
CHANGED
|
@@ -439,11 +439,13 @@ function pathHash(p) {
|
|
|
439
439
|
}
|
|
440
440
|
|
|
441
441
|
function syncManagedGlobalDir(srcDir, dstDir, backupRoot, filter, label) {
|
|
442
|
-
const out = { synced: 0, changed: 0, backups: 0, failed: 0, failures: [] };
|
|
442
|
+
const out = { synced: 0, changed: 0, removed: 0, backups: 0, failed: 0, failures: [] };
|
|
443
443
|
if (!fs.existsSync(srcDir)) return out;
|
|
444
444
|
fs.mkdirSync(dstDir, { recursive: true });
|
|
445
|
+
const shipped = new Set();
|
|
445
446
|
for (const e of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
446
447
|
if (!filter(e)) continue;
|
|
448
|
+
shipped.add(e.name);
|
|
447
449
|
const s = path.join(srcDir, e.name);
|
|
448
450
|
const d = path.join(dstDir, e.name);
|
|
449
451
|
try {
|
|
@@ -461,6 +463,26 @@ function syncManagedGlobalDir(srcDir, dstDir, backupRoot, filter, label) {
|
|
|
461
463
|
out.failures.push(`${label}:${e.name}:${err && err.code ? err.code : 'ERROR'}`);
|
|
462
464
|
}
|
|
463
465
|
}
|
|
466
|
+
// Prune orphans: a global claudeflow-* that is NO LONGER shipped (a removed or renamed skill/agent, e.g.
|
|
467
|
+
// claudeflow-method-bdd-lite after its merge into atdd-lite) must be DELETED, not left behind. Claude
|
|
468
|
+
// prioritizes ~/.claude over the project copy, so a stale global artifact silently shadows the current set —
|
|
469
|
+
// the exact redundancy where a deleted skill keeps loading. Overwriting the shipped ones is not enough; the
|
|
470
|
+
// set must MIRROR what ships. Only the managed claudeflow-* namespace is pruned (filter gates it); the user's
|
|
471
|
+
// own skills/agents never match the filter and are untouched. Backed up first, like every managed change.
|
|
472
|
+
for (const e of fs.readdirSync(dstDir, { withFileTypes: true })) {
|
|
473
|
+
if (!filter(e) || shipped.has(e.name)) continue;
|
|
474
|
+
const d = path.join(dstDir, e.name);
|
|
475
|
+
try {
|
|
476
|
+
copyPath(d, path.join(backupRoot, path.basename(dstDir), e.name));
|
|
477
|
+
out.backups++;
|
|
478
|
+
fs.rmSync(d, { recursive: true, force: true });
|
|
479
|
+
out.removed++;
|
|
480
|
+
out.changed++;
|
|
481
|
+
} catch (err) {
|
|
482
|
+
out.failed++;
|
|
483
|
+
out.failures.push(`${label}:prune:${e.name}:${err && err.code ? err.code : 'ERROR'}`);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
464
486
|
return out;
|
|
465
487
|
}
|
|
466
488
|
|
|
@@ -506,6 +528,31 @@ function countFiles(dir) {
|
|
|
506
528
|
return n;
|
|
507
529
|
}
|
|
508
530
|
|
|
531
|
+
// Remove managed (claudeflow-*) artifacts present in dst but NO LONGER shipped in src — a removed or renamed
|
|
532
|
+
// skill/agent must disappear, not linger. Overwriting the shipped set is not enough: a leftover copy (project OR
|
|
533
|
+
// global) keeps being discovered and loaded, the redundancy that let a deleted skill keep running. The filter
|
|
534
|
+
// gates the managed namespace, so the user's OWN skills/agents never match and are untouched. Backs up first.
|
|
535
|
+
function pruneManagedOrphans(srcDir, dstDir, filter, backupRoot, label) {
|
|
536
|
+
const out = { removed: 0, backups: 0, failed: 0, failures: [] };
|
|
537
|
+
if (!fs.existsSync(srcDir) || !fs.existsSync(dstDir)) return out;
|
|
538
|
+
const shipped = new Set();
|
|
539
|
+
for (const e of fs.readdirSync(srcDir, { withFileTypes: true })) if (filter(e)) shipped.add(e.name);
|
|
540
|
+
for (const e of fs.readdirSync(dstDir, { withFileTypes: true })) {
|
|
541
|
+
if (!filter(e) || shipped.has(e.name)) continue;
|
|
542
|
+
const d = path.join(dstDir, e.name);
|
|
543
|
+
try {
|
|
544
|
+
copyPath(d, path.join(backupRoot, path.basename(dstDir), e.name));
|
|
545
|
+
out.backups++;
|
|
546
|
+
fs.rmSync(d, { recursive: true, force: true });
|
|
547
|
+
out.removed++;
|
|
548
|
+
} catch (err) {
|
|
549
|
+
out.failed++;
|
|
550
|
+
out.failures.push(`${label}:prune:${e.name}:${err && err.code ? err.code : 'ERROR'}`);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return out;
|
|
554
|
+
}
|
|
555
|
+
|
|
509
556
|
function mergeSettings(cwd, payloadSettings) {
|
|
510
557
|
const sp = path.join(cwd, '.claude', 'settings.json');
|
|
511
558
|
let data = {};
|
|
@@ -908,6 +955,8 @@ function installFromPayload(src, cwd, options = {}) {
|
|
|
908
955
|
const d = path.join(dst, e.name);
|
|
909
956
|
if (replace(path.join(srcSkills, e.name), d, cwd, `skills:${e.name}`)) out.skills++;
|
|
910
957
|
}
|
|
958
|
+
out.obsoleteRemoved += pruneManagedOrphans(srcSkills, dst,
|
|
959
|
+
e => e.isDirectory() && e.name.startsWith('claudeflow-'), backupRoot, 'skills').removed;
|
|
911
960
|
}
|
|
912
961
|
});
|
|
913
962
|
|
|
@@ -921,6 +970,8 @@ function installFromPayload(src, cwd, options = {}) {
|
|
|
921
970
|
if (!e.isFile() || !e.name.startsWith('claudeflow-') || !e.name.endsWith('.md')) continue;
|
|
922
971
|
if (replace(path.join(srcAgents, e.name), path.join(dst, e.name), cwd, `agents:${e.name}`)) out.agents++;
|
|
923
972
|
}
|
|
973
|
+
out.obsoleteRemoved += pruneManagedOrphans(srcAgents, dst,
|
|
974
|
+
e => e.isFile() && e.name.startsWith('claudeflow-') && e.name.endsWith('.md'), backupRoot, 'agents').removed;
|
|
924
975
|
}
|
|
925
976
|
});
|
|
926
977
|
|
|
@@ -952,6 +1003,8 @@ function installFromPayload(src, cwd, options = {}) {
|
|
|
952
1003
|
const d = path.join(dst, e.name);
|
|
953
1004
|
if (replace(path.join(srcSkills, e.name), d, cwd, `codex-skills:${e.name}`)) out.codexSkills++;
|
|
954
1005
|
}
|
|
1006
|
+
out.obsoleteRemoved += pruneManagedOrphans(srcSkills, dst,
|
|
1007
|
+
e => e.isDirectory() && e.name.startsWith('claudeflow-'), backupRoot, 'codex-skills').removed;
|
|
955
1008
|
}
|
|
956
1009
|
});
|
|
957
1010
|
|
|
@@ -965,6 +1018,8 @@ function installFromPayload(src, cwd, options = {}) {
|
|
|
965
1018
|
if (!e.isFile() || !e.name.startsWith('claudeflow-') || !e.name.endsWith('.toml')) continue;
|
|
966
1019
|
if (replace(path.join(srcAgents, e.name), path.join(dst, e.name), cwd, `codex-agents:${e.name}`)) out.codexAgents++;
|
|
967
1020
|
}
|
|
1021
|
+
out.obsoleteRemoved += pruneManagedOrphans(srcAgents, dst,
|
|
1022
|
+
e => e.isFile() && e.name.startsWith('claudeflow-') && e.name.endsWith('.toml'), backupRoot, 'codex-agents').removed;
|
|
968
1023
|
}
|
|
969
1024
|
});
|
|
970
1025
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axiomatic-labs/claudeflow",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.51.0",
|
|
4
4
|
"description": "Claudeflow — AI-powered development toolkit for Claude Code and Codex. Skills, agents, hooks, and quality gates that ship production apps.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"claudeflow": "./bin/cli.js"
|