@diegosouzacdv/jev-browser-mcp 0.4.0 → 0.4.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.
package/README.md CHANGED
@@ -69,9 +69,11 @@ sessão do browser por processo e reutiliza essa sessão entre chamadas. O plano
69
69
  passado ao Jev continua declarativo: clique, preenchimento, seleção nativa,
70
70
  hover, espera, teclas aprovadas, asserções por elemento, upload restrito a uma
71
71
  raiz local configurada e reações idempotentes a um comentário único. Também
72
- aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
73
- JavaScript enviado pelo harness, seletores livres nem coordenadas. Ele usa a
74
- biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
72
+ aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
73
+ JavaScript enviado pelo harness nem coordenadas. Além de papel/nome acessível,
74
+ aceita `label`, `placeholder`, `title`, `text`, `test_id` e `selector`; CSS/XPath
75
+ são o último recurso e geram um aviso no resultado. Ele usa a
76
+ biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
75
77
  Playwright. O transporte MCP usa `stdio`; toda saída de diagnóstico vai para
76
78
  `stderr` para não misturar com JSON-RPC.
77
79
 
@@ -87,29 +89,55 @@ a página inicial, captura o snapshot acessível e pede ao Jev que escolha um
87
89
  plano. Em seguida, executa o plano inteiro na mesma sessão e confere o
88
90
  resultado esperado na tela.
89
91
 
90
- Cada plano pode usar:
91
-
92
- - `click`, `type`, `hover` e `select_option` com papel/nome acessível exatos;
92
+ Cada plano pode usar:
93
+
94
+ - `click`, `type`, `hover`, `select_option`, `press`, `assert_*` e upload com
95
+ papel/nome acessível ou um localizador: `label`, `placeholder`, `title`,
96
+ `text`, `test_id` ou `selector`;
97
+ - `near: {"text":"..."}` para localizar o controle logo depois de um texto,
98
+ e `within: {"row_containing":"..."}` para limitar a ação à linha certa;
99
+ - `within: {"role":"dialog"}` sem `name` para usar o único diálogo visível;
100
+ o MCP ignora diálogos visualmente ocultos, inclusive os que ficaram no DOM
101
+ com `opacity: 0`;
102
+ - `name: ""` com `index` não negativo para controles sem nome. O resultado
103
+ inclui um aviso porque a posição pode mudar entre execuções. O índice é
104
+ zero-based para o mesmo papel e segue o localizador Playwright
105
+ `{role, name: ""}`; controles desabilitados não aparecem no diagnóstico, mas
106
+ continuam contando para que o índice aponte ao controle correto;
107
+ - `selector` com CSS ou XPath como último recurso. O MCP identifica essa escolha
108
+ em `warnings`; não é permitido enviar JavaScript nem coordenadas;
93
109
  - `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
94
110
  - `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
95
111
  `blur: true` para desfocar o campo e `sensitive: false` para permitir que o
96
- valor apareça nas evidências;
112
+ valor apareça nas evidências. Nesse modo, `\n` envia Enter e `\t` envia Tab;
97
113
  - `wait_for_text` e `wait_for_condition` (`network_idle`, `hidden` ou
98
- `text_hidden`);
99
- - `press_key` com `PageDown`, `PageUp`, `Home`, `End`, `ArrowDown`, `ArrowUp`,
100
- `Enter`, `Escape` ou `Tab`;
114
+ `text_hidden`). `wait_for_text` aceita `fail_on: {"role":"alert"}` para
115
+ interromper a espera assim que um alerta visível aparecer e incluir seu texto
116
+ no erro. `network_idle` aceita `url_contains` para aguardar só as requisições
117
+ correspondentes;
118
+ - `press` (o alias legado `press_key` também é aceito) com `PageDown`, `PageUp`,
119
+ `Home`, `End`, setas, `Enter`, `Escape`, `Tab` ou `Shift+Tab`. Sem alvo,
120
+ envia a tecla ao elemento focado; com alvo, usa o localizador informado;
101
121
  - `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`; `assert_text`
102
122
  pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
103
123
  - `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
104
124
  dropzone;
105
125
  - `audit_accessibility` com axe-core para WCAG 2.1 A/AA;
106
- - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
107
- não repetem uma reação já no estado pedido e distinguem `Curtir` de
108
- `Descurtir`.
109
-
110
- Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
111
- container acessível único, como uma linha ou card. `index` escolhe uma ocorrência
112
- zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
126
+ - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
127
+ não repetem uma reação já no estado pedido e distinguem `Curtir` de
128
+ `Descurtir`.
129
+
130
+ Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
131
+ localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
132
+ aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
133
+ `url_contains`; o MCP precisa observar a requisição depois da etapa anterior e
134
+ esperar que ela termine.
135
+
136
+ Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
137
+ container acessível único, como uma linha, card ou diálogo. `index` escolhe uma
138
+ ocorrência zero-based dentro desse escopo; sem `index`, o MCP exige exatamente
139
+ um alvo. Para uma página com rótulo `for` quebrado, `label` também procura o
140
+ controle próximo ao texto visível do rótulo.
113
141
 
114
142
  ```json
115
143
  {
@@ -121,8 +149,43 @@ zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
121
149
  ```
122
150
 
123
151
  ```json
124
- {"action":"click","role":"button","name":"Add to cart","index":0}
125
- ```
152
+ {"action":"click","role":"button","name":"Add to cart","index":0}
153
+ ```
154
+
155
+ Exemplos para controles legados sem nome acessível:
156
+
157
+ ```json
158
+ {"action":"type","role":"textbox","label":"Vencimento","text":"05/10/2026"}
159
+ {"action":"type","role":"textbox","target_text":"Vencimento","text":"05/10/2026"}
160
+ {"action":"click","role":"link","title":"Editar documento","within":{"row_containing":"1528721"}}
161
+ {"action":"press","key":"Enter","role":"textbox","placeholder":"Busca rápida"}
162
+ {"action":"click","role":"button","name":"","index":0}
163
+ {"action":"click","selector":"#save-document"}
164
+ ```
165
+
166
+ O reconhecimento retorna `unnamed_controls_initial` e
167
+ `unnamed_controls_final`, cada um com papel, índice Playwright por papel, rótulo
168
+ mais próximo e um trecho HTML sanitizado dos controles visíveis e habilitados
169
+ sem nome. `unnamed_controls` continua disponível como alias da lista final. O
170
+ placeholder conta como nome acessível. O snapshot também resume campos de
171
+ formulário com `id`, `name`, valor, estado
172
+ desabilitado, rótulo e índice zero-based entre campos de mesmo nome. Valores
173
+ sensíveis, como senha, token e cartão, são ocultados. `snapshot_include_hidden`
174
+ é `false` por padrão; defina `true` somente quando precisar inspecionar campos
175
+ ocultos também.
176
+
177
+ Em uma etapa `type`, `text` contém o valor a digitar; use `target_text` para
178
+ localizar pelo texto visível próximo ao campo. Esse localizador exige `role`
179
+ `textbox`, `searchbox` ou `combobox`.
180
+
181
+ Por padrão, o MCP executa todos os passos antes de avaliar `expected_outcome`.
182
+ Valores dentro de campos não contam como resultado visível. `stop_on_expected:
183
+ true` habilita parada antecipada quando o texto esperado aparece fora dos
184
+ campos; mantenha `false` para fluxos com várias etapas.
185
+
186
+ Os erros de validação apontam o campo inválido e os campos aceitos. Os limites
187
+ de `timeout_seconds` informam o máximo configurado, em vez de exigir tentativa
188
+ e erro.
126
189
 
127
190
  ### Captura de downloads
128
191
 
@@ -159,12 +222,13 @@ trechos da página. Qualquer violação reprova esse fluxo. A auditoria automát
159
222
  encontra problemas comuns, mas não comprova conformidade WCAG completa; combine-a
160
223
  com revisão manual e testes com usuários assistivos.
161
224
 
162
- Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
163
- corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
164
- conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
165
- configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
166
- próximos quando o snapshot os encontrar. O plano não aceita JavaScript enviado
167
- pelo harness, coordenadas ou seletores livres.
225
+ Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
226
+ corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
227
+ conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
228
+ configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
229
+ próximos quando o snapshot os encontrar. CSS/XPath são permitidos somente como
230
+ localizadores explícitos de último recurso e geram aviso. O plano não aceita
231
+ JavaScript enviado pelo harness nem coordenadas.
168
232
 
169
233
  Os aliases `value` → `text` em `type`/`wait_for_text` e `value` → `expected` em
170
234
  asserções são aceitos. `comment` também é aceito em planos e passos, mas é
@@ -265,8 +329,16 @@ esse resultado e `expected_outcome_visible` continua descrevendo somente o
265
329
  texto global. `incomplete` significa que nenhum critério foi comprovado;
266
330
  confiança do Jev não substitui essa verificação. `timings_ms.ready_ms` mede a
267
331
  espera da SPA; `warnings` registra capturas vazias durante transições; e
268
- `failed_step` identifica índice, ação, alvo, timeout e erro resumido quando uma
269
- etapa falha.
332
+ `failed_step` identifica índice, ação, localizador, timeout e erro resumido
333
+ quando uma etapa falha. Cada etapa executada também registra a composição do
334
+ localizador usado e, quando disponível, `resolved_target` com tag, `id`, papel
335
+ e nome acessível do elemento resolvido. Etapas `type` só incluem o valor final
336
+ do campo quando `sensitive: false`.
337
+
338
+ Com `capture_network_error_bodies: true`, respostas JSON de erro da mesma
339
+ origem são capturadas mesmo quando usam transferência chunked e não enviam
340
+ `Content-Length`. Corpos acima do limite, com formato inválido ou que não
341
+ podem ser lidos com segurança são omitidos e explicados em `warnings`.
270
342
 
271
343
  `jev_browser_mcp.browser.max_action_timeout_seconds` limita esperas por ações,
272
344
  seletores e condições. `JEV_BROWSER_UPLOAD_ROOT` libera uploads somente dentro
@@ -285,11 +357,13 @@ continua informada mesmo quando a lista é truncada.
285
357
  O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
286
358
  `block_trackers`, `capture_console_errors`, `capture_network_errors`,
287
359
  `capture_network_error_bodies`, `ready_timeout_seconds`, `ready_network_idle`,
288
- `ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure` e
289
- `trace_on_failure`. Sem override, os padrões são lidos de `jev_browser_mcp` em
360
+ `ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure`,
361
+ `trace_on_failure`, `snapshot_include_hidden` e `stop_on_expected`. Sem override,
362
+ os padrões são lidos de `jev_browser_mcp` em
290
363
  `config/ui-testing.json`: um plano candidato pula a chamada Decisions;
291
364
  captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
292
- de recursos ficam desligados. O browser espera a SPA renderizar uma captura
365
+ de recursos ficam desligados; o plano roda até o fim e campos ocultos não são
366
+ acrescentados ao snapshot. O browser espera a SPA renderizar uma captura
293
367
  acessível estável. `ready_text` pode identificar o conteúdo que marca a
294
368
  prontidão. `reuse_page: true` pula a navegação somente quando a página e
295
369
  `initial_url` têm a mesma origem. `snapshot_scope` aceita `body`, `main` ou
@@ -32,6 +32,9 @@
32
32
  "max_step_timeout_seconds": 60,
33
33
  "key_delay_ms_default": 30,
34
34
  "reuse_page_default": false,
35
+ "stop_on_expected_default": false,
36
+ "snapshot_include_hidden_default": false,
37
+ "visibility_poll_interval_ms_default": 50,
35
38
  "capture_network_error_bodies_default": false,
36
39
  "max_network_error_body_bytes": 65536,
37
40
  "max_network_error_message_chars": 300,
@@ -69,9 +69,11 @@ sessão do browser por processo e reutiliza essa sessão entre chamadas. O plano
69
69
  passado ao Jev continua declarativo: clique, preenchimento, seleção nativa,
70
70
  hover, espera, teclas aprovadas, asserções por elemento, upload restrito a uma
71
71
  raiz local configurada e reações idempotentes a um comentário único. Também
72
- aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
73
- JavaScript enviado pelo harness, seletores livres nem coordenadas. Ele usa a
74
- biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
72
+ aceita um nome de iframe para as ações que ocorrem dentro dele. Não aceita
73
+ JavaScript enviado pelo harness nem coordenadas. Além de papel/nome acessível,
74
+ aceita `label`, `placeholder`, `title`, `text`, `test_id` e `selector`; CSS/XPath
75
+ são o último recurso e geram um aviso no resultado. Ele usa a
76
+ biblioteca Playwright diretamente, sem iniciar um segundo servidor MCP do
75
77
  Playwright. O transporte MCP usa `stdio`; toda saída de diagnóstico vai para
76
78
  `stderr` para não misturar com JSON-RPC.
77
79
 
@@ -87,29 +89,55 @@ a página inicial, captura o snapshot acessível e pede ao Jev que escolha um
87
89
  plano. Em seguida, executa o plano inteiro na mesma sessão e confere o
88
90
  resultado esperado na tela.
89
91
 
90
- Cada plano pode usar:
91
-
92
- - `click`, `type`, `hover` e `select_option` com papel/nome acessível exatos;
92
+ Cada plano pode usar:
93
+
94
+ - `click`, `type`, `hover`, `select_option`, `press`, `assert_*` e upload com
95
+ papel/nome acessível ou um localizador: `label`, `placeholder`, `title`,
96
+ `text`, `test_id` ou `selector`;
97
+ - `near: {"text":"..."}` para localizar o controle logo depois de um texto,
98
+ e `within: {"row_containing":"..."}` para limitar a ação à linha certa;
99
+ - `within: {"role":"dialog"}` sem `name` para usar o único diálogo visível;
100
+ o MCP ignora diálogos visualmente ocultos, inclusive os que ficaram no DOM
101
+ com `opacity: 0`;
102
+ - `name: ""` com `index` não negativo para controles sem nome. O resultado
103
+ inclui um aviso porque a posição pode mudar entre execuções. O índice é
104
+ zero-based para o mesmo papel e segue o localizador Playwright
105
+ `{role, name: ""}`; controles desabilitados não aparecem no diagnóstico, mas
106
+ continuam contando para que o índice aponte ao controle correto;
107
+ - `selector` com CSS ou XPath como último recurso. O MCP identifica essa escolha
108
+ em `warnings`; não é permitido enviar JavaScript nem coordenadas;
93
109
  - `timeout_seconds` opcional em cada etapa, limitado pela configuração central;
94
110
  - `type` com `mode: "keys"` para digitar sequencialmente em campos com máscara,
95
111
  `blur: true` para desfocar o campo e `sensitive: false` para permitir que o
96
- valor apareça nas evidências;
112
+ valor apareça nas evidências. Nesse modo, `\n` envia Enter e `\t` envia Tab;
97
113
  - `wait_for_text` e `wait_for_condition` (`network_idle`, `hidden` ou
98
- `text_hidden`);
99
- - `press_key` com `PageDown`, `PageUp`, `Home`, `End`, `ArrowDown`, `ArrowUp`,
100
- `Enter`, `Escape` ou `Tab`;
114
+ `text_hidden`). `wait_for_text` aceita `fail_on: {"role":"alert"}` para
115
+ interromper a espera assim que um alerta visível aparecer e incluir seu texto
116
+ no erro. `network_idle` aceita `url_contains` para aguardar só as requisições
117
+ correspondentes;
118
+ - `press` (o alias legado `press_key` também é aceito) com `PageDown`, `PageUp`,
119
+ `Home`, `End`, setas, `Enter`, `Escape`, `Tab` ou `Shift+Tab`. Sem alvo,
120
+ envia a tecla ao elemento focado; com alvo, usa o localizador informado;
101
121
  - `assert_text`, `assert_value`, `assert_visible` e `assert_hidden`; `assert_text`
102
122
  pode receber apenas `role` quando a região, como `alert`, não tem nome acessível;
103
123
  - `upload_file` para input rotulado, botão que abre o seletor de arquivo ou
104
124
  dropzone;
105
125
  - `audit_accessibility` com axe-core para WCAG 2.1 A/AA;
106
- - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
107
- não repetem uma reação já no estado pedido e distinguem `Curtir` de
108
- `Descurtir`.
109
-
110
- Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
111
- container acessível único, como uma linha ou card. `index` escolhe uma ocorrência
112
- zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
126
+ - `like_comment` e `unlike_comment`, que localizam uma linha pelo autor e texto,
127
+ não repetem uma reação já no estado pedido e distinguem `Curtir` de
128
+ `Descurtir`.
129
+
130
+ Em `wait_for_condition` com `condition: "hidden"`, use qualquer um desses
131
+ localizadores, `near` ou `within`; `text_hidden` recebe o texto direto. Para
132
+ aguardar o fim de uma chamada específica, use `condition: "network_idle"` com
133
+ `url_contains`; o MCP precisa observar a requisição depois da etapa anterior e
134
+ esperar que ela termine.
135
+
136
+ Quando vários controles têm o mesmo papel e nome, `within` limita a busca a um
137
+ container acessível único, como uma linha, card ou diálogo. `index` escolhe uma
138
+ ocorrência zero-based dentro desse escopo; sem `index`, o MCP exige exatamente
139
+ um alvo. Para uma página com rótulo `for` quebrado, `label` também procura o
140
+ controle próximo ao texto visível do rótulo.
113
141
 
114
142
  ```json
115
143
  {
@@ -121,8 +149,43 @@ zero-based dentro desse escopo; sem `index`, o MCP exige exatamente um alvo.
121
149
  ```
122
150
 
123
151
  ```json
124
- {"action":"click","role":"button","name":"Add to cart","index":0}
125
- ```
152
+ {"action":"click","role":"button","name":"Add to cart","index":0}
153
+ ```
154
+
155
+ Exemplos para controles legados sem nome acessível:
156
+
157
+ ```json
158
+ {"action":"type","role":"textbox","label":"Vencimento","text":"05/10/2026"}
159
+ {"action":"type","role":"textbox","target_text":"Vencimento","text":"05/10/2026"}
160
+ {"action":"click","role":"link","title":"Editar documento","within":{"row_containing":"1528721"}}
161
+ {"action":"press","key":"Enter","role":"textbox","placeholder":"Busca rápida"}
162
+ {"action":"click","role":"button","name":"","index":0}
163
+ {"action":"click","selector":"#save-document"}
164
+ ```
165
+
166
+ O reconhecimento retorna `unnamed_controls_initial` e
167
+ `unnamed_controls_final`, cada um com papel, índice Playwright por papel, rótulo
168
+ mais próximo e um trecho HTML sanitizado dos controles visíveis e habilitados
169
+ sem nome. `unnamed_controls` continua disponível como alias da lista final. O
170
+ placeholder conta como nome acessível. O snapshot também resume campos de
171
+ formulário com `id`, `name`, valor, estado
172
+ desabilitado, rótulo e índice zero-based entre campos de mesmo nome. Valores
173
+ sensíveis, como senha, token e cartão, são ocultados. `snapshot_include_hidden`
174
+ é `false` por padrão; defina `true` somente quando precisar inspecionar campos
175
+ ocultos também.
176
+
177
+ Em uma etapa `type`, `text` contém o valor a digitar; use `target_text` para
178
+ localizar pelo texto visível próximo ao campo. Esse localizador exige `role`
179
+ `textbox`, `searchbox` ou `combobox`.
180
+
181
+ Por padrão, o MCP executa todos os passos antes de avaliar `expected_outcome`.
182
+ Valores dentro de campos não contam como resultado visível. `stop_on_expected:
183
+ true` habilita parada antecipada quando o texto esperado aparece fora dos
184
+ campos; mantenha `false` para fluxos com várias etapas.
185
+
186
+ Os erros de validação apontam o campo inválido e os campos aceitos. Os limites
187
+ de `timeout_seconds` informam o máximo configurado, em vez de exigir tentativa
188
+ e erro.
126
189
 
127
190
  ### Captura de downloads
128
191
 
@@ -159,12 +222,13 @@ trechos da página. Qualquer violação reprova esse fluxo. A auditoria automát
159
222
  encontra problemas comuns, mas não comprova conformidade WCAG completa; combine-a
160
223
  com revisão manual e testes com usuários assistivos.
161
224
 
162
- Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
163
- corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
164
- conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
165
- configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
166
- próximos quando o snapshot os encontrar. O plano não aceita JavaScript enviado
167
- pelo harness, coordenadas ou seletores livres.
225
+ Para ações em iframe, acrescente `"frame": "payment-iframe"`; o valor precisa
226
+ corresponder ao atributo `name` ou `title` do iframe. O snapshot inclui o
227
+ conteúdo acessível dos iframes nomeados dentro do escopo, limitado pela
228
+ configuração. Se um alvo estiver ausente, o erro inclui até três nomes acessíveis
229
+ próximos quando o snapshot os encontrar. CSS/XPath são permitidos somente como
230
+ localizadores explícitos de último recurso e geram aviso. O plano não aceita
231
+ JavaScript enviado pelo harness nem coordenadas.
168
232
 
169
233
  Os aliases `value` → `text` em `type`/`wait_for_text` e `value` → `expected` em
170
234
  asserções são aceitos. `comment` também é aceito em planos e passos, mas é
@@ -265,8 +329,16 @@ esse resultado e `expected_outcome_visible` continua descrevendo somente o
265
329
  texto global. `incomplete` significa que nenhum critério foi comprovado;
266
330
  confiança do Jev não substitui essa verificação. `timings_ms.ready_ms` mede a
267
331
  espera da SPA; `warnings` registra capturas vazias durante transições; e
268
- `failed_step` identifica índice, ação, alvo, timeout e erro resumido quando uma
269
- etapa falha.
332
+ `failed_step` identifica índice, ação, localizador, timeout e erro resumido
333
+ quando uma etapa falha. Cada etapa executada também registra a composição do
334
+ localizador usado e, quando disponível, `resolved_target` com tag, `id`, papel
335
+ e nome acessível do elemento resolvido. Etapas `type` só incluem o valor final
336
+ do campo quando `sensitive: false`.
337
+
338
+ Com `capture_network_error_bodies: true`, respostas JSON de erro da mesma
339
+ origem são capturadas mesmo quando usam transferência chunked e não enviam
340
+ `Content-Length`. Corpos acima do limite, com formato inválido ou que não
341
+ podem ser lidos com segurança são omitidos e explicados em `warnings`.
270
342
 
271
343
  `jev_browser_mcp.browser.max_action_timeout_seconds` limita esperas por ações,
272
344
  seletores e condições. `JEV_BROWSER_UPLOAD_ROOT` libera uploads somente dentro
@@ -285,11 +357,13 @@ continua informada mesmo quando a lista é truncada.
285
357
  O `run_browser_flow` aceita `options` com `fast_path`, `snapshot_scope`,
286
358
  `block_trackers`, `capture_console_errors`, `capture_network_errors`,
287
359
  `capture_network_error_bodies`, `ready_timeout_seconds`, `ready_network_idle`,
288
- `ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure` e
289
- `trace_on_failure`. Sem override, os padrões são lidos de `jev_browser_mcp` em
360
+ `ready_stable_ms`, `ready_text`, `reuse_page`, `screenshot_on_failure`,
361
+ `trace_on_failure`, `snapshot_include_hidden` e `stop_on_expected`. Sem override,
362
+ os padrões são lidos de `jev_browser_mcp` em
290
363
  `config/ui-testing.json`: um plano candidato pula a chamada Decisions;
291
364
  captura de console e screenshot de falha ficam ligadas; trace, rede e bloqueio
292
- de recursos ficam desligados. O browser espera a SPA renderizar uma captura
365
+ de recursos ficam desligados; o plano roda até o fim e campos ocultos não são
366
+ acrescentados ao snapshot. O browser espera a SPA renderizar uma captura
293
367
  acessível estável. `ready_text` pode identificar o conteúdo que marca a
294
368
  prontidão. `reuse_page: true` pula a navegação somente quando a página e
295
369
  `initial_url` têm a mesma origem. `snapshot_scope` aceita `body`, `main` ou
@@ -27,6 +27,9 @@ const CONFIG_KEYS = {
27
27
  "max_step_timeout_seconds",
28
28
  "key_delay_ms_default",
29
29
  "reuse_page_default",
30
+ "stop_on_expected_default",
31
+ "snapshot_include_hidden_default",
32
+ "visibility_poll_interval_ms_default",
30
33
  "capture_network_error_bodies_default",
31
34
  "max_network_error_body_bytes",
32
35
  "max_network_error_message_chars",
@@ -264,6 +267,7 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
264
267
  postStepReadyTimeoutMs: postStepReadyTimeoutSeconds * 1000,
265
268
  maxStepTimeoutSeconds: positiveNumber(browserOptions.max_step_timeout_seconds, "jev_browser_mcp.browser.max_step_timeout_seconds"),
266
269
  keyDelayMs: positiveNumber(browserOptions.key_delay_ms_default, "jev_browser_mcp.browser.key_delay_ms_default", true),
270
+ visibilityPollMs: positiveNumber(browserOptions.visibility_poll_interval_ms_default, "jev_browser_mcp.browser.visibility_poll_interval_ms_default", true),
267
271
  maxNetworkErrorBodyBytes: positiveNumber(browserOptions.max_network_error_body_bytes, "jev_browser_mcp.browser.max_network_error_body_bytes", true),
268
272
  maxNetworkErrorMessageChars: positiveNumber(browserOptions.max_network_error_message_chars, "jev_browser_mcp.browser.max_network_error_message_chars", true),
269
273
  maxUploadFiles: positiveNumber(browserOptions.max_upload_files, "jev_browser_mcp.browser.max_upload_files", true),
@@ -287,6 +291,8 @@ export function loadSettings({ env = process.env, configPath = CONFIG_PATH } = {
287
291
  blockTrackers: booleanValue(browserOptions.block_trackers_default, "jev_browser_mcp.browser.block_trackers_default"),
288
292
  readyNetworkIdle: booleanValue(browserOptions.ready_network_idle_default, "jev_browser_mcp.browser.ready_network_idle_default"),
289
293
  reusePage: booleanValue(browserOptions.reuse_page_default, "jev_browser_mcp.browser.reuse_page_default"),
294
+ stopOnExpected: booleanValue(browserOptions.stop_on_expected_default, "jev_browser_mcp.browser.stop_on_expected_default"),
295
+ snapshotIncludeHidden: booleanValue(browserOptions.snapshot_include_hidden_default, "jev_browser_mcp.browser.snapshot_include_hidden_default"),
290
296
  readyTimeoutSeconds: readyTimeoutSecondsDefault,
291
297
  readyStableMs: readyStableMsDefault,
292
298
  snapshotScope,