@silasfmartins/testhub 1.0.0 → 1.0.2

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.
@@ -80,7 +80,7 @@ Nao documenta detalhes do **Portal/UI** nem changelog por versao. Para isso, use
80
80
  - `McpLocalClient` deve tentar iniciar STDIO automaticamente em ordem:
81
81
  1. `HUB_MCP_STDIO_BIN` (quando definido),
82
82
  2. `autocore-hub-mcp` global,
83
- 3. `npx -y @silasfmartins/testhub-orchestrator-mcp --stdio`.
83
+ 3. `npx -y @silasfmartins/autocore-orchestrator-mcp --stdio`.
84
84
  - Em `tools/list`, expor somente `codegen`; manter `playwright_execute` apenas como alias de compatibilidade em `tools/call` (sem aparecer na listagem).
85
85
  - No `consumer-postinstall` do framework (Windows local), configurar AutoStart do MCP automaticamente apos a instalacao:
86
86
  - usar Startup do usuario (`%APPDATA%\\...\\Startup`) sem depender de Task Scheduler,
@@ -118,7 +118,7 @@ function isExtensionInstalled(extensionId) {
118
118
  }
119
119
  // 🌐 Registry privado do Azure Artifacts (único registry para pacotes @rbqa)
120
120
  const AZURE_REGISTRY = "https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/";
121
- const WINDOWS_MCP_AUTOSTART_START_COMMAND = "npx -y @silasfmartins/testhub-orchestrator-mcp";
121
+ const WINDOWS_MCP_AUTOSTART_START_COMMAND = "npx -y @silasfmartins/autocore-orchestrator-mcp";
122
122
  const WINDOWS_MCP_STARTUP_SCRIPT_FILE = "autocore-orchestrator-mcp.cmd";
123
123
  const WINDOWS_MCP_STARTUP_VBS_FILE = "autocore-orchestrator-mcp.vbs";
124
124
  /**
@@ -157,11 +157,11 @@ async function execNpmCommand(command, timeoutMs = 30000) {
157
157
  */
158
158
  async function getInstalledMcpVersion() {
159
159
  try {
160
- const result = await execNpmCommand("npm list -g @silasfmartins/testhub-orchestrator-mcp --depth=0 --json");
160
+ const result = await execNpmCommand("npm list -g @silasfmartins/autocore-orchestrator-mcp --depth=0 --json");
161
161
  if (!result)
162
162
  return null;
163
163
  const data = JSON.parse(result.stdout);
164
- return (data.dependencies?.["@silasfmartins/testhub-orchestrator-mcp"]?.version || null);
164
+ return (data.dependencies?.["@silasfmartins/autocore-orchestrator-mcp"]?.version || null);
165
165
  }
166
166
  catch {
167
167
  return null;
@@ -173,7 +173,7 @@ async function getInstalledMcpVersion() {
173
173
  */
174
174
  async function getLatestMcpVersion() {
175
175
  try {
176
- const result = await execNpmCommand(`npm view @silasfmartins/testhub-orchestrator-mcp version --registry=${AZURE_REGISTRY}`, 30000);
176
+ const result = await execNpmCommand(`npm view @silasfmartins/autocore-orchestrator-mcp version --registry=${AZURE_REGISTRY}`, 30000);
177
177
  if (!result)
178
178
  return null;
179
179
  return result.stdout.trim() || null;
@@ -183,13 +183,13 @@ async function getLatestMcpVersion() {
183
183
  }
184
184
  }
185
185
  /**
186
- * 🔍 Verifica se o pacote @silasfmartins/testhub-orchestrator-mcp está instalado globalmente
186
+ * 🔍 Verifica se o pacote @silasfmartins/autocore-orchestrator-mcp está instalado globalmente
187
187
  */
188
188
  async function isMcpPackageInstalled() {
189
189
  try {
190
- const result = await execNpmCommand("npm list -g @silasfmartins/testhub-orchestrator-mcp --depth=0");
190
+ const result = await execNpmCommand("npm list -g @silasfmartins/autocore-orchestrator-mcp --depth=0");
191
191
  return result
192
- ? result.stdout.includes("@silasfmartins/testhub-orchestrator-mcp")
192
+ ? result.stdout.includes("@silasfmartins/autocore-orchestrator-mcp")
193
193
  : false;
194
194
  }
195
195
  catch {
@@ -203,7 +203,7 @@ async function isMcpPackageInstalled() {
203
203
  async function checkRegistryAccess() {
204
204
  try {
205
205
  // Tenta obter a versão do pacote no Azure Artifacts
206
- const result = await execNpmCommand(`npm view @silasfmartins/testhub-orchestrator-mcp version --registry=${AZURE_REGISTRY}`, 30000);
206
+ const result = await execNpmCommand(`npm view @silasfmartins/autocore-orchestrator-mcp version --registry=${AZURE_REGISTRY}`, 30000);
207
207
  if (result && result.stdout.trim()) {
208
208
  return result.stdout.trim();
209
209
  }
@@ -214,7 +214,7 @@ async function checkRegistryAccess() {
214
214
  }
215
215
  }
216
216
  /**
217
- * 📦 Instala ou atualiza o pacote @silasfmartins/testhub-orchestrator-mcp globalmente
217
+ * 📦 Instala ou atualiza o pacote @silasfmartins/autocore-orchestrator-mcp globalmente
218
218
  *
219
219
  * 🎯 COMPORTAMENTO:
220
220
  * - Se já está na última versão: NÃO reinstala (economia de tempo)
@@ -242,7 +242,6 @@ async function installMcpPackageGlobally() {
242
242
  console.log("🆕 MCP não encontrado globalmente");
243
243
  }
244
244
  // 2️⃣ Verificar acesso ao registry e obter última versão
245
- console.log("🔍 Verificando registry Azure Artifacts...");
246
245
  const latestVersion = await checkRegistryAccess();
247
246
  if (!latestVersion) {
248
247
  console.log("🔒 Sem acesso ao registry Azure Artifacts (modo offline)");
@@ -252,7 +251,7 @@ async function installMcpPackageGlobally() {
252
251
  }
253
252
  console.log("⚠️ O MCP será executado via npx quando necessário");
254
253
  console.log(" 💡 Conecte-se à VPN e execute:");
255
- console.log(` npm install -g @silasfmartins/testhub-orchestrator-mcp --registry=${AZURE_REGISTRY}`);
254
+ console.log(` npm install -g @silasfmartins/autocore-orchestrator-mcp --registry=${AZURE_REGISTRY}`);
256
255
  return false;
257
256
  }
258
257
  console.log(`🌐 Última versão disponível: ${latestVersion}`);
@@ -270,7 +269,7 @@ async function installMcpPackageGlobally() {
270
269
  console.log("🔄 Instalando MCP globalmente...");
271
270
  }
272
271
  // 5️⃣ Executar instalação/atualização
273
- const installResult = await execNpmCommand(`npm install -g @silasfmartins/testhub-orchestrator-mcp@${latestVersion} --registry=${AZURE_REGISTRY}`, 60000);
272
+ const installResult = await execNpmCommand(`npm install -g @silasfmartins/autocore-orchestrator-mcp@${latestVersion} --registry=${AZURE_REGISTRY}`, 60000);
274
273
  if (!installResult) {
275
274
  console.log("⚠️ Falha ao instalar/atualizar MCP");
276
275
  if (installedVersion) {
@@ -400,7 +399,7 @@ async function ensureMcpConfig() {
400
399
  },
401
400
  "autocore-orchestrator": {
402
401
  command: "npx",
403
- args: ["-y", "@silasfmartins/testhub-orchestrator-mcp"],
402
+ args: ["-y", "@silasfmartins/autocore-orchestrator-mcp"],
404
403
  env: {
405
404
  HUB_BACKEND_URL: "http://brtlvlty0559pl:3333",
406
405
  },
@@ -426,7 +425,7 @@ async function ensureMcpConfig() {
426
425
  },
427
426
  "autocore-orchestrator": {
428
427
  command: "npx",
429
- args: ["-y", "@silasfmartins/testhub-orchestrator-mcp"],
428
+ args: ["-y", "@silasfmartins/autocore-orchestrator-mcp"],
430
429
  env: {
431
430
  HUB_BACKEND_URL: "http://brtlvlty0559pl:3333",
432
431
  },
@@ -61,8 +61,6 @@ export default defineConfig({
61
61
  trace: 'on',
62
62
  },
63
63
  })`);
64
- // .npmrc
65
- write('.npmrc', `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`);
66
64
  // .gitignore
67
65
  write('.gitignore', `# Playwright
68
66
  node_modules/
@@ -131,10 +129,10 @@ test.describe('API Tests - ${projectName}', () => {
131
129
  test('CT001 - Exemplo de requisição API', async ({ }, testInfo: TestInfo) => {
132
130
  TestAnnotations.Api.testInfo = testInfo
133
131
  await TestAnnotations.setSystem('MEU_SISTEMA')
134
-
132
+
135
133
  // Exemplo de requisição - substitua pelo seu statement
136
134
  // await new StatementsToken().getToken()
137
-
135
+
138
136
  // Exemplo de chamada API direta
139
137
  await ApiActions.executeGet(
140
138
  'Buscar dados do endpoint',
@@ -180,20 +178,20 @@ export class StatementsToken {
180
178
  const VALIDATE_TOKEN = 200
181
179
 
182
180
  const tokenResponse = await ApiActions.post(
183
- new RequestToken().requestToken(),
184
- "Requisição Token Sistêmico",
181
+ new RequestToken().requestToken(),
182
+ "Requisição Token Sistêmico",
185
183
  true
186
184
  );
187
185
 
188
186
  ApiActions.validateEquals(
189
187
  tokenResponse.status(),
190
- VALIDATE_TOKEN,
188
+ VALIDATE_TOKEN,
191
189
  "Validação do status code da requisição de token"
192
190
  );
193
191
 
194
192
  // Armazenar token para uso posterior
195
193
  DataStore.set("ACCESS_TOKEN", tokenResponse.get("token"))
196
-
194
+
197
195
  Logger.info("Token obtido e armazenado com sucesso");
198
196
  }
199
197
  }
@@ -205,7 +203,7 @@ import { StatementsToken } from '../src/statements/token/StatementsToken.js';
205
203
  test.describe('Exemplo API Tests', () => {
206
204
  TestAnnotations.Api.testInfo = testInfo;
207
205
  await TestAnnotations.setSystem('MEU_SISTEMA');
208
- test('Deve obter token com sucesso', async () => {
206
+ test('Deve obter token com sucesso', async () => {
209
207
  // Obter token
210
208
  await new StatementsToken().getToken()
211
209
  });
@@ -364,12 +362,12 @@ import { type TestInfo, test, TestAnnotations } from '@silasfmartins/testhub'
364
362
 
365
363
  test('Meu teste de API', async ({ }, testInfo) => {
366
364
  TestAnnotations.Api.testInfo = testInfo;
367
-
365
+
368
366
  const response = await ApiActions.get({
369
367
  url: 'https://api.example.com/endpoint',
370
368
  options: {}
371
369
  }, 'Descrição da requisição');
372
-
370
+
373
371
  ApiActions.validateEquals(response.status, 200, 'Status deve ser 200');
374
372
  });
375
373
  \`\`\`
@@ -383,7 +381,7 @@ test('Fluxo autenticado', async () => {
383
381
  // Obter token
384
382
  const statements = new StatementsToken();
385
383
  await statements.getToken();
386
-
384
+
387
385
  // Usar token
388
386
  const token = DataStore.get('ACCESS_TOKEN');
389
387
  // ... usar token em requisições subsequentes
@@ -60,8 +60,6 @@ export default defineConfig({
60
60
  trace: 'on',
61
61
  },
62
62
  })`);
63
- // .npmrc
64
- write('.npmrc', `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`);
65
63
  // .gitignore
66
64
  write('.gitignore', `# Playwright
67
65
  node_modules/
@@ -143,32 +141,32 @@ DB_PASSWORD=
143
141
  write('src/models/ModelDBA.ts', `export class ModelDBA {
144
142
  getCep(cidade: string): string {
145
143
  return /*sql*/ \`
146
- SELECT
147
- ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
148
- FROM
149
- siebel.s_addr_per
150
- WHERE
151
- x_network_owner = 'VIVO2'
152
- AND x_access_technology = 'GPON'
153
- AND city = '\${cidade}'
154
- AND comments LIKE '%Endereço com cobertura%'
155
- ORDER BY
144
+ SELECT
145
+ ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
146
+ FROM
147
+ siebel.s_addr_per
148
+ WHERE
149
+ x_network_owner = 'VIVO2'
150
+ AND x_access_technology = 'GPON'
151
+ AND city = '\${cidade}'
152
+ AND comments LIKE '%Endereço com cobertura%'
153
+ ORDER BY
156
154
  last_upd DESC
157
155
  \`;
158
156
  }
159
157
 
160
158
  getCep2(cidade: string, tecnology: string): string {
161
159
  return /*sql*/ \`
162
- SELECT
163
- ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
164
- FROM
165
- siebel.s_addr_per
166
- WHERE
167
- x_network_owner = 'VIVO2'
160
+ SELECT
161
+ ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
162
+ FROM
163
+ siebel.s_addr_per
164
+ WHERE
165
+ x_network_owner = 'VIVO2'
168
166
  AND x_access_technology = '\${tecnology}'
169
- AND city = '\${cidade}'
170
- AND comments LIKE '%Endereço com cobertura%'
171
- ORDER BY
167
+ AND city = '\${cidade}'
168
+ AND comments LIKE '%Endereço com cobertura%'
169
+ ORDER BY
172
170
  last_upd DESC
173
171
  \`;
174
172
  }
@@ -121,8 +121,6 @@ export default defineConfig({
121
121
  ],
122
122
  });
123
123
  `);
124
- // .npmrc
125
- write('.npmrc', `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`);
126
124
  // .gitignore
127
125
  write('.gitignore', `# Playwright
128
126
  node_modules/
@@ -414,7 +412,7 @@ test.describe('Login', () => {
414
412
  test('Login test', async ({}, testInfo: TestInfo) => {
415
413
  TestAnnotations.Frontend.testInfo = testInfo;
416
414
  await TestAnnotations.setSystem('MEU_SISTEMA');
417
-
415
+
418
416
  await new PageLogin().navigateToLogin();
419
417
  });
420
418
  });
@@ -60,8 +60,6 @@ export default defineConfig({
60
60
  },
61
61
  });
62
62
  `);
63
- // .npmrc
64
- write('.npmrc', `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`);
65
63
  // .gitignore otimizado para mobile
66
64
  write('.gitignore', `# Mobile específicos
67
65
  node_modules/
@@ -72,7 +72,7 @@ export default defineConfig({
72
72
  // ✅ Projetos "headless" (sem browser) — para SSH, API, Banco, Mobile
73
73
  {
74
74
  name: 'ssh',
75
- use: {
75
+ use: {
76
76
  browserName: undefined,
77
77
  screenshot: 'off',
78
78
  trace: 'off',
@@ -81,8 +81,8 @@ export default defineConfig({
81
81
  },
82
82
  {
83
83
  name: 'api',
84
- use: {
85
- browserName: undefined,
84
+ use: {
85
+ browserName: undefined,
86
86
  screenshot: 'off',
87
87
  trace: 'off',
88
88
  video: 'off'
@@ -90,8 +90,8 @@ export default defineConfig({
90
90
  },
91
91
  {
92
92
  name: 'banco',
93
- use: {
94
- browserName: undefined,
93
+ use: {
94
+ browserName: undefined,
95
95
  screenshot: 'off',
96
96
  trace: 'off',
97
97
  video: 'off'
@@ -99,7 +99,7 @@ export default defineConfig({
99
99
  },
100
100
  {
101
101
  name: 'mobile',
102
- use: { browserName: undefined,
102
+ use: { browserName: undefined,
103
103
  screenshot: 'off',
104
104
  trace: 'off',
105
105
  video: 'off'
@@ -143,8 +143,6 @@ export default defineConfig({
143
143
  ],
144
144
  });
145
145
  `);
146
- // .npmrc
147
- write('.npmrc', `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`);
148
146
  // .gitignore otimizado para cenários
149
147
  write('.gitignore', `# Playwright
150
148
  node_modules/
@@ -388,7 +386,7 @@ parameters:
388
386
  - esteira1
389
387
  - esteira2
390
388
  - prodlike
391
-
389
+
392
390
  - name: browser
393
391
  displayName: Escolha o navegador para os testes
394
392
  type: string
@@ -551,15 +549,15 @@ ${projectName}/
551
549
  \`\`\`typescript
552
550
  test('CT001 - Cenário misto', async ({ page }, testInfo) => {
553
551
  TestAnnotations.Mixed.testInfo = testInfo;
554
-
552
+
555
553
  // 1. Obter token via API
556
554
  const tokenResponse = await ApiActions.post(tokenRequest, 'Obtenção de token');
557
555
  DataStore.set('TOKEN', tokenResponse.body.access_token);
558
-
556
+
559
557
  // 2. Usar interface
560
558
  await WebActions.navegarPara('/app', 'Navegação');
561
559
  await WebActions.preencherCampo(searchInput, 'busca', 'Preenchimento');
562
-
560
+
563
561
  // 3. Validar via banco (se disponível)
564
562
  const dbResults = await BancoHelper.executarQuery(query);
565
563
  expect(dbResults.length).toBeGreaterThan(0);
@@ -571,13 +569,13 @@ test('CT001 - Cenário misto', async ({ page }, testInfo) => {
571
569
  test('Fluxo E2E completo', async () => {
572
570
  // Fase 1: Autenticação
573
571
  await authenticateViaAPI();
574
-
572
+
575
573
  // Fase 2: Navegação e interação
576
574
  await performUIInteractions();
577
-
575
+
578
576
  // Fase 3: Validação de dados
579
577
  await validateDataConsistency();
580
-
578
+
581
579
  // Fase 4: Cleanup e relatório
582
580
  await generateEvidences();
583
581
  });
@@ -588,10 +586,10 @@ test('Fluxo E2E completo', async () => {
588
586
  test('Validação de infraestrutura', async () => {
589
587
  // Verificar serviços via SSH
590
588
  await SSHActions.write('systemctl status myapp');
591
-
589
+
592
590
  // Validar dados no banco
593
591
  await BancoActions.executarQuery('SELECT 1 FROM dual');
594
-
592
+
595
593
  // Validar interface está acessível
596
594
  await WebActions.navegarPara('/health', 'Health check');
597
595
  });
@@ -65,8 +65,6 @@ export default defineConfig({
65
65
  },
66
66
  })
67
67
  `);
68
- // .npmrc
69
- write('.npmrc', `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`);
70
68
  // .gitignore
71
69
  write('.gitignore', `# Playwright
72
70
  node_modules/
@@ -127,10 +127,10 @@ function execNpmSync(args, timeoutMs = 30000) {
127
127
  // ✅ Obter versão instalada globalmente do pacote MCP
128
128
  function getInstalledMcpVersion() {
129
129
  try {
130
- const result = execNpmSync(['list', '-g', '@silasfmartins/testhub-orchestrator-mcp', '--depth=0', '--json']);
130
+ const result = execNpmSync(['list', '-g', '@silasfmartins/autocore-orchestrator-mcp', '--depth=0', '--json']);
131
131
  if (result.status === 0) {
132
132
  const data = JSON.parse(result.stdout);
133
- return data.dependencies?.['@silasfmartins/testhub-orchestrator-mcp']?.version || null;
133
+ return data.dependencies?.['@silasfmartins/autocore-orchestrator-mcp']?.version || null;
134
134
  }
135
135
  return null;
136
136
  }
@@ -141,7 +141,7 @@ function getInstalledMcpVersion() {
141
141
  // ✅ Verificar acesso ao registry e obter última versão do MCP
142
142
  function checkRegistryAndGetLatestVersion() {
143
143
  try {
144
- const result = execNpmSync(['view', '@silasfmartins/testhub-orchestrator-mcp', 'version', `--registry=${AZURE_REGISTRY}`], 30000);
144
+ const result = execNpmSync(['view', '@silasfmartins/autocore-orchestrator-mcp', 'version', `--registry=${AZURE_REGISTRY}`], 30000);
145
145
  if (result.status === 0 && result.stdout.trim()) {
146
146
  return result.stdout.trim();
147
147
  }
@@ -151,15 +151,15 @@ function checkRegistryAndGetLatestVersion() {
151
151
  return null;
152
152
  }
153
153
  }
154
- // ✅ Verificar se o pacote @silasfmartins/testhub-orchestrator-mcp está instalado globalmente
154
+ // ✅ Verificar se o pacote @silasfmartins/autocore-orchestrator-mcp está instalado globalmente
155
155
  function checkGlobalMcpPackage() {
156
- const result = execNpmSync(['list', '-g', '@silasfmartins/testhub-orchestrator-mcp', '--depth=0']);
157
- return result.status === 0 && result.stdout.includes('@silasfmartins/testhub-orchestrator-mcp');
156
+ const result = execNpmSync(['list', '-g', '@silasfmartins/autocore-orchestrator-mcp', '--depth=0']);
157
+ return result.status === 0 && result.stdout.includes('@silasfmartins/autocore-orchestrator-mcp');
158
158
  }
159
159
  // ✅ Instalar ou atualizar pacote MCP globalmente
160
160
  // 🎯 COMPORTAMENTO:
161
161
  // - Se já está na última versão: NÃO reinstala
162
- // - Se versão antiga: atualiza automaticamente
162
+ // - Se versão antiga: atualiza automaticamente
163
163
  // - Se não instalado: instala globalmente
164
164
  // - Se offline: usa versão local existente
165
165
  function installOrUpdateMcpPackage() {
@@ -174,7 +174,6 @@ function installOrUpdateMcpPackage() {
174
174
  console.log('AutoCore: MCP não encontrado globalmente');
175
175
  }
176
176
  // Verificar acesso ao registry e obter última versão
177
- console.log('AutoCore: Verificando registry Azure Artifacts...');
178
177
  const latestVersion = checkRegistryAndGetLatestVersion();
179
178
  if (!latestVersion) {
180
179
  console.log('AutoCore: Sem acesso ao registry Azure Artifacts (modo offline)');
@@ -199,7 +198,7 @@ function installOrUpdateMcpPackage() {
199
198
  console.log('AutoCore: Instalando MCP globalmente...');
200
199
  }
201
200
  // Executar instalação/atualização
202
- const installResult = execNpmSync(['install', '-g', `@silasfmartins/testhub-orchestrator-mcp@${latestVersion}`, `--registry=${AZURE_REGISTRY}`], 60000);
201
+ const installResult = execNpmSync(['install', '-g', `@silasfmartins/autocore-orchestrator-mcp@${latestVersion}`, `--registry=${AZURE_REGISTRY}`], 60000);
203
202
  if (installResult.status === 0) {
204
203
  const newVersion = getInstalledMcpVersion();
205
204
  if (installedVersion) {
@@ -299,7 +298,7 @@ async function ensureMcpConfig() {
299
298
  },
300
299
  'autocore-orchestrator': {
301
300
  command: 'npx',
302
- args: ['-y', '@silasfmartins/testhub-orchestrator-mcp'],
301
+ args: ['-y', '@silasfmartins/autocore-orchestrator-mcp'],
303
302
  env: {
304
303
  HUB_BACKEND_URL: 'http://brtlvlty0559pl:3333',
305
304
  },
@@ -325,7 +324,7 @@ async function ensureMcpConfig() {
325
324
  },
326
325
  'autocore-orchestrator': {
327
326
  command: 'npx',
328
- args: ['-y', '@silasfmartins/testhub-orchestrator-mcp'],
327
+ args: ['-y', '@silasfmartins/autocore-orchestrator-mcp'],
329
328
  env: {
330
329
  HUB_BACKEND_URL: 'http://brtlvlty0559pl:3333',
331
330
  },
@@ -986,7 +986,10 @@ export class WebActions {
986
986
  return await fn(initialCandidate);
987
987
  }
988
988
  // 🔄 Refresh DOM antes da primeira tentativa — garantir DOM fresco para SPAs/Shadow DOM
989
- await WebActions.refreshDOM(150).catch(() => { });
989
+ // 🛡️ Pular refreshDOM se já estiver em contexto de recovery (evitar overhead desnecessário)
990
+ if (WebActions._recoveryDepth <= 0) {
991
+ await WebActions.refreshDOM(150).catch(() => { });
992
+ }
990
993
  // 🎯 Catalog pre-resolve + lazy auto-refresh (Item 18/20 v2.7.44)
991
994
  // Se o target for texto/label (não XPath explícito), tentar resolver via catálogo local.
992
995
  // Na primeira ação de cada URL, popular o catálogo automaticamente.
@@ -1008,11 +1011,16 @@ export class WebActions {
1008
1011
  }
1009
1012
  catch { }
1010
1013
  }
1014
+ // 🛡️ Flag para rastrear se entramos no bloco de recovery (catch).
1015
+ // Sem essa flag, o finally decrementa _recoveryDepth mesmo em chamadas bem-sucedidas,
1016
+ // fazendo depth ficar negativo e desabilitando o guard de recursão em falhas futuras.
1017
+ let enteredRecovery = false;
1011
1018
  try {
1012
1019
  const initialCandidate = await WebActions.resolveCandidateForRecovery(originalElement);
1013
1020
  return await fn(initialCandidate);
1014
1021
  }
1015
1022
  catch (error) {
1023
+ enteredRecovery = true;
1016
1024
  // 🔄 Refresh DOM imediato após falha — capturar estado mais recente do Shadow DOM
1017
1025
  await WebActions.refreshDOM(200).catch(() => { });
1018
1026
  // 🛡️ Incrementar profundidade de recovery para evitar recursão infinita
@@ -1345,8 +1353,12 @@ export class WebActions {
1345
1353
  throw error;
1346
1354
  }
1347
1355
  finally {
1348
- // 🛡️ Decrementar profundidade de recovery independente de sucesso/falha
1349
- WebActions._recoveryDepth--;
1356
+ // 🛡️ Decrementar profundidade de recovery SOMENTE se entramos no bloco de recovery.
1357
+ // Sem essa condição, chamadas bem-sucedidas decrementam sem ter incrementado,
1358
+ // fazendo _recoveryDepth ficar negativo e desabilitando o guard de recursão.
1359
+ if (enteredRecovery) {
1360
+ WebActions._recoveryDepth--;
1361
+ }
1350
1362
  }
1351
1363
  }
1352
1364
  // Helper genérico para tentar heurísticas de preenchimento/atribuição de valor
@@ -91,8 +91,8 @@ function getMcpStdioCandidates() {
91
91
  });
92
92
  candidates.push({
93
93
  command: "npx",
94
- args: ["-y", "@silasfmartins/testhub-orchestrator-mcp", "--stdio"],
95
- label: "npx:@silasfmartins/testhub-orchestrator-mcp",
94
+ args: ["-y", "@silasfmartins/autocore-orchestrator-mcp", "--stdio"],
95
+ label: "npx:@silasfmartins/autocore-orchestrator-mcp",
96
96
  });
97
97
  // remover duplicados mantendo ordem
98
98
  const dedupe = new Set();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@silasfmartins/testhub",
3
3
  "description": "Biblioteca de utilitários para automação de testes",
4
- "version": "1.0.0",
4
+ "version": "1.0.2",
5
5
  "author": "Silas Martins Feliciano da Silva <silas.martins2041@gmail.com>",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
@@ -106,7 +106,7 @@
106
106
  "cross-env": "^10.1.0",
107
107
  "esbuild": "^0.27.4",
108
108
  "typescript": "^5.9.3",
109
- "ultracite": "7.3.1",
109
+ "ultracite": "7.3.2",
110
110
  "undici": "^7.24.4",
111
111
  "vitest": "4.1.0"
112
112
  },
@@ -141,7 +141,7 @@ function isExtensionInstalled(extensionId: string): boolean {
141
141
  const AZURE_REGISTRY =
142
142
  "https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/";
143
143
  const WINDOWS_MCP_AUTOSTART_START_COMMAND =
144
- "npx -y @silasfmartins/testhub-orchestrator-mcp";
144
+ "npx -y @silasfmartins/autocore-orchestrator-mcp";
145
145
  const WINDOWS_MCP_STARTUP_SCRIPT_FILE = "autocore-orchestrator-mcp.cmd";
146
146
  const WINDOWS_MCP_STARTUP_VBS_FILE = "autocore-orchestrator-mcp.vbs";
147
147
 
@@ -193,12 +193,12 @@ async function execNpmCommand(
193
193
  async function getInstalledMcpVersion(): Promise<string | null> {
194
194
  try {
195
195
  const result = await execNpmCommand(
196
- "npm list -g @silasfmartins/testhub-orchestrator-mcp --depth=0 --json",
196
+ "npm list -g @silasfmartins/autocore-orchestrator-mcp --depth=0 --json",
197
197
  );
198
198
  if (!result) return null;
199
199
  const data = JSON.parse(result.stdout);
200
200
  return (
201
- data.dependencies?.["@silasfmartins/testhub-orchestrator-mcp"]?.version || null
201
+ data.dependencies?.["@silasfmartins/autocore-orchestrator-mcp"]?.version || null
202
202
  );
203
203
  } catch {
204
204
  return null;
@@ -212,7 +212,7 @@ async function getInstalledMcpVersion(): Promise<string | null> {
212
212
  async function getLatestMcpVersion(): Promise<string | null> {
213
213
  try {
214
214
  const result = await execNpmCommand(
215
- `npm view @silasfmartins/testhub-orchestrator-mcp version --registry=${AZURE_REGISTRY}`,
215
+ `npm view @silasfmartins/autocore-orchestrator-mcp version --registry=${AZURE_REGISTRY}`,
216
216
  30000,
217
217
  );
218
218
  if (!result) return null;
@@ -223,15 +223,15 @@ async function getLatestMcpVersion(): Promise<string | null> {
223
223
  }
224
224
 
225
225
  /**
226
- * 🔍 Verifica se o pacote @silasfmartins/testhub-orchestrator-mcp está instalado globalmente
226
+ * 🔍 Verifica se o pacote @silasfmartins/autocore-orchestrator-mcp está instalado globalmente
227
227
  */
228
228
  async function isMcpPackageInstalled(): Promise<boolean> {
229
229
  try {
230
230
  const result = await execNpmCommand(
231
- "npm list -g @silasfmartins/testhub-orchestrator-mcp --depth=0",
231
+ "npm list -g @silasfmartins/autocore-orchestrator-mcp --depth=0",
232
232
  );
233
233
  return result
234
- ? result.stdout.includes("@silasfmartins/testhub-orchestrator-mcp")
234
+ ? result.stdout.includes("@silasfmartins/autocore-orchestrator-mcp")
235
235
  : false;
236
236
  } catch {
237
237
  return false;
@@ -246,7 +246,7 @@ async function checkRegistryAccess(): Promise<string | null> {
246
246
  try {
247
247
  // Tenta obter a versão do pacote no Azure Artifacts
248
248
  const result = await execNpmCommand(
249
- `npm view @silasfmartins/testhub-orchestrator-mcp version --registry=${AZURE_REGISTRY}`,
249
+ `npm view @silasfmartins/autocore-orchestrator-mcp version --registry=${AZURE_REGISTRY}`,
250
250
  30000,
251
251
  );
252
252
  if (result && result.stdout.trim()) {
@@ -259,7 +259,7 @@ async function checkRegistryAccess(): Promise<string | null> {
259
259
  }
260
260
 
261
261
  /**
262
- * 📦 Instala ou atualiza o pacote @silasfmartins/testhub-orchestrator-mcp globalmente
262
+ * 📦 Instala ou atualiza o pacote @silasfmartins/autocore-orchestrator-mcp globalmente
263
263
  *
264
264
  * 🎯 COMPORTAMENTO:
265
265
  * - Se já está na última versão: NÃO reinstala (economia de tempo)
@@ -289,7 +289,6 @@ async function installMcpPackageGlobally(): Promise<boolean> {
289
289
  }
290
290
 
291
291
  // 2️⃣ Verificar acesso ao registry e obter última versão
292
- console.log("🔍 Verificando registry Azure Artifacts...");
293
292
  const latestVersion = await checkRegistryAccess();
294
293
 
295
294
  if (!latestVersion) {
@@ -301,7 +300,7 @@ async function installMcpPackageGlobally(): Promise<boolean> {
301
300
  console.log("⚠️ O MCP será executado via npx quando necessário");
302
301
  console.log(" 💡 Conecte-se à VPN e execute:");
303
302
  console.log(
304
- ` npm install -g @silasfmartins/testhub-orchestrator-mcp --registry=${AZURE_REGISTRY}`,
303
+ ` npm install -g @silasfmartins/autocore-orchestrator-mcp --registry=${AZURE_REGISTRY}`,
305
304
  );
306
305
  return false;
307
306
  }
@@ -326,7 +325,7 @@ async function installMcpPackageGlobally(): Promise<boolean> {
326
325
 
327
326
  // 5️⃣ Executar instalação/atualização
328
327
  const installResult = await execNpmCommand(
329
- `npm install -g @silasfmartins/testhub-orchestrator-mcp@${latestVersion} --registry=${AZURE_REGISTRY}`,
328
+ `npm install -g @silasfmartins/autocore-orchestrator-mcp@${latestVersion} --registry=${AZURE_REGISTRY}`,
330
329
  60000,
331
330
  );
332
331
 
@@ -492,7 +491,7 @@ async function ensureMcpConfig(): Promise<void> {
492
491
  },
493
492
  "autocore-orchestrator": {
494
493
  command: "npx",
495
- args: ["-y", "@silasfmartins/testhub-orchestrator-mcp"],
494
+ args: ["-y", "@silasfmartins/autocore-orchestrator-mcp"],
496
495
  env: {
497
496
  HUB_BACKEND_URL: "http://brtlvlty0559pl:3333",
498
497
  },
@@ -523,7 +522,7 @@ async function ensureMcpConfig(): Promise<void> {
523
522
  },
524
523
  "autocore-orchestrator": {
525
524
  command: "npx",
526
- args: ["-y", "@silasfmartins/testhub-orchestrator-mcp"],
525
+ args: ["-y", "@silasfmartins/autocore-orchestrator-mcp"],
527
526
  env: {
528
527
  HUB_BACKEND_URL: "http://brtlvlty0559pl:3333",
529
528
  },
@@ -87,12 +87,6 @@ export default defineConfig({
87
87
  })`,
88
88
  )
89
89
 
90
- // .npmrc
91
- write(
92
- '.npmrc',
93
- `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`,
94
- )
95
-
96
90
  // .gitignore
97
91
  write(
98
92
  '.gitignore',
@@ -184,10 +178,10 @@ test.describe('API Tests - ${projectName}', () => {
184
178
  test('CT001 - Exemplo de requisição API', async ({ }, testInfo: TestInfo) => {
185
179
  TestAnnotations.Api.testInfo = testInfo
186
180
  await TestAnnotations.setSystem('MEU_SISTEMA')
187
-
181
+
188
182
  // Exemplo de requisição - substitua pelo seu statement
189
183
  // await new StatementsToken().getToken()
190
-
184
+
191
185
  // Exemplo de chamada API direta
192
186
  await ApiActions.executeGet(
193
187
  'Buscar dados do endpoint',
@@ -245,20 +239,20 @@ export class StatementsToken {
245
239
  const VALIDATE_TOKEN = 200
246
240
 
247
241
  const tokenResponse = await ApiActions.post(
248
- new RequestToken().requestToken(),
249
- "Requisição Token Sistêmico",
242
+ new RequestToken().requestToken(),
243
+ "Requisição Token Sistêmico",
250
244
  true
251
245
  );
252
246
 
253
247
  ApiActions.validateEquals(
254
248
  tokenResponse.status(),
255
- VALIDATE_TOKEN,
249
+ VALIDATE_TOKEN,
256
250
  "Validação do status code da requisição de token"
257
251
  );
258
252
 
259
253
  // Armazenar token para uso posterior
260
254
  DataStore.set("ACCESS_TOKEN", tokenResponse.get("token"))
261
-
255
+
262
256
  Logger.info("Token obtido e armazenado com sucesso");
263
257
  }
264
258
  }
@@ -274,7 +268,7 @@ import { StatementsToken } from '../src/statements/token/StatementsToken.js';
274
268
  test.describe('Exemplo API Tests', () => {
275
269
  TestAnnotations.Api.testInfo = testInfo;
276
270
  await TestAnnotations.setSystem('MEU_SISTEMA');
277
- test('Deve obter token com sucesso', async () => {
271
+ test('Deve obter token com sucesso', async () => {
278
272
  // Obter token
279
273
  await new StatementsToken().getToken()
280
274
  });
@@ -446,12 +440,12 @@ import { type TestInfo, test, TestAnnotations } from '@silasfmartins/testhub'
446
440
 
447
441
  test('Meu teste de API', async ({ }, testInfo) => {
448
442
  TestAnnotations.Api.testInfo = testInfo;
449
-
443
+
450
444
  const response = await ApiActions.get({
451
445
  url: 'https://api.example.com/endpoint',
452
446
  options: {}
453
447
  }, 'Descrição da requisição');
454
-
448
+
455
449
  ApiActions.validateEquals(response.status, 200, 'Status deve ser 200');
456
450
  });
457
451
  \`\`\`
@@ -465,7 +459,7 @@ test('Fluxo autenticado', async () => {
465
459
  // Obter token
466
460
  const statements = new StatementsToken();
467
461
  await statements.getToken();
468
-
462
+
469
463
  // Usar token
470
464
  const token = DataStore.get('ACCESS_TOKEN');
471
465
  // ... usar token em requisições subsequentes
@@ -94,12 +94,6 @@ export default defineConfig({
94
94
  })`,
95
95
  )
96
96
 
97
- // .npmrc
98
- write(
99
- '.npmrc',
100
- `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`,
101
- )
102
-
103
97
  // .gitignore
104
98
  write(
105
99
  '.gitignore',
@@ -208,32 +202,32 @@ DB_PASSWORD=
208
202
  `export class ModelDBA {
209
203
  getCep(cidade: string): string {
210
204
  return /*sql*/ \`
211
- SELECT
212
- ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
213
- FROM
214
- siebel.s_addr_per
215
- WHERE
216
- x_network_owner = 'VIVO2'
217
- AND x_access_technology = 'GPON'
218
- AND city = '\${cidade}'
219
- AND comments LIKE '%Endereço com cobertura%'
220
- ORDER BY
205
+ SELECT
206
+ ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
207
+ FROM
208
+ siebel.s_addr_per
209
+ WHERE
210
+ x_network_owner = 'VIVO2'
211
+ AND x_access_technology = 'GPON'
212
+ AND city = '\${cidade}'
213
+ AND comments LIKE '%Endereço com cobertura%'
214
+ ORDER BY
221
215
  last_upd DESC
222
216
  \`;
223
217
  }
224
218
 
225
219
  getCep2(cidade: string, tecnology: string): string {
226
220
  return /*sql*/ \`
227
- SELECT
228
- ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
229
- FROM
230
- siebel.s_addr_per
231
- WHERE
232
- x_network_owner = 'VIVO2'
221
+ SELECT
222
+ ZIPCODE, X_NUMBER, X_BB_MAX_SPEED, X_OPTL_TR_NAME
223
+ FROM
224
+ siebel.s_addr_per
225
+ WHERE
226
+ x_network_owner = 'VIVO2'
233
227
  AND x_access_technology = '\${tecnology}'
234
- AND city = '\${cidade}'
235
- AND comments LIKE '%Endereço com cobertura%'
236
- ORDER BY
228
+ AND city = '\${cidade}'
229
+ AND comments LIKE '%Endereço com cobertura%'
230
+ ORDER BY
237
231
  last_upd DESC
238
232
  \`;
239
233
  }
@@ -153,12 +153,6 @@ export default defineConfig({
153
153
  `,
154
154
  )
155
155
 
156
- // .npmrc
157
- write(
158
- '.npmrc',
159
- `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`,
160
- )
161
-
162
156
  // .gitignore
163
157
  write(
164
158
  '.gitignore',
@@ -506,7 +500,7 @@ test.describe('Login', () => {
506
500
  test('Login test', async ({}, testInfo: TestInfo) => {
507
501
  TestAnnotations.Frontend.testInfo = testInfo;
508
502
  await TestAnnotations.setSystem('MEU_SISTEMA');
509
-
503
+
510
504
  await new PageLogin().navigateToLogin();
511
505
  });
512
506
  });
@@ -91,12 +91,6 @@ export default defineConfig({
91
91
  `,
92
92
  )
93
93
 
94
- // .npmrc
95
- write(
96
- '.npmrc',
97
- `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`,
98
- )
99
-
100
94
  // .gitignore otimizado para mobile
101
95
  write(
102
96
  '.gitignore',
@@ -99,7 +99,7 @@ export default defineConfig({
99
99
  // ✅ Projetos "headless" (sem browser) — para SSH, API, Banco, Mobile
100
100
  {
101
101
  name: 'ssh',
102
- use: {
102
+ use: {
103
103
  browserName: undefined,
104
104
  screenshot: 'off',
105
105
  trace: 'off',
@@ -108,8 +108,8 @@ export default defineConfig({
108
108
  },
109
109
  {
110
110
  name: 'api',
111
- use: {
112
- browserName: undefined,
111
+ use: {
112
+ browserName: undefined,
113
113
  screenshot: 'off',
114
114
  trace: 'off',
115
115
  video: 'off'
@@ -117,8 +117,8 @@ export default defineConfig({
117
117
  },
118
118
  {
119
119
  name: 'banco',
120
- use: {
121
- browserName: undefined,
120
+ use: {
121
+ browserName: undefined,
122
122
  screenshot: 'off',
123
123
  trace: 'off',
124
124
  video: 'off'
@@ -126,7 +126,7 @@ export default defineConfig({
126
126
  },
127
127
  {
128
128
  name: 'mobile',
129
- use: { browserName: undefined,
129
+ use: { browserName: undefined,
130
130
  screenshot: 'off',
131
131
  trace: 'off',
132
132
  video: 'off'
@@ -172,12 +172,6 @@ export default defineConfig({
172
172
  `,
173
173
  )
174
174
 
175
- // .npmrc
176
- write(
177
- '.npmrc',
178
- `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`,
179
- )
180
-
181
175
  // .gitignore otimizado para cenários
182
176
  write(
183
177
  '.gitignore',
@@ -451,7 +445,7 @@ parameters:
451
445
  - esteira1
452
446
  - esteira2
453
447
  - prodlike
454
-
448
+
455
449
  - name: browser
456
450
  displayName: Escolha o navegador para os testes
457
451
  type: string
@@ -618,15 +612,15 @@ ${projectName}/
618
612
  \`\`\`typescript
619
613
  test('CT001 - Cenário misto', async ({ page }, testInfo) => {
620
614
  TestAnnotations.Mixed.testInfo = testInfo;
621
-
615
+
622
616
  // 1. Obter token via API
623
617
  const tokenResponse = await ApiActions.post(tokenRequest, 'Obtenção de token');
624
618
  DataStore.set('TOKEN', tokenResponse.body.access_token);
625
-
619
+
626
620
  // 2. Usar interface
627
621
  await WebActions.navegarPara('/app', 'Navegação');
628
622
  await WebActions.preencherCampo(searchInput, 'busca', 'Preenchimento');
629
-
623
+
630
624
  // 3. Validar via banco (se disponível)
631
625
  const dbResults = await BancoHelper.executarQuery(query);
632
626
  expect(dbResults.length).toBeGreaterThan(0);
@@ -638,13 +632,13 @@ test('CT001 - Cenário misto', async ({ page }, testInfo) => {
638
632
  test('Fluxo E2E completo', async () => {
639
633
  // Fase 1: Autenticação
640
634
  await authenticateViaAPI();
641
-
635
+
642
636
  // Fase 2: Navegação e interação
643
637
  await performUIInteractions();
644
-
638
+
645
639
  // Fase 3: Validação de dados
646
640
  await validateDataConsistency();
647
-
641
+
648
642
  // Fase 4: Cleanup e relatório
649
643
  await generateEvidences();
650
644
  });
@@ -655,10 +649,10 @@ test('Fluxo E2E completo', async () => {
655
649
  test('Validação de infraestrutura', async () => {
656
650
  // Verificar serviços via SSH
657
651
  await SSHActions.write('systemctl status myapp');
658
-
652
+
659
653
  // Validar dados no banco
660
654
  await BancoActions.executarQuery('SELECT 1 FROM dual');
661
-
655
+
662
656
  // Validar interface está acessível
663
657
  await WebActions.navegarPara('/health', 'Health check');
664
658
  });
@@ -91,12 +91,6 @@ export default defineConfig({
91
91
  `,
92
92
  )
93
93
 
94
- // .npmrc
95
- write(
96
- '.npmrc',
97
- `registry=https://pkgs.dev.azure.com/telefonica-vivo-brasil/_packaging/DevOps/npm/registry/`,
98
- )
99
-
100
94
  // .gitignore
101
95
  write(
102
96
  '.gitignore',
@@ -147,10 +147,10 @@ function execNpmSync(args: string[], timeoutMs = 30000): { stdout: string; statu
147
147
  // ✅ Obter versão instalada globalmente do pacote MCP
148
148
  function getInstalledMcpVersion(): string | null {
149
149
  try {
150
- const result = execNpmSync(['list', '-g', '@silasfmartins/testhub-orchestrator-mcp', '--depth=0', '--json'])
150
+ const result = execNpmSync(['list', '-g', '@silasfmartins/autocore-orchestrator-mcp', '--depth=0', '--json'])
151
151
  if (result.status === 0) {
152
152
  const data = JSON.parse(result.stdout)
153
- return data.dependencies?.['@silasfmartins/testhub-orchestrator-mcp']?.version || null
153
+ return data.dependencies?.['@silasfmartins/autocore-orchestrator-mcp']?.version || null
154
154
  }
155
155
  return null
156
156
  } catch {
@@ -162,7 +162,7 @@ function getInstalledMcpVersion(): string | null {
162
162
  function checkRegistryAndGetLatestVersion(): string | null {
163
163
  try {
164
164
  const result = execNpmSync(
165
- ['view', '@silasfmartins/testhub-orchestrator-mcp', 'version', `--registry=${AZURE_REGISTRY}`],
165
+ ['view', '@silasfmartins/autocore-orchestrator-mcp', 'version', `--registry=${AZURE_REGISTRY}`],
166
166
  30000
167
167
  )
168
168
  if (result.status === 0 && result.stdout.trim()) {
@@ -174,23 +174,23 @@ function checkRegistryAndGetLatestVersion(): string | null {
174
174
  }
175
175
  }
176
176
 
177
- // ✅ Verificar se o pacote @silasfmartins/testhub-orchestrator-mcp está instalado globalmente
177
+ // ✅ Verificar se o pacote @silasfmartins/autocore-orchestrator-mcp está instalado globalmente
178
178
  function checkGlobalMcpPackage(): boolean {
179
- const result = execNpmSync(['list', '-g', '@silasfmartins/testhub-orchestrator-mcp', '--depth=0'])
180
- return result.status === 0 && result.stdout.includes('@silasfmartins/testhub-orchestrator-mcp')
179
+ const result = execNpmSync(['list', '-g', '@silasfmartins/autocore-orchestrator-mcp', '--depth=0'])
180
+ return result.status === 0 && result.stdout.includes('@silasfmartins/autocore-orchestrator-mcp')
181
181
  }
182
182
 
183
183
  // ✅ Instalar ou atualizar pacote MCP globalmente
184
184
  // 🎯 COMPORTAMENTO:
185
185
  // - Se já está na última versão: NÃO reinstala
186
- // - Se versão antiga: atualiza automaticamente
186
+ // - Se versão antiga: atualiza automaticamente
187
187
  // - Se não instalado: instala globalmente
188
188
  // - Se offline: usa versão local existente
189
189
  function installOrUpdateMcpPackage(): { installed: boolean; updated: boolean; version: string | null } {
190
190
  console.log('AutoCore: ======================================================')
191
191
  console.log('AutoCore: MCP - Verificando instalação global')
192
192
  console.log('AutoCore: ======================================================')
193
-
193
+
194
194
  const installedVersion = getInstalledMcpVersion()
195
195
 
196
196
  if (installedVersion) {
@@ -198,11 +198,10 @@ function installOrUpdateMcpPackage(): { installed: boolean; updated: boolean; ve
198
198
  } else {
199
199
  console.log('AutoCore: MCP não encontrado globalmente')
200
200
  }
201
-
201
+
202
202
  // Verificar acesso ao registry e obter última versão
203
- console.log('AutoCore: Verificando registry Azure Artifacts...')
204
203
  const latestVersion = checkRegistryAndGetLatestVersion()
205
-
204
+
206
205
  if (!latestVersion) {
207
206
  console.log('AutoCore: Sem acesso ao registry Azure Artifacts (modo offline)')
208
207
  if (installedVersion) {
@@ -212,28 +211,28 @@ function installOrUpdateMcpPackage(): { installed: boolean; updated: boolean; ve
212
211
  console.log('AutoCore: MCP será executado via npx quando necessário')
213
212
  return { installed: false, updated: false, version: null }
214
213
  }
215
-
214
+
216
215
  console.log(`AutoCore: Última versão disponível: ${latestVersion}`)
217
-
216
+
218
217
  // Comparar versões se já instalado
219
218
  if (installedVersion) {
220
219
  if (installedVersion === latestVersion) {
221
220
  console.log('AutoCore: MCP já está na última versão global - nada a fazer! ✓')
222
221
  return { installed: true, updated: false, version: installedVersion }
223
222
  }
224
-
223
+
225
224
  // Versão desatualizada - atualizar
226
225
  console.log(`AutoCore: Atualizando MCP: ${installedVersion} → ${latestVersion}`)
227
226
  } else {
228
227
  console.log('AutoCore: Instalando MCP globalmente...')
229
228
  }
230
-
229
+
231
230
  // Executar instalação/atualização
232
231
  const installResult = execNpmSync(
233
- ['install', '-g', `@silasfmartins/testhub-orchestrator-mcp@${latestVersion}`, `--registry=${AZURE_REGISTRY}`],
232
+ ['install', '-g', `@silasfmartins/autocore-orchestrator-mcp@${latestVersion}`, `--registry=${AZURE_REGISTRY}`],
234
233
  60000
235
234
  )
236
-
235
+
237
236
  if (installResult.status === 0) {
238
237
  const newVersion = getInstalledMcpVersion()
239
238
  if (installedVersion) {
@@ -244,13 +243,13 @@ function installOrUpdateMcpPackage(): { installed: boolean; updated: boolean; ve
244
243
  console.log('AutoCore: Disponível para todos os projetos da máquina')
245
244
  return { installed: true, updated: !!installedVersion, version: newVersion || latestVersion }
246
245
  }
247
-
246
+
248
247
  console.warn('AutoCore: Falha ao instalar/atualizar MCP')
249
248
  if (installedVersion) {
250
249
  console.log(`AutoCore: Usando versão global existente: ${installedVersion}`)
251
250
  return { installed: true, updated: false, version: installedVersion }
252
251
  }
253
-
252
+
254
253
  console.log('AutoCore: MCP será executado via npx')
255
254
  return { installed: false, updated: false, version: null }
256
255
  }
@@ -265,12 +264,12 @@ function extractUserHash(url: string): string {
265
264
  async function copyCopilotInstructions(): Promise<void> {
266
265
  try {
267
266
  const cwd = process.cwd()
268
-
267
+
269
268
  // Se estiver em dist/scripts, subir dois níveis; senão, um nível
270
269
  const isDist = __dirname.includes('dist')
271
270
  const levelsUp = isDist ? '../..' : '..'
272
271
  const sourceFile = path.join(__dirname, levelsUp, '.github', 'copilot-instructions.md')
273
-
272
+
274
273
  const targetDir = path.join(cwd, '.github')
275
274
  const targetFile = path.join(targetDir, 'copilot-instructions.md')
276
275
 
@@ -344,7 +343,7 @@ async function ensureMcpConfig(): Promise<void> {
344
343
  },
345
344
  'autocore-orchestrator': {
346
345
  command: 'npx',
347
- args: ['-y', '@silasfmartins/testhub-orchestrator-mcp'],
346
+ args: ['-y', '@silasfmartins/autocore-orchestrator-mcp'],
348
347
  env: {
349
348
  HUB_BACKEND_URL: 'http://brtlvlty0559pl:3333',
350
349
  },
@@ -357,7 +356,7 @@ async function ensureMcpConfig(): Promise<void> {
357
356
  if (existsSync(mcpFile)) {
358
357
  // Arquivo existe - preservar hashes do usuário
359
358
  const currentContent = JSON.parse(readFileSync(mcpFile, 'utf8'))
360
-
359
+
361
360
  // Preservar hash do mcp-estimative
362
361
  let existingEstimativeHash = ''
363
362
  if (currentContent.servers?.['mcp-estimative']?.url) {
@@ -373,7 +372,7 @@ async function ensureMcpConfig(): Promise<void> {
373
372
  },
374
373
  'autocore-orchestrator': {
375
374
  command: 'npx',
376
- args: ['-y', '@silasfmartins/testhub-orchestrator-mcp'],
375
+ args: ['-y', '@silasfmartins/autocore-orchestrator-mcp'],
377
376
  env: {
378
377
  HUB_BACKEND_URL: 'http://brtlvlty0559pl:3333',
379
378
  },
@@ -384,7 +383,7 @@ async function ensureMcpConfig(): Promise<void> {
384
383
  }
385
384
 
386
385
  writeFileSync(mcpFile, JSON.stringify(updatedConfig, null, 2))
387
-
386
+
388
387
  if (existingEstimativeHash) {
389
388
  console.log('AutoCore: Arquivo mcp.json atualizado (hash mcp-estimative preservado) ✓')
390
389
  } else {
@@ -413,19 +412,19 @@ async function ensurePlaywrightInstalled(): Promise<void> {
413
412
  try {
414
413
  const cwd = process.cwd()
415
414
  const pkgFile = path.join(cwd, 'package.json')
416
-
415
+
417
416
  if (!existsSync(pkgFile)) return
418
-
417
+
419
418
  const content = readFileSync(pkgFile, 'utf8')
420
419
  const pkg = JSON.parse(content)
421
-
420
+
422
421
  // Verificar se é projeto Frontend ou Scenarios (tem @playwright/test nas dependências)
423
- const hasPlaywright =
424
- pkg.dependencies?.['@playwright/test'] ||
422
+ const hasPlaywright =
423
+ pkg.dependencies?.['@playwright/test'] ||
425
424
  pkg.devDependencies?.['@playwright/test'] ||
426
425
  pkg.dependencies?.['@silasfmartins/testhub'] ||
427
426
  pkg.devDependencies?.['@silasfmartins/testhub']
428
-
427
+
429
428
  // Determinar se devemos instalar browsers Playwright
430
429
  // Prioridade 1: variável de ambiente PROJECT_TYPE (WEB/FRONTEND or SCENARIOS)
431
430
  const projectTypeEnv = (process.env.PROJECT_TYPE || process.env.PROJECTTYPE || '').toUpperCase()
@@ -439,7 +438,7 @@ async function ensurePlaywrightInstalled(): Promise<void> {
439
438
 
440
439
  // Só instalar se o projeto for Web/Frontend ou Scenarios (por env ou por scripts indicativos)
441
440
  if (!hasPlaywright || !(isProjectTypeWebOrScenarios || hasFrontendScripts)) return
442
-
441
+
443
442
  // Verificar se os browsers já estão instalados em vários locais comuns
444
443
  function browsersPresent(dir: string): boolean {
445
444
  try {