@axiomatic-labs/claudeflow 2.49.31 → 2.49.33

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.
Files changed (2) hide show
  1. package/lib/install.js +75 -3
  2. package/package.json +1 -1
package/lib/install.js CHANGED
@@ -27,7 +27,19 @@ const PER_PROJECT_CONFIGS = ['brand.json', 'risk-signals.json', 'test-context.js
27
27
  // Paths appended to the project's .gitignore (add-if-absent). These hold TEST credentials / Playwright
28
28
  // storage state — they must NEVER be committed. test-context.json is per-project runtime state; .auth/
29
29
  // holds storageState files the orchestrator seeds for auth-gated functional verification.
30
- const GITIGNORE_LINES = ['__pycache__/', '*.pyc', '.claudeflow/test-context.json', '.claudeflow/.auth/', '.claudeflow/telemetry/', '.claudeflow/certification/', '.claudeflow/tools/', '.claudeflow/backups/'];
30
+ const GITIGNORE_LINES = [
31
+ '__pycache__/',
32
+ '*.pyc',
33
+ '.claudeflow/test-context.json',
34
+ '.claudeflow/.auth/',
35
+ '.claudeflow/telemetry/',
36
+ '.claudeflow/certification/',
37
+ '.claudeflow/headless-e2e/',
38
+ '.claudeflow/headless-claude/',
39
+ '.claudeflow/e2e-runs/',
40
+ '.claudeflow/tools/',
41
+ '.claudeflow/backups/',
42
+ ];
31
43
  const SHARED_CONFIGS = ['playbook-map.json', 'agent-map.json']; // always refreshed (shared system)
32
44
  const CODEX_DOCS = ['claudeflow-codex-migration.md', 'codexflow-codex-native-workflow.md', 'codexflow-local-actions.md'];
33
45
 
@@ -623,8 +635,8 @@ function mergeCodexMarketplace(cwd, payloadMarketplace) {
623
635
  return true;
624
636
  }
625
637
 
626
- // Seed the BASE MCP server set (playwright for visual QA / browser_verification, context7 for live library
627
- // docs during Discover, chrome-devtools for Chrome DevTools inspection) into the project's root `.mcp.json`.
638
+ // Seed the BASE MCP server set (context7 for live library docs during Discover, chrome-devtools for Chrome
639
+ // DevTools inspection) into the project's root `.mcp.json`.
628
640
  // ADD-IF-ABSENT by server key: create the file if missing, else merge in only the keys the user doesn't
629
641
  // already have (never clobber a server they configured). A corrupt/unexpected `.mcp.json` is left untouched
630
642
  // (don't risk eating the user's servers). Returns the number of servers added (0 = nothing to do). Like the
@@ -644,6 +656,53 @@ function mergeMcp(cwd, baseServers) {
644
656
  return added;
645
657
  }
646
658
 
659
+ function isManagedPlaywrightMcp(server) {
660
+ const args = Array.isArray(server && server.args) ? server.args.join(' ') : '';
661
+ return Boolean(server && String(server.command || '').includes('npx') && args.includes('@playwright/mcp'));
662
+ }
663
+
664
+ function pruneManagedPlaywrightMcpFile(mp) {
665
+ if (!fs.existsSync(mp)) return false;
666
+ let data = {};
667
+ try { data = JSON.parse(fs.readFileSync(mp, 'utf8')); } catch { return false; }
668
+ if (typeof data !== 'object' || data === null || Array.isArray(data)) return false;
669
+ const servers = data.mcpServers;
670
+ if (!servers || !isManagedPlaywrightMcp(servers.playwright)) return false;
671
+ delete servers.playwright;
672
+ fs.writeFileSync(mp, JSON.stringify(data, null, 2) + '\n');
673
+ return true;
674
+ }
675
+
676
+ function pruneManagedPlaywrightMcp(cwd) {
677
+ return pruneManagedPlaywrightMcpFile(path.join(cwd, '.mcp.json'));
678
+ }
679
+
680
+ function pruneManagedPlaywrightCodexConfigFile(cp) {
681
+ if (!fs.existsSync(cp)) return false;
682
+ const before = fs.readFileSync(cp, 'utf8');
683
+ const range = tomlSectionRange(before, 'mcp_servers.playwright');
684
+ if (!range) return false;
685
+ const section = before.slice(range.start, range.end);
686
+ if (!section.includes('@playwright/mcp')) return false;
687
+ const updated = (before.slice(0, range.start) + before.slice(range.end)).replace(/\n{3,}/g, '\n\n').replace(/\s*$/, '\n');
688
+ fs.writeFileSync(cp, updated);
689
+ return true;
690
+ }
691
+
692
+ function pruneManagedPlaywrightCodexConfig(cwd) {
693
+ return pruneManagedPlaywrightCodexConfigFile(path.join(cwd, '.codex', 'config.toml'));
694
+ }
695
+
696
+ function pruneGlobalManagedPlaywrightMcp(homeDir) {
697
+ const home = homeDir || os.homedir();
698
+ let changed = 0;
699
+ if (pruneManagedPlaywrightMcpFile(path.join(home, '.mcp.json'))) changed++;
700
+ if (pruneManagedPlaywrightMcpFile(path.join(home, '.claude', 'mcp-configs', 'mcp-servers.json'))) changed++;
701
+ if (pruneManagedPlaywrightCodexConfigFile(path.join(home, '.claude', '.codex', 'config.toml'))) changed++;
702
+ if (pruneManagedPlaywrightCodexConfigFile(path.join(home, '.codex', 'config.toml'))) changed++;
703
+ return changed;
704
+ }
705
+
647
706
  // Append the claudeflow runtime/cache paths to the project's .gitignore, ADD-IF-ABSENT. These hold TEST
648
707
  // credentials / Playwright storage state and Python hook bytecode; they must never be committed. Create the file if missing; else
649
708
  // append only the lines NOT already present as an EXACT line (a `Set.has()` on the trimmed existing lines —
@@ -714,16 +773,19 @@ function installFromPayload(src, cwd, options = {}) {
714
773
  globalAgents: 0,
715
774
  globalChanged: 0,
716
775
  globalBackups: 0,
776
+ globalMcpPruned: 0,
717
777
  localBackups: 0,
718
778
  ownershipRepaired: 0,
719
779
  codexSkills: 0,
720
780
  codexAgents: 0,
721
781
  codexHooks: false,
722
782
  codexConfig: false,
783
+ codexConfigPruned: false,
723
784
  codexMarketplace: false,
724
785
  codexPlugin: 0,
725
786
  docs: 0,
726
787
  mcp: 0,
788
+ mcpPruned: false,
727
789
  serenaMcp: 0,
728
790
  serenaCodexConfig: false,
729
791
  tooling: {},
@@ -834,6 +896,7 @@ function installFromPayload(src, cwd, options = {}) {
834
896
  out.globalAgents = r.agents;
835
897
  out.globalChanged = r.changed;
836
898
  out.globalBackups = r.backups;
899
+ out.globalMcpPruned = pruneGlobalManagedPlaywrightMcp(options.globalHome || os.homedir());
837
900
  if (r.failed) {
838
901
  out.failed.push(`global-claude-artifacts:${r.failed}`);
839
902
  for (const f of r.failures || []) out.failed.push(f);
@@ -882,6 +945,9 @@ function installFromPayload(src, cwd, options = {}) {
882
945
  });
883
946
 
884
947
  // 7) .mcp.json — seed the base MCP servers (add-if-absent; never clobber the user's own servers).
948
+ step('mcp-prune-playwright', () => {
949
+ out.mcpPruned = pruneManagedPlaywrightMcp(cwd);
950
+ });
885
951
  step('mcp', () => {
886
952
  const srcMcp = path.join(src, 'assets', 'mcp.base.json');
887
953
  if (fs.existsSync(srcMcp)) {
@@ -910,6 +976,7 @@ function installFromPayload(src, cwd, options = {}) {
910
976
  if (fs.existsSync(srcHooks)) out.codexHooks = mergeCodexHooks(cwd, JSON.parse(fs.readFileSync(srcHooks, 'utf8')));
911
977
  });
912
978
  step('codex-config', () => {
979
+ out.codexConfigPruned = pruneManagedPlaywrightCodexConfig(cwd);
913
980
  const srcConfig = path.join(src, '.codex', 'config.toml');
914
981
  if (fs.existsSync(srcConfig)) out.codexConfig = mergeCodexConfig(cwd, fs.readFileSync(srcConfig, 'utf8'));
915
982
  });
@@ -1025,12 +1092,14 @@ async function run() {
1025
1092
  + (summary.globalBackups ? `, ${summary.globalBackups} backups` : '')
1026
1093
  + ')'
1027
1094
  : '')
1095
+ + (summary.globalMcpPruned ? ` · global Playwright MCP removed (${summary.globalMcpPruned})` : '')
1028
1096
  + (summary.localBackups ? ` · ${summary.localBackups} local stale path${summary.localBackups > 1 ? 's' : ''} moved to backup` : '')
1029
1097
  + (summary.ownershipRepaired ? ` · ownership restored on ${summary.ownershipRepaired} path${summary.ownershipRepaired > 1 ? 's' : ''}` : '')
1030
1098
  + (summary.codexSkills ? ` · ${summary.codexSkills} Codex skills` : '')
1031
1099
  + (summary.codexAgents ? ` · ${summary.codexAgents} Codex agents` : '')
1032
1100
  + (summary.codexHooks ? ' · Codex hooks merged' : '')
1033
1101
  + (summary.codexConfig ? ' · Codex config synced' : '')
1102
+ + (summary.mcpPruned || summary.codexConfigPruned ? ' · Playwright MCP removed' : '')
1034
1103
  + (summary.tooling && summary.tooling.serena && summary.tooling.serena.status === 'ready' ? ' · Serena ready' : '')
1035
1104
  + (summary.tooling && summary.tooling.astGrep && summary.tooling.astGrep.status === 'ready' ? ' · ast-grep ready' : '')
1036
1105
  + (summary.serenaMcp || summary.serenaCodexConfig ? ' · Serena MCP configured' : '')
@@ -1061,6 +1130,9 @@ module.exports.syncClaudeMd = syncClaudeMd;
1061
1130
  module.exports.syncAgentsMd = syncAgentsMd;
1062
1131
  module.exports.syncGlobalClaudeArtifacts = syncGlobalClaudeArtifacts;
1063
1132
  module.exports.mergeMcp = mergeMcp;
1133
+ module.exports.pruneManagedPlaywrightMcp = pruneManagedPlaywrightMcp;
1134
+ module.exports.pruneManagedPlaywrightCodexConfig = pruneManagedPlaywrightCodexConfig;
1135
+ module.exports.pruneGlobalManagedPlaywrightMcp = pruneGlobalManagedPlaywrightMcp;
1064
1136
  module.exports.mergeGitignore = mergeGitignore;
1065
1137
  module.exports.mergeCodexHooks = mergeCodexHooks;
1066
1138
  module.exports.mergeCodexConfig = mergeCodexConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axiomatic-labs/claudeflow",
3
- "version": "2.49.31",
3
+ "version": "2.49.33",
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"