terminal-smart-cli 0.43.0 → 0.45.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.
Files changed (2) hide show
  1. package/lib/meta.js +21 -3
  2. package/package.json +1 -1
package/lib/meta.js CHANGED
@@ -224,14 +224,25 @@ function _pngFramesDiff(frames) {
224
224
  // a página, captura ERROS DE CONSOLE (ex: "Invalid Date") e tira PRINT pro olho criticar o
225
225
  // visual. Se a home for uma TELA DE LOGIN, LOGA com o seed e verifica as telas AUTENTICADAS
226
226
  // (senão dashboard/kanban quebrados passariam batido). Dá pra web a MESMA verificação real que apps têm.
227
+ // escolhe uma porta: usa a preferida se estiver LIVRE, senão pega uma efêmera livre.
228
+ // robustez do gate: se a porta do código está ocupada (órfão/outro processo), NÃO trava —
229
+ // passa a porta escolhida ao servidor via PORT env e é ELA que o gate polla (o app respeita
230
+ // process.env.PORT). Neutraliza também o bug de "log com porta hardcoded".
231
+ function _pickPort(preferred) {
232
+ const net = require('net');
233
+ const testFree = (p) => new Promise(res => { const s = net.createServer(); s.once('error', () => res(false)); s.once('listening', () => s.close(() => res(true))); try { s.listen(p, '127.0.0.1'); } catch (_) { res(false); } });
234
+ const ephemeral = () => new Promise(res => { const s = net.createServer(); s.listen(0, '127.0.0.1', () => { const p = s.address().port; s.close(() => res(p)); }); s.once('error', () => res(preferred)); });
235
+ return testFree(preferred).then(free => free ? preferred : ephemeral());
236
+ }
237
+
227
238
  async function webRunGate(b, opts = {}) {
228
- const cwd = b.cwd, port = b.port || 3000, url = 'http://localhost:' + port + '/';
239
+ const cwd = b.cwd, port = await _pickPort(b.port || 3000), url = 'http://localhost:' + port + '/';
229
240
  // instala deps se faltarem
230
241
  try { if (!fs.existsSync(path.join(cwd, 'node_modules'))) { try { cp.execSync('npm install', { cwd, stdio: 'ignore', timeout: 240000 }); } catch (_) {} } } catch (_) {}
231
242
  // sobe o servidor (shell:true resolve npm.cmd no Windows; detached pra matar a árvore)
232
243
  let srv, srvlog = '';
233
244
  try {
234
- srv = cp.spawn(b.startCmd, { cwd, detached: process.platform !== 'win32', shell: true, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
245
+ srv = cp.spawn(b.startCmd, { cwd, env: { ...process.env, PORT: String(port) }, detached: process.platform !== 'win32', shell: true, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
235
246
  srv.stdout && srv.stdout.on('data', d => { srvlog += d.toString(); });
236
247
  srv.stderr && srv.stderr.on('data', d => { srvlog += d.toString(); });
237
248
  } catch (e) { return { ok: false, crash: 'não consegui iniciar o servidor: ' + e.message }; }
@@ -1024,6 +1035,13 @@ async function run(goal, opts = {}) {
1024
1035
  save(st, dir);
1025
1036
  } else {
1026
1037
  st.status = 'running';
1038
+ // RESUME = tentativa LIMPA. Sem isto, missão pausada por estagnação RE-TRAVA na hora
1039
+ // (contador/fp/erro-de-build persistidos no estado). Zera o watchdog + escalonamentos e
1040
+ // LIMPA o buildError velho → o gate RE-RODA do zero (pega fix de ambiente/harness que
1041
+ // resolveu o erro fora do código, ex: porta que estava ocupada). Se ainda falhar DE VERDADE,
1042
+ // os contadores re-acumulam normalmente nesta janela e o watchdog corta como sempre.
1043
+ st.stagnant = 0; st.lastFp = null; st.escalations = 0;
1044
+ st.buildError = ''; st.lastBuildSig = '';
1027
1045
  if (opts.addBudget) st.budget += opts.addBudget;
1028
1046
  else if (st.creditsSpent >= st.budget) st.budget = st.creditsSpent + budget; // nova janela ao retomar
1029
1047
  }
@@ -1143,7 +1161,7 @@ async function run(goal, opts = {}) {
1143
1161
  }
1144
1162
  st.lastBuildSig = sig;
1145
1163
  let fixItem = st.checklist.find(it => it.id === 'build_fix');
1146
- if (!fixItem) { fixItem = { id: 'build_fix', desc: (lang === 'en' ? 'Fix compile errors until the build succeeds and the APK is generated' : 'Corrigir os erros de compilação até o build passar e o APK ser gerado'), passes: false, attempts: 0, isBuild: true }; st.checklist.push(fixItem); }
1164
+ if (!fixItem) { const _webk = !!(b && b.kind === 'web'); fixItem = { id: 'build_fix', desc: (lang === 'en' ? (_webk ? 'Fix errors until the server starts and responds cleanly (web gate)' : 'Fix compile errors until the build succeeds and the APK is generated') : (_webk ? 'Corrigir os erros até o servidor subir e responder limpo (gate web)' : 'Corrigir os erros de compilação até o build passar e o APK ser gerado')), passes: false, attempts: 0, isBuild: true }; st.checklist.push(fixItem); }
1147
1165
  fixItem.passes = false; fixItem.blocked = false;
1148
1166
  save(st, dir);
1149
1167
  onRoundDone({ checklist: st.checklist, spent: st.creditsSpent, buildFailed: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "terminal-smart-cli",
3
- "version": "0.43.0",
3
+ "version": "0.45.0",
4
4
  "description": "Terminal Smart no seu terminal — pergunte, analise logs por pipe e orquestre agentes de IA. Comando: ts",
5
5
  "bin": {
6
6
  "ts": "bin/ts.js"