<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>TabNews</title>
        <link>https://www.tabnews.com.br/recentes/rss</link>
        <description>Conteúdos para quem trabalha com Programação e Tecnologia</description>
        <lastBuildDate>Sat, 12 Sep 2026 00:10:36 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>pt</language>
        <image>
            <title>TabNews</title>
            <url>https://www.tabnews.com.br/favicon-mobile.png</url>
            <link>https://www.tabnews.com.br/recentes/rss</link>
        </image>
        <item>
            <title><![CDATA[Criei um site de empregos que ajuda as pessoas, tem bastante acesso, mas nao consigo monetizar nada]]></title>
            <link>https://www.tabnews.com.br/gustavoludtke/criei-um-site-de-empregos-que-ajuda-as-pessoas-tem-bastante-acesso-mas-nao-consigo-monetizar-nada</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/gustavoludtke/criei-um-site-de-empregos-que-ajuda-as-pessoas-tem-bastante-acesso-mas-nao-consigo-monetizar-nada</guid>
            <pubDate>Sat, 12 Sep 2026 00:10:36 GMT</pubDate>
            <description><![CDATA[Meu objetivo é ajudar as pessoas, mas está dificil ajudar sem ter nenhuma verba para ajudar a pagar os anuncios (que é a engrenagem do projeto). Tenho varios programas que ajudam, como um...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Meu objetivo é ajudar as pessoas, mas está dificil ajudar sem ter nenhuma verba para ajudar a pagar os anuncios (que é a engrenagem do projeto). Tenho varios programas que ajudam, como um ajustador de currículo online e mais coisas. Alguém tem ideias para contribuir?<br><a href="https://opiniaosul.com" rel="nofollow">https://opiniaosul.com</a></p></div>]]></content:encoded>
            <author>gustavoludtke</author>
        </item>
        <item>
            <title><![CDATA[CSS4 não existe. Mas o CSS de 2026 já reage a tamanho, estado, posição e scroll]]></title>
            <link>https://www.tabnews.com.br/mrmsoares/css4-nao-existe-mas-o-css-de-2026-ja-reage-a-tamanho-estado-posicao-e-scroll</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/mrmsoares/css4-nao-existe-mas-o-css-de-2026-ja-reage-a-tamanho-estado-posicao-e-scroll</guid>
            <pubDate>Fri, 11 Sep 2026 23:44:00 GMT</pubDate>
            <description><![CDATA[CSS3, CSS4 e CSS5 se fragmentando em módulos modernos ao redor de um núcleo luminoso de CSS Em 2020, publiquei um texto dizendo que CSS4 nunca existiria como a próxima versão única do CSS...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p><a href="https://www.vivodecodigo.com.br/frontend/qual-e-a-versao-atual-do-css?utm_source=tabnews&#x26;utm_medium=community&#x26;utm_campaign=css4-css5-2026&#x26;utm_content=cover" rel="nofollow"><img src="https://www.vivodecodigo.com.br/covers/qual-e-a-versao-atual-do-css-og.webp" alt="CSS3, CSS4 e CSS5 se fragmentando em módulos modernos ao redor de um núcleo luminoso de CSS"></a></p><p>Em 2020, publiquei um texto dizendo que CSS4 nunca existiria como a próxima versão única do CSS. Recentemente, um leitor encontrou aquele artigo e disse que eu não estava sendo totalmente sincero.</p><p>Ele tocou no ponto certo.</p><p>Não porque o W3C tenha lançado um pacote chamado CSS4. Isso não aconteceu. O problema é que responder apenas "CSS4 não existe" deixa de fora quase tudo o que aconteceu com a linguagem nos últimos seis anos.</p><p>A resposta curta e precisa, em setembro de 2026, é esta:</p><blockquote><p><strong>CSS4 e CSS5 não existem como versões oficiais únicas da linguagem. Depois do CSS Level 3, os módulos passaram a evoluir de maneira independente. Por isso existem Selectors Level 4, CSS Color Level 4 e CSS Cascade Level 5 sem existir uma versão global chamada CSS4 ou CSS5.</strong></p></blockquote><p>Só que a discussão do nome ficou pequena. O CSS atual já consegue reagir ao tamanho de um componente, ao estado dos elementos dentro dele, à posição do scroll e à localização de uma âncora. Ele também ganhou estados nativos de interface, trajetórias de movimento, formas declarativas e espaços de cor perceptuais.</p><p>A pergunta útil deixou de ser "qual é a versão do CSS?". Agora ela é: <strong>como saber o que já pode entrar em produção e o que ainda precisa de fallback?</strong></p><h2 id="mrmsoares-content-snapshot-baseline-e-interop-respondem-a-perguntas-diferentes">Snapshot, Baseline e Interop respondem a perguntas diferentes</h2><p>Tratar esses três projetos como sinônimos cria uma falsa sensação de segurança.</p><table><thead><tr><th align="left">Referência</th><th align="left">Pergunta que ela ajuda a responder</th><th align="left">O que ela não garante</th></tr></thead><tbody><tr><td align="left"><a href="https://www.w3.org/TR/css-2025/" rel="nofollow">CSS Snapshot</a></td><td align="left">Quais especificações formam o estado atual do CSS segundo sua estabilidade normativa?</td><td align="left">Adoção completa pelos navegadores usados no seu produto</td></tr><tr><td align="left"><a href="https://web.dev/baseline/2026" rel="nofollow">Baseline</a></td><td align="left">O recurso chegou ao conjunto principal de navegadores acompanhado pelo projeto?</td><td align="left">Compatibilidade com toda versão antiga, WebView ou browser corporativo</td></tr><tr><td align="left"><a href="https://web.dev/blog/interop-2026" rel="nofollow">Interop</a></td><td align="left">Em quais áreas os motores estão trabalhando para aumentar a convergência?</td><td align="left">Suporte completo ou idêntico naquele momento</td></tr></tbody></table><p>O CSS Snapshot 2025 é explícito: módulos independentes podem chegar ao Level 4 ou além, mas a linguagem inteira não possui mais esses níveis. O mesmo documento também avisa que a inclusão de um módulo considera estabilidade da especificação, não sua taxa de adoção nos browsers.</p><p>Baseline e Interop completam a análise, mas a decisão final ainda depende da sua audiência e do papel daquele recurso na interface.</p><h2 id="mrmsoares-content-três-provas-de-que-o-problema-mudou">Três provas de que o problema mudou</h2><h3 id="mrmsoares-content-1-um-componente-pode-responder-ao-próprio-espaço-e-ao-estado-interno">1. Um componente pode responder ao próprio espaço e ao estado interno</h3><p>Media queries observam o viewport. Container queries permitem que a unidade responda ao espaço que realmente recebeu no layout.</p><pre><code class="hljs language-html"><span class="hljs-tag">&#x3C;<span class="hljs-name">article</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"probe"</span>></span>  <span class="hljs-tag">&#x3C;<span class="hljs-name">label</span>></span>    <span class="hljs-tag">&#x3C;<span class="hljs-name">input</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"advanced"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"checkbox"</span>></span>    Exibir telemetria avançada  <span class="hljs-tag">&#x3C;/<span class="hljs-name">label</span>></span>  <span class="hljs-tag">&#x3C;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"probe__layout"</span>></span>    <span class="hljs-tag">&#x3C;<span class="hljs-name">section</span>></span>Métricas<span class="hljs-tag">&#x3C;/<span class="hljs-name">section</span>></span>    <span class="hljs-tag">&#x3C;<span class="hljs-name">aside</span>></span>Detalhes<span class="hljs-tag">&#x3C;/<span class="hljs-name">aside</span>></span>  <span class="hljs-tag">&#x3C;/<span class="hljs-name">div</span>></span><span class="hljs-tag">&#x3C;/<span class="hljs-name">article</span>></span></code></pre><pre><code class="hljs language-css"><span class="hljs-selector-class">.probe</span> {  container: probe / inline-size;}<span class="hljs-selector-class">.probe__layout</span> {  <span class="hljs-attribute">display</span>: grid;  <span class="hljs-attribute">gap</span>: <span class="hljs-number">1rem</span>;}<span class="hljs-keyword">@container</span> probe (<span class="hljs-attribute">min-width</span>: <span class="hljs-number">36rem</span>) {  <span class="hljs-selector-class">.probe__layout</span> {    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">2</span>fr <span class="hljs-number">1</span>fr;  }}<span class="hljs-selector-class">.probe</span><span class="hljs-selector-pseudo">:has</span>(<span class="hljs-selector-id">#advanced</span><span class="hljs-selector-pseudo">:checked</span>) {  <span class="hljs-attribute">border-color</span>: <span class="hljs-built_in">oklch</span>(<span class="hljs-number">72%</span> <span class="hljs-number">0.2</span> <span class="hljs-number">250</span>);}</code></pre><p>O layout responde ao contêiner, não à tela inteira. O elemento pai reage ao checkbox com <code>:has()</code>, sem listener de clique e sem uma classe sincronizada por JavaScript.</p><p>Isso não transforma CSS em linguagem de regra de negócio. Significa apenas que decisões de apresentação podem permanecer na camada que já conhece o layout e a estrutura.</p><h3 id="mrmsoares-content-2-um-popover-pode-abrir-e-se-posicionar-sem-calcular-coordenadas">2. Um popover pode abrir e se posicionar sem calcular coordenadas</h3><p>O HTML representa a abertura. O CSS relaciona o painel à sua âncora.</p><pre><code class="hljs language-html"><span class="hljs-tag">&#x3C;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"beacon"</span> <span class="hljs-attr">popovertarget</span>=<span class="hljs-string">"telemetry"</span>></span>  Abrir telemetria<span class="hljs-tag">&#x3C;/<span class="hljs-name">button</span>></span><span class="hljs-tag">&#x3C;<span class="hljs-name">aside</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"telemetry"</span> <span class="hljs-attr">popover</span>></span>  Dados do módulo selecionado<span class="hljs-tag">&#x3C;/<span class="hljs-name">aside</span>></span></code></pre><pre><code class="hljs language-css"><span class="hljs-selector-class">.beacon</span> {  anchor-name: --beacon;}<span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">position-anchor</span>: --beacon) {  <span class="hljs-selector-id">#telemetry</span>:popover-open {    <span class="hljs-attribute">position</span>-anchor: --beacon;    <span class="hljs-attribute">top</span>: <span class="hljs-built_in">anchor</span>(bottom);    <span class="hljs-attribute">left</span>: <span class="hljs-built_in">anchor</span>(center);    translate: -<span class="hljs-number">50%</span> <span class="hljs-number">0.5rem</span>;  }}</code></pre><p>Sem anchor positioning, o popover nativo ainda pode abrir. A camada nova melhora a posição sem transformar sua ausência em falha funcional.</p><h3 id="mrmsoares-content-3-a-posição-do-scroll-pode-dirigir-a-animação">3. A posição do scroll pode dirigir a animação</h3><pre><code class="hljs language-css"><span class="hljs-selector-class">.timeline</span> {  <span class="hljs-attribute">overflow-x</span>: auto;  <span class="hljs-attribute">scroll-snap-type</span>: inline mandatory;  scroll-timeline: --history inline;}<span class="hljs-selector-class">.progress</span> {  <span class="hljs-attribute">transform-origin</span>: left;  <span class="hljs-attribute">animation</span>: fill linear both;  <span class="hljs-attribute">animation</span>-timeline: --history;}<span class="hljs-keyword">@keyframes</span> fill {  <span class="hljs-selector-tag">from</span> { scale: <span class="hljs-number">0.05</span> <span class="hljs-number">1</span>; }  <span class="hljs-selector-tag">to</span> { scale: <span class="hljs-number">1</span> <span class="hljs-number">1</span>; }}</code></pre><p>Não há evento <code>scroll</code>, cálculo manual de porcentagem nem <code>requestAnimationFrame</code>. Sem a timeline, o conteúdo continua rolável e o <code>scroll-snap</code> continua útil. O efeito é progressivo.</p><h2 id="mrmsoares-content-o-experimento-que-não-cabia-em-uma-coleção-de-snippets">O experimento que não cabia em uma coleção de snippets</h2><p>Snippets separados mostram sintaxe. Eles não provam que os recursos conseguem formar uma interface coerente.</p><p>Por isso construí o <strong>Observatório CSS 2026</strong>, uma central interativa que combina nove capacidades em um único sistema:</p><ol><li>container queries;</li><li><code>:has()</code>;</li><li>estados nativos com <code>:checked</code>, <code>:open</code> e <code>:target</code>;</li><li>animações guiadas pelo scroll;</li><li>anchor positioning e popover;</li><li>navegação por fragmentos;</li><li>motion path;</li><li><code>clip-path</code> com <code>shape()</code> progressivo;</li><li>OKLCH, <code>color-mix()</code> e <code>contrast-color()</code>.</li></ol><p>Os controles usam HTML nativo. Não há JavaScript mantendo o estado das interações. O componente também preserva conteúdo e operação quando uma camada recente não está disponível, funciona por teclado e respeita <code>prefers-reduced-motion</code>.</p><p>Você pode testar a interface aqui:</p><h3 id="mrmsoares-content-abrir-o-observatório-css-2026-e-testar-as-nove-capacidades"><a href="https://www.vivodecodigo.com.br/frontend/qual-e-a-versao-atual-do-css?utm_source=tabnews&#x26;utm_medium=community&#x26;utm_campaign=css4-css5-2026&#x26;utm_content=observatorio" rel="nofollow">Abrir o Observatório CSS 2026 e testar as nove capacidades</a></h3><h2 id="mrmsoares-content-o-critério-que-uso-antes-de-colocar-css-novo-em-produção">O critério que uso antes de colocar CSS novo em produção</h2><p>Uma demonstração impressionante ainda não é uma decisão de produto. Para cada recurso, faço cinco perguntas:</p><ol><li><strong>Qual é a fonte da afirmação?</strong> Localizo o módulo, seu estágio e documentação de compatibilidade datada.</li><li><strong>A funcionalidade é essencial ou progressiva?</strong> Comprar, autenticar e ler exigem um limiar diferente de uma transição visual.</li><li><strong>Qual tarefa permanece sem o recurso?</strong> Fallback deve preservar informação e operação, não necessariamente reproduzir cada pixel.</li><li><strong>A matriz genérica representa meus usuários?</strong> Baseline não conhece WebViews antigas, políticas corporativas nem os dados reais do seu produto.</li><li><strong>Quando essa decisão será revista?</strong> Registro data, navegadores testados, fallback e condição para removê-lo.</li></ol><p>O princípio é simples:</p><pre><code class="hljs language-css"><span class="hljs-selector-class">.feature</span> {  <span class="hljs-comment">/* Base legível e funcional para todos. */</span>}<span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">position-anchor</span>: --menu-trigger) {  <span class="hljs-selector-class">.feature</span> {    <span class="hljs-comment">/* Melhoria aplicada somente quando a capacidade existe. */</span>  }}</code></pre><p>CSS moderno não elimina fundamentos. Ele recompensa HTML semântico, cascade compreendida, acessibilidade e fallbacks deliberados.</p><h2 id="mrmsoares-content-então-qual-versão-do-css-você-usa">Então qual versão do CSS você usa?</h2><p>Na maioria dos projetos, a resposta mais honesta é apenas <strong>CSS</strong>.</p><p>Quando precisar de precisão, cite o recurso ou o módulo: container queries, Selectors Level 4, CSS Color 4, Cascade Layers. Se a conversa for sobre adoção, acrescente o estado Baseline e os browsers realmente testados.</p><p>CSS4 não virou o sucessor oficial de CSS3. CSS5 também não. Ao mesmo tempo, níveis 4 e 5 são reais dentro dos módulos, e existe até um grupo comunitário discutindo CSS4 como rótulo didático, separado das normas oficiais.</p><p>O leitor que questionou meu texto antigo tinha razão sobre o problema central: dizer somente que CSS4 não existe já não explica o CSS que usamos hoje.</p><p>A versão completa reúne a história, a distinção entre os níveis, as fontes verificadas em setembro de 2026, os nove exemplos, os fallbacks e o Observatório funcionando no navegador:</p><h3 id="mrmsoares-content-ler-o-artigo-completo-e-experimentar-o-css-de-2026"><a href="https://www.vivodecodigo.com.br/frontend/qual-e-a-versao-atual-do-css?utm_source=tabnews&#x26;utm_medium=community&#x26;utm_campaign=css4-css5-2026&#x26;utm_content=cta-final" rel="nofollow">Ler o artigo completo e experimentar o CSS de 2026</a></h3><p>Qual desses recursos mudou mais a forma como você escreve CSS? E qual ainda parece cedo demais para o seu ambiente de produção?</p></div>]]></content:encoded>
            <author>mrmsoares</author>
        </item>
        <item>
            <title><![CDATA[Pitch: atomicvulns — um laboratório de vulnerabilidades web, uma vuln por vez]]></title>
            <link>https://www.tabnews.com.br/doretox/atomicvulns-um-laboratorio-de-vulnerabilidades-web-uma-vuln-por-vez</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/doretox/atomicvulns-um-laboratorio-de-vulnerabilidades-web-uma-vuln-por-vez</guid>
            <pubDate>Fri, 11 Sep 2026 20:04:13 GMT</pubDate>
            <description><![CDATA[Passei os últimos meses construindo um projeto pessoal e ele chegou na v1.0, então resolvi compartilhar. O atomicvulns é uma coleção de apps web propositalmente vulneráveis, mas com uma i...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Passei os últimos meses construindo um projeto pessoal e ele chegou na v1.0, então resolvi compartilhar.</p><p>O atomicvulns é uma coleção de apps web propositalmente vulneráveis, mas com uma ideia diferente: cada app isola uma única vulnerabilidade, nada além disso. Em vez de um sistema gigante cheio de falhas (tipo DVWA ou Juice Shop), aqui cada exercício é pequeno e focado — você lê o código, vê a causa, explora, e compara com a versão corrigida ao lado.</p><p>Cada "átomo" vem com o app vulnerável, o app corrigido, um diff comentado entre os dois, e um walkthrough do exploit passo a passo. A v1.0 cobre as 10 categorias do OWASP Top 10 2021 com 38 átomos no total.</p><p>É pra quem está estudando pentest / AppSec e já manja o básico de HTTP e terminal, o Burp Suite é a ferramenta principal em todos os walkthroughs.</p><p>Alguns detalhes:</p><ul><li>Open source (MIT).</li><li>Bilíngue — toda a documentação em inglês e português, porque senti falta de material assim pra quem estuda em PT-BR.</li><li>Projeto solo, feito por mim. Meu foco foi ter um lugar onde cada falha fica clara e isolada, o material que eu queria ter tido enquanto estudava e aprendia pentest web.</li><li>Construído em par com IA, com cada átomo validado por mim rodando o exploit na mão.</li></ul><p>Fiz pra mim, mas agora que está pronto, se ajudar mais alguém no caminho, ótimo.</p><p>🔗 <a href="https://github.com/doretox/atomicvulns">https://github.com/doretox/atomicvulns</a></p></div>]]></content:encoded>
            <author>doretox</author>
        </item>
        <item>
            <title><![CDATA[Você está usando IA do jeito errado]]></title>
            <link>https://www.tabnews.com.br/moacirmoda/voce-esta-usando-ia-do-jeito-errado</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/moacirmoda/voce-esta-usando-ia-do-jeito-errado</guid>
            <pubDate>Fri, 11 Sep 2026 18:54:52 GMT</pubDate>
            <description><![CDATA[O próximo salto é dar a ela contexto, ferramentas e memória Você abre o ChatGPT, escreve um prompt, recebe uma resposta e fecha a aba. Parece que está usando IA. Mas, na prática, você ape...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><h2 id="moacirmoda-content-o-próximo-salto-é-dar-a-ela-contexto-ferramentas-e-memória">O próximo salto é dar a ela contexto, ferramentas e memória</h2><p>Você abre o ChatGPT, escreve um prompt, recebe uma resposta e fecha a aba. Parece que está usando IA. Mas, na prática, você apenas trocou a caixa de busca por uma caixa de conversa.</p><p>Nos últimos meses, montei um sistema em que a IA não apenas responde: ela encontra o que precisa e executa o trabalho. Na edição de hoje da Newsletter do Moa, vou abrir essa arquitetura em detalhes para você copiar.</p><h3 id="moacirmoda-content-meu-setup-de-ia-não-está-no-meu-computador">Meu setup de IA não está no meu computador</h3><p>Semana passada, eu estava conversando com meu amigo Henrique Bastos sobre como tenho usado inteligência artificial no meu dia a dia.</p><p>Em algum momento, contei que uso o 1Password para guardar as credenciais de que minhas ferramentas de IA precisam. A ideia é simples: em vez de colocar uma chave de API dentro de um projeto ou entregar a chave para a IA, eu guardo tudo no 1Password e peço à IA para acessar aquela credencial somente no momento em que precisa usá-la.</p><p>O Henrique ficou interessado. Comentou que esse também era um problema para ele e gostou da solução. Então, me pediu para compartilhar em mais detalhes como estou usando IA, buscando outros insights como esse.</p><p>Quando comecei a organizar as ideias, percebi que o que eu construí nos últimos meses foi uma forma estruturada de usar IA. Eu não a uso mais apenas como uma aplicação que abro no computador quando preciso de ajuda. Ela virou uma camada operacional da minha vida e do meu trabalho.</p><p>Neste momento, por exemplo, estou falando com a IA pelo celular. Estou usando a minha voz para interagir com ela e elaborar este texto. Não estou com o notebook aberto, não digitei nada, não abri um terminal, não procurei arquivos e não fiz nada “manualmente”. Apenas expliquei o que queria.</p><p>Essa simplicidade só é possível porque, por trás dessa conversa, existe uma infraestrutura capaz de acessar meus projetos, consultar documentação, recuperar contexto e transformar o que estou dizendo em trabalho. Nos próximos parágrafos, vou te apresentar essa estrutura detalhadamente.</p><h3 id="moacirmoda-content-o-lugar-do-trabalho-migrou">O lugar do trabalho migrou</h3><p>Vamos começar pelo começo. A base do meu setup é um pequeno servidor que fica ligado na tomada 24/7, lá no meu escritório. Ele roda num Lenovo ThinkCentre usado, que paguei menos de mil reais na OLX. O batizei de Olimpo, e é nele que vive boa parte do meu ambiente de IA.</p><p>Meu notebook e meu celular funcionam como pontos de acesso. Posso começar uma tarefa no computador, fechar a tampa e continuar depois pelo celular. Os processos não dependem de uma janela aberta no meu Mac. Eles não rodam mais na minha máquina, mas sim num servidor, independentemente de onde eu estiver.</p><p>Essa liberdade é o que permite usar um celular como uma interface real de trabalho. O telefone não precisa guardar meus projetos, executar ferramentas ou ter grande capacidade de processamento. Ele precisa apenas me conectar a um ambiente que já possui tudo isso.</p><h3 id="moacirmoda-content-eu-praticamente-não-digito-mais">Eu praticamente não digito mais</h3><p>Eu ainda uso o notebook, claro. Prefiro mil vezes trabalhar por ele do que pelo celular. Sem contar que existem ainda algumas poucas atividades em que a IA precisa controlar aplicativos ou até mesmo o browser, e na minha máquina fica mais fácil.</p><p>Mas, confesso que a maior parte do meu trabalho hoje acontece pela voz. Enquanto caminho, estou no carro ou longe da mesa, posso explicar um problema, desenvolver uma ideia ou pedir uma análise. Falar permite transmitir muito mais contexto do que eu provavelmente escreveria num prompt.</p><p>O ponto mais importante é que eu não preciso ditar comandos. Eu não preciso dizer para a IA entrar em determinado diretório, abrir três arquivos, executar uma busca e consultar uma API. Posso falar no nível da minha intenção: “Quero entender como está a operação comercial”; “Procura aquela conversa que tive com uma pessoa”; “Transforma esta ideia num texto”; “Avalie esse problema levando em conta o que já decidimos”.</p><p>A IA traduz essa intenção em ações menores. Por isso, a voz não é apenas uma forma conveniente de escrever prompts. Ela funciona como uma linguagem operacional. Eu falo sobre o problema; o sistema lida com arquivos, comandos, bases de dados e serviços.</p><p>Isso também depende da qualidade dos modelos que uso. Hoje só trabalho usando modelos avançados da OpenAI, como o Sol (ainda quero testar o Astra).</p><h3 id="moacirmoda-content-o-codex-é-meu-motor-de-trabalho">O Codex é meu motor de trabalho</h3><p>Quando falo que uso o notebook ou o celular para trabalhar, a interface que aparece para mim é o aplicativo do ChatGPT. Tenho o aplicativo instalado nos dois dispositivos e, dentro deles, configurei uma conexão SSH. O motor de trabalho é o Codex.</p><p>Quando começo uma conversa, existe por trás dela uma instância do Codex operando dentro do servidor. É o Codex que acessa meus projetos, lê arquivos, executa comandos, chama outras ferramentas e realiza o trabalho que pedi. O aplicativo do ChatGPT é a interface que me leva até esse ambiente.</p><p>Dentro do Olimpo existe um ambiente que chamo de Devbox. Ele é minha estação remota de desenvolvimento e de trabalho com IA. É ali que ficam os agentes, as ferramentas de linha de comando e os projetos que uso com mais frequência. Uso o Tailscale como ferramenta de VPN para poder acessar esse ambiente sem expor o servidor diretamente na internet.</p><p>Em termos simples: o ChatGPT é a interface, o Codex é o agente, o Sol é o modelo, o Devbox é o ambiente de execução e o Olimpo é a máquina física onde tudo isso vive.<br>Cada capacidade tem seu próprio ambiente<br>O Olimpo não é um servidor com tudo instalado junto. Uso o Proxmox para separar as funções em containers. Existe um ambiente para desenvolvimento, outro para WhatsApp, outro para Discord, outro para monitoramento e outros para tarefas específicas.</p><p>Um container roda o WAHA, que conecta minhas contas de WhatsApp. Outro roda o Discord Manager, que guarda o histórico do servidor do Tintim e o disponibiliza para a IA. Há duas instâncias do Hermes, um agente pessoal que pode funcionar pelo Telegram. Uma é minha; a outra é da minha esposa, com ferramentas e permissões diferentes. Também existem containers para automações, monitoramento, mídia e downloads.</p><p>Essa separação me permite adicionar capacidades sem transformar o servidor inteiro. Quando surge uma necessidade, posso criar uma peça especializada e ensinar os agentes a usá-la.</p><p>Se um serviço falha, o restante não precisa parar. Se preciso atualizar uma ferramenta, consigo trabalhar naquele ambiente específico. E cada agente acessa apenas aquilo que faz sentido para sua função.</p><h3 id="moacirmoda-content-os-projetos-explicam-o-trabalho-a-ser-feito">Os projetos explicam o trabalho a ser feito</h3><p>Dar acesso a arquivos e ferramentas não é suficiente. Para trabalhar bem, a IA precisa entender o contexto de cada projeto. Precisa saber o que está sendo construído, quais decisões já foram tomadas, quais regras deve seguir e o que não pode fazer. Por isso, tenho um repositório GitHub para cada projeto.</p><p>No projeto onde controlo minhas finanças, por exemplo, existem regras de segurança, conciliação e revisão. No projeto em que gerencio meu canal do YouTube, existem critérios editoriais e processos para preparar vídeos. Num projeto de inteligência comercial que estou criando para o Tintim, existem perguntas, fontes, hipóteses e evidências. No próprio projeto do Olimpo está documentado como cada serviço foi instalado e como deve ser operado.</p><p>As skills globais entram como uma extensão disso. Elas estão disponíveis para todos os projetos e facilitam a interação deles com o mundo externo. Tenho skills para consultar o Notion, acessar o Google Workspace, buscar conversas no WhatsApp, ler o Discord, consultar bases de dados, transcrever áudios e trabalhar com vários outros serviços.</p><p>Elas também definem limites. Algumas ferramentas são deliberadamente somente leitura. A IA consegue consultar e analisar, mas a própria ferramenta não oferece operações para modificar os dados.</p><p>Essa organização reduz a quantidade de instruções que preciso dar em cada conversa. Em vez de explicar novamente como um processo funciona, eu mantenho esse conhecimento junto do sistema. Quando eu falo, o projeto e as skills completam o contexto que não foi dito.</p><h3 id="moacirmoda-content-a-memória-atravessa-as-conversas">A memória atravessa as conversas</h3><p>Ainda existe outro tipo de contexto que não pertence a um projeto específico. Quem sou eu? O que está acontecendo na empresa? Quais decisões tomei? Que tensões continuam abertas? Quando mencionei determinado assunto pela última vez?</p><p>Uso dois sistemas principais para isso. O Second Brain é meu vault no Obsidian. Nele guardo acontecimentos, ideias, pessoas, reuniões e materiais da minha vida e do meu trabalho. O Mirror Mind cuida da continuidade da relação com os agentes. Ele também mantém minha identidade, minhas jornadas, decisões, padrões e diferentes formas de olhar para um problema.</p><p>Os projetos explicam como o trabalho deve ser feito. O Second Brain guarda o que aconteceu. O Mirror ajuda a IA a entender de que trajetória aquela conversa faz parte.</p><p>Isso permite que eu fale de uma forma muito mais natural. Posso dizer “aquela conversa com o Henrique”, “o problema da semana passada” ou “continua a tese que estávamos construindo”. A IA sabe do que eu estou falando porque tem contexto.<br>Usar os sistemas sem entregar as chaves</p><p>Eu uso IA somente no modo YOLO. Não vejo sentido se não for pra ser assim. Mas, como diria Uncle Ben: “Com grandes poderes, vêm grandes responsabilidades”. Por isso, eu tenho um cuidado extra relacionado à segurança das senhas e chaves de que os agentes precisam para usar todos esses serviços.</p><p>Para consultar uma API, acessar uma base de dados ou operar um serviço, geralmente é necessário algum tipo de credencial. A solução mais simples seria colocar essas chaves em arquivos de configuração dentro dos projetos. Eu não faço isso.</p><p>O que faço é usar o 1Password como fonte de verdade para os segredos. A skill sabe qual credencial precisa, onde ela está e em qual variável deve ser injetada. Quando a ferramenta é executada, o 1Password fornece o segredo apenas para aquele processo. A IA não recebe o valor da credencial. A chave não precisa aparecer no prompt, no código, no histórico do terminal ou no repositório.</p><p>No Discord Manager, por exemplo, o token sai do 1Password, atravessa uma conexão SSH e é armazenado como uma credencial criptografada do systemd dentro do container. O valor não fica num <code>.env</code>.</p><h3 id="moacirmoda-content-processos-100-autônomos-e-confiáveis">Processos 100% autônomos e confiáveis</h3><p>A beleza de se ter um setup desse é que ele é 100% moldável pela própria IA. Isso significa poder ter diversos sistemas e rotinas rodando de forma autônoma, sem que eu precise interagir ativamente. O próprio setup, inclusive, foi criado quase que 100% pela IA.</p><p>No setup, eu tenho várias rotinas automatizadas. Há rotinas que sincronizam projetos, fazem backup, importam anotações de reuniões, atualizam meu Second Brain ou cuidam de tarefas no servidor.</p><p>Mas como saber se essas rotinas estão funcionando corretamente? Simples. Quando uma automação funciona normalmente, eu não preciso ficar sabendo de nada. Agora, quando falha, recebo uma mensagem pelo Telegram. Se um processo parar de enviar seu sinal periódico de saúde, o monitor detecta. Se um serviço cair, recebo um alerta. Se algo der errado, existem logs para investigar.</p><p>Uso o Uptime Kuma para monitorar serviços e receber heartbeats das automações. Os processos deixam logs, usam locks para evitar execuções sobrepostas e são executados por timers do systemd.</p><h3 id="moacirmoda-content-o-que-existe-por-trás-das-conversas">O que existe por trás das conversas</h3><p>Até aqui, expliquei os princípios por trás da arquitetura. Para tornar isso mais concreto, esta é uma fotografia do que existe hoje no meu setup. Não é uma recomendação para que todo mundo instale as mesmas coisas. É apenas o sistema que foi surgindo conforme minhas necessidades apareceram. Estou te mostrando para te alimentar de referências.</p><h3 id="moacirmoda-content-os-ambientes">Os ambientes</h3><p>Tecnicamente, a maior parte desses ambientes é composta por containers LXC, embora no dia a dia eu pense neles como pequenas máquinas separadas.</p><p>Olimpo: é o servidor físico. Roda Proxmox, compartilha os discos pela rede, fornece acesso remoto pelo Tailscale e hospeda todos os outros ambientes.</p><p>Devbox: é a minha estação remota de trabalho. É onde o Codex opera, onde estão os projetos e onde ficam instaladas as principais ferramentas usadas pelos agentes.</p><p>WAHA: conecta minhas contas pessoal e Business do WhatsApp, permitindo que os agentes consultem minhas conversas.</p><p>Discord Manager: mantém uma cópia local do histórico do Discord da Tintim e oferece ferramentas para pesquisar mensagens, acompanhar menções, criar bookmarks e responder conversas.</p><p>Automações: executa pequenas rotinas recorrentes, como backups e integrações entre os serviços.</p><p>Uptime Kuma: monitora a disponibilidade dos serviços e os sinais periódicos enviados pelas automações. Quando alguma coisa para de funcionar, ele dispara um alerta.</p><p>Jellyfin: organiza e reproduz minha biblioteca de filmes e séries. Também possui as ferramentas usadas para baixar e sincronizar legendas.</p><p>qBittorrent e Jackett: cuidam da busca e do download de filmes e séries, salvando os arquivos diretamente na biblioteca usada pelo Jellyfin.</p><h3 id="moacirmoda-content-as-skills-globais">As skills globais</h3><p>As skills ensinam o Codex a usar cada serviço. Elas descrevem qual ferramenta deve ser chamada, como a autenticação funciona, quais operações são permitidas e como o resultado deve ser interpretado.</p><p>1Password: localiza e injeta credenciais nos processos sem expor seus valores para a IA ou salvá-los nos projetos.</p><p>Apify: executa e administra Actors de coleta e processamento de dados na nuvem.<br>Asaas: consulta clientes, cobranças, assinaturas, pagamentos, saldo e outras informações financeiras. A skill é somente leitura.</p><p>Discord Manager: permite pesquisar o histórico do Discord da Tintim, acompanhar mensagens e menções, organizar bookmarks e enviar respostas.</p><p>Firecrawl: pesquisa e extrai informações da web. Dependendo da tarefa, pode buscar páginas, navegar por sites, interagir com interfaces, coletar dados estruturados ou produzir pesquisas mais extensas.</p><p>GitHub: permite trabalhar com repositórios, issues, pull requests, Actions e releases.<br>Google Workspace: acessa Drive, Docs, Sheets, Gmail, Calendar, Meet e outros serviços do Google.</p><p>Kommo: recupera e resume o histórico de conversas dos leads no CRM da Tintim. É somente leitura.</p><p>Make: consulta cenários, execuções, webhooks, conexões e outros recursos da nossa conta do Make.</p><p>Notion: pesquisa, lê e edita páginas e bases do Notion.<br>WhatsApp: pesquisa conversas, mensagens, contatos e grupos nas minhas contas pessoal e Business.</p><p>Além dessas, cada projeto pode ter suas próprias skills. O projeto do Olimpo, por exemplo, possui uma skill que coordena Jackett, qBittorrent, Jellyfin e as ferramentas de legenda parabaixar um filme ou episódio inteiro a partir de um pedido em linguagem natural.</p><h3 id="moacirmoda-content-os-projetos">Os projetos</h3><p>Os projetos guardam tanto o trabalho quanto o contexto necessário para realizá-lo. Estes são os principais repositórios que existem hoje na minha Devbox:</p><p>Olimpo: documenta e versiona a infraestrutura do meu servidor, seus serviços, instalações, automações e decisões operacionais.</p><p>Second Brain: é meu vault pessoal no Obsidian, onde guardo acontecimentos, reuniões, pessoas, ideias e materiais da minha vida e do meu trabalho.</p><p>Mirror Mind: é o sistema de memória e identidade que mantém continuidade entre minhas conversas, decisões e jornadas.</p><p>Canal do Moa: reúne os processos editoriais e as automações usadas para preparar vídeos, criar leads, selecionar recomendações e conectar o canal à newsletter.<br>Newsletter do Moa: contém as skills e os agentes usados no processo semanal de produção da newsletter.</p><p>Financeiro: é meu controle financeiro pessoal, construído sobre Beancount.<br>Inteligência Comercial: reúne fontes, evidências e investigações sobre a máquina comercial da Tintim, da aquisição do lead até a venda.</p><p>Product Management: é o segundo cérebro de produto da Tintim, com pesquisas, dados, decisões e conhecimento sobre clientes e produto.</p><p>Essa lista mostra que acessar meus projetos não significa apenas programar. A IA transita entre infraestrutura, finanças, produto, conteúdo, memória pessoal e operação da empresa.<br>A IA como camada operacional</p><p>O que mais me interessa nessa arquitetura não é o servidor, o Proxmox ou qualquer ferramenta isolada. É a relação que o conjunto permite.</p><p>Eu expresso uma intenção. A IA encontra o contexto, escolhe uma capacidade, acessa os sistemas necessários e realiza o trabalho. Dependendo da tarefa, ela pode ler arquivos, consultar uma base, procurar uma conversa, recuperar uma reunião ou modificar um projeto. Meu notebook e meu celular são formas diferentes de entrar nessa camada. Na maior parte do tempo, eu entro falando.</p><p>Isso não elimina o trabalho. Eu ainda preciso formular bem os problemas, revisar decisões e assumir responsabilidade pelo que é feito. A diferença é que não preciso operar pessoalmente cada etapa intermediária.</p><p>A mudança mais importante não foi instalar uma IA mais inteligente. Foi construir um ambiente no qual ela consegue trabalhar de forma contínua, contextualizada e segura.</p></div>]]></content:encoded>
            <author>moacirmoda</author>
        </item>
        <item>
            <title><![CDATA[win-mute: desliga IA, telemetria e bloatware do Windows 10/11]]></title>
            <link>https://www.tabnews.com.br/obrenoalvim/win-mute-desliga-ia-telemetria-e-bloatware-do-windows-10-11</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/obrenoalvim/win-mute-desliga-ia-telemetria-e-bloatware-do-windows-10-11</guid>
            <pubDate>Fri, 11 Sep 2026 18:50:09 GMT</pubDate>
            <description><![CDATA[Cansei do Windows vir cheio de coisa que eu nunca pedi: IA ligada sem eu querer, telemetria que nao da pra ver direito, bloatware que fico desinstalando toda vez que formato uma maquina....]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Cansei do Windows vir cheio de coisa que eu nunca pedi: IA ligada sem eu querer, telemetria que nao da pra ver direito, bloatware que fico desinstalando toda vez que formato uma maquina. Entao fiz um kit PowerShell que desliga tudo isso de uma vez, em Windows 10 e 11.</p><h2 id="obrenoalvim-content-o-que-faz">O que faz</h2><p>O win-mute tem 72 ajustes em 6 categorias:</p><ul><li><strong>AI</strong>: Copilot, Recall, Click To Do, Cortana, busca do Bing, IA generativa, Destaques de busca, Suggested Actions do clipboard</li><li><strong>Telemetry</strong>: nivel de dado de diagnostico, DiagTrack, ID de publicidade, historico de atividades, CEIP, relatorio de erro</li><li><strong>Services</strong>: Retail Demo, Maps broker, Fax, indexacao da busca, Remote Registry, servicos do Xbox</li><li><strong>ScheduledTasks</strong>: CEIP, Application Experience, prompt de feedback, telemetria do autochk</li><li><strong>Bloatware</strong>: 25 apps de fabrica (Xbox, Bing Weather/News, Solitaire, Skype, Teams consumer, etc)</li><li><strong>Privacy</strong>: anuncio no Iniciar/tela de bloqueio, secao "Recomendados", menu de clique direito classico, icone de Chat, Widgets, nag do OneDrive, instalacao automatica de app patrocinado, entre outros</li></ul><p>Cada ajuste e um objeto PowerShell simples com blocos Apply, Revert e Test, mexendo nos mesmos pontos que ferramenta fechada tipo essa mexe: chave de registro de Group Policy, tipo de inicializacao de servico, tarefa agendada, remocao de pacote Appx. Nada escondido, da pra abrir modules/*.ps1 e ler cada um antes de rodar.</p><h2 id="obrenoalvim-content-pesquisei-reclamacao-real-antes-de-escrever-o-codigo">Pesquisei reclamacao real antes de escrever o codigo</h2><p>Em vez de chutar quais ajustes importam, pesquisei o que usuario de Windows realmente reclama (Reddit, imprensa tech, 2025-2026), em duas rodadas:</p><ul><li><strong>Revolta contra Windows 11</strong>: menu de clique direito capado, anuncio no Menu Iniciar, feed "Recomendados" forcado, icone de Chat na taskbar, app patrocinado se instalando sozinho.</li><li><strong>Dor especifica do Windows 10</strong> (pos fim de suporte, out/2025): nag insistente de upgrade pro Windows 11 pra quem fica no 10 usando ESU, Bing sequestrando a busca da taskbar, icone de Pessoas que ninguem pediu, Edge recriando atalho na area de trabalho toda hora.</li></ul><h2 id="obrenoalvim-content-windows-10-ou-11-detectado-sozinho">Windows 10 ou 11, detectado sozinho</h2><p>Sem escolher versao na mao. O script confere o numero de build e os ajustes que so existem numa versao (Copilot, Recall, o menu de contexto classico, Widgets) somem sozinhos na outra. 64 dos 72 ajustes valem no Windows 10, 70 no Windows 11.</p><h2 id="obrenoalvim-content-cli-e-gui">CLI e GUI</h2><pre><code class="hljs language-powershell"># Lista interativa.\Invoke-WinMute.ps1# Sem prompt, uma ou mais categorias.\Invoke-WinMute.ps1 -Categories AI,Telemetry -All# So o que nao tem efeito colateral nenhum.\Invoke-WinMute.ps1 -All -SafeOnly# Reverte tudo.\Invoke-WinMute.ps1 -Undo</code></pre><p>Pra quem nao quer mexer com PowerShell, o START-GUI.bat abre uma janela WPF que se auto-eleva, mostra um botao grande "Aplicar agora" com os ajustes seguros recomendados, e deixa a lista completa escondida atras de "Personalizar". Troca entre portugues e ingles com um clique, sem reabrir a janela.</p><h2 id="obrenoalvim-content-a-pergunta-vou-perder-alguma-coisa">A pergunta "vou perder alguma coisa?"</h2><p>Reconferi os 72 ajustes pensando exatamente nisso. Nenhum toca em arquivo pessoal, so mexe em valor de registro, tipo de inicializacao de servico, estado de tarefa agendada, ou desinstala app da Store (remove so a config local daquele app, nunca Documentos ou foto). Achei um caso real na auditoria: forcar "apps em segundo plano" desligado pra todo mundo pode parar notificacao de app de mensagem/email, entao tirei esse do grupo "Seguro" e passei pra "Moderado" em vez de deixar no clique unico. Por padrao a ferramenta cria um ponto de restauracao do Windows antes de qualquer mudanca, como rede de seguranca extra.</p><p>Uma coisa que deixei de fora de proposito: atualizacao forcada e reinicio automatico do Windows. Desligar isso troca incomodo de interface por PC sem patch de seguranca, e essa troca nao vale a pena nem no -All.</p><p>Codigo aberto, licenca MIT, so PowerShell, sem dependencia externa. Repo: <a href="https://github.com/obrenoalvim/win-mute">https://github.com/obrenoalvim/win-mute</a></p><p>Qual "funcionalidade" do Windows voce desligaria primeiro se pudesse?</p><p>Ps.: Desenvolvo o <a href="http://www.bloodlink.com.br" rel="nofollow">BloodLink</a>, plataforma gratuita que conecta doadores de sangue a campanhas de doacao. Se quiser conhecer, vale a visita.</p></div>]]></content:encoded>
            <author>obrenoalvim</author>
        </item>
        <item>
            <title><![CDATA[Conectei um MCP local ao ChatGPT usando a conta Free]]></title>
            <link>https://www.tabnews.com.br/FranciscoOssian/conectei-um-mcp-local-ao-chatgpt-usando-a-conta-free</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/FranciscoOssian/conectei-um-mcp-local-ao-chatgpt-usando-a-conta-free</guid>
            <pubDate>Fri, 11 Sep 2026 18:36:11 GMT</pubDate>
            <description><![CDATA[Estava testando MCPs e queria conectar um servidor MCP rodando localmente ao ChatGPT, sem precisar expor o servidor diretamente à Internet. Acabei descobrindo o Secure MCP Tunnel da OpenA...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Estava testando MCPs e queria conectar um servidor MCP rodando localmente ao ChatGPT, sem precisar expor o servidor diretamente à Internet.</p><p>Acabei descobrindo o Secure MCP Tunnel da OpenAI.</p><p>A arquitetura ficou basicamente:</p><p>ChatGPT<br>↓<br>Secure MCP Tunnel<br>↓<br>tunnel-client<br>↓<br>MCP local</p><p>Para testar, usei um MCP de terceiros para o LinkedIn e consegui utilizar suas ferramentas pelo ChatGPT enquanto o MCP continuava rodando na minha máquina.</p><p>Achei interessante principalmente pela possibilidade de desenvolver e testar MCPs localmente sem precisar publicar um endpoint HTTP só para fazer a integração.</p><p>Documentei o processo, incluindo configuração, comandos e algumas considerações de segurança:</p><p><a href="https://www.foln.dev/blog/chatgpt-mcp-secure-tunnel" rel="nofollow">Como conectar um MCP local ao ChatGPT usando o Secure MCP Tunnel</a></p><blockquote><p>Aviso: o "mcp-server-linkedin" utilizado no exemplo é um projeto de terceiros. Não é desenvolvido nem verificado pela OpenAI ou pelo LinkedIn, e seu uso é de responsabilidade de quem o executa. O LinkedIn possui restrições quanto a scraping e automações, então vale entender bem o que você está executando antes de utilizá-lo.</p></blockquote></div>]]></content:encoded>
            <author>FranciscoOssian</author>
        </item>
        <item>
            <title><![CDATA[Uma linguagem de programação em italiano? Interpretada em PHP? Como assim?]]></title>
            <link>https://www.tabnews.com.br/AdaiasMagdiel/uma-linguagem-de-programacao-em-italiano-interpretada-em-php-como-assim</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/AdaiasMagdiel/uma-linguagem-de-programacao-em-italiano-interpretada-em-php-como-assim</guid>
            <pubDate>Fri, 11 Sep 2026 18:16:53 GMT</pubDate>
            <description><![CDATA[Olá, pessoas! Recentemente voltei a estudar design de linguagens de programação. Acho que é um conhecimento que vale a pena pra qualquer programador, independente da área: entender não só...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Olá, pessoas!</p><p>Recentemente voltei a estudar design de linguagens de programação. Acho que é um conhecimento que vale a pena pra qualquer programador, independente da área: entender não só por cima, mas também por baixo dos panos, como as linguagens funcionam, como são construídas e como rodam. Pode ser que você nunca chegue a usar esse conhecimento no dia a dia, mas isso não é motivo pra deixar de aprender.</p><h2 id="adaiasmagdiel-content-crafting-interpreters">Crafting Interpreters</h2><p>Se você quer começar a entender e construir suas próprias linguagens, recomendo demais o <a href="https://craftinginterpreters.com/contents.html" rel="nofollow">Crafting Interpreters</a>. É uma das portas de entrada mais didáticas que existem no assunto.</p><p>Confesso que a minha primeira linguagem não nasceu da leitura do livro, e sim depois de ver o Alexey Kutepov, o <a href="https://www.youtube.com/@TsodingDaily" rel="nofollow">Tsoding</a>, construindo uma <a href="https://www.youtube.com/playlist?list=PLpM-Dvs8t0VbMZA7wW9aR3EtBqe2kinu4" rel="nofollow">linguagem stack-based inspirada em Forth em Python</a>. Fui atrás e criei a <a href="https://github.com/AdaiasMagdiel/Beremiz">Beremiz</a>, uma stack-based feita em Lua, inspirada no Porth do próprio Tsoding.</p><h2 id="adaiasmagdiel-content-e-aí-entra-a-codice">E aí entra a Codice</h2><p>Dessa vez decidi construir uma linguagem com sintaxe "c-like". Chamei ela de <strong>Codice</strong>, "código" em italiano.</p><p>A ideia por trás do nome não é só estética: ao mesmo tempo que exercito conhecimento de construção de linguagens, aproveito pra estudar italiano, já que todas as palavras-chave, mensagens de erro e nomes de conceitos da linguagem são em italiano. E quem sabe também sirva de porta de entrada pra falantes do idioma que queiram aprender programação, do mesmo jeito que temos o Portugol, a Égua, o Delégua e o Birl para o português:</p><ul><li><a href="https://pt.wikipedia.org/wiki/Portugol" rel="nofollow">https://pt.wikipedia.org/wiki/Portugol</a></li><li><a href="https://egua.dev/" rel="nofollow">https://egua.dev/</a></li><li><a href="https://github.com/designLiquido/delegua">https://github.com/designLiquido/delegua</a></li><li><a href="https://birl-language.github.io/" rel="nofollow">https://birl-language.github.io/</a></li></ul><h2 id="adaiasmagdiel-content-por-que-php">Por que PHP?</h2><p>Porque a Codice não tem nenhuma ambição de ser uma linguagem útil ou com aplicação real, é uma toy language, feita por diversão e aprendizado. Muita gente que está começando na programação acha que precisa aprender ferramentas ou linguagens específicas pra "poder" construir certas coisas, quando na real você pode validar qualquer ideia na linguagem que você já conhece, do seu jeito.</p><p>Óbvio que uma linguagem interpretada em PHP nunca vai ter a performance de algo feito "do jeito certo", mas performance nunca foi o objetivo aqui. Depois de madura, nada impede a Codice de ser reescrita em outra linguagem, compilada para bytecode ou até rodando sobre a JVM (o que, aliás, pretendo fazer no futuro).</p><h2 id="adaiasmagdiel-content-um-gostinho-da-sintaxe">Um gostinho da sintaxe</h2><p>Hoje a Codice já tem lexer, parser e um interpretador tree-walking rodando de ponta a ponta, com tipos <code>stringa</code>, <code>booleano</code>, <code>nullo</code>, <code>intero</code> e <code>decimale</code>:</p><pre><code>stampa("Interi: ", 42, ", ", 1_000_000);stampa("Decimali: ", 3.14, ", ", .5, ", ", 1_234.567_89, ", ", 67.);stampa("Booleani: ", vero, ", ", falso);stampa("Nullo: ", nullo);</code></pre><p>Saída:</p><pre><code>Interi: 42, 1000000Decimali: 3.14, 0.5, 1234.56789, 67.0Booleani: vero, falsoNullo: nullo</code></pre><p>Ainda não tem variáveis, controle de fluxo nem funções definidas pelo usuário, ainda está bem no início. Mas o pipeline completo já funciona, incluindo um REPL simples.</p><h2 id="adaiasmagdiel-content-acompanhe-o-desenvolvimento">Acompanhe o desenvolvimento</h2><p>O código está no meu GitHub, aberto e público: <a href="https://github.com/AdaiasMagdiel/codice">https://github.com/AdaiasMagdiel/codice</a></p><p>É isso, galera. Até mais e obrigado pelos peixes!</p></div>]]></content:encoded>
            <author>AdaiasMagdiel</author>
        </item>
        <item>
            <title><![CDATA[Rebranding em 2026 sem deixar a plataforma com cara de artefato do Claude]]></title>
            <link>https://www.tabnews.com.br/leander/rebranding-em-2026-sem-deixar-a-plataforma-com-cara-de-artefato-do-claude</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/leander/rebranding-em-2026-sem-deixar-a-plataforma-com-cara-de-artefato-do-claude</guid>
            <pubDate>Fri, 11 Sep 2026 17:59:31 GMT</pubDate>
            <description><![CDATA[Trabalho com desenvolvimento há tempo suficiente para já ter visto quase todo tipo de rebranding. Já vi empresa trocar o logo e chamar isso de transformação digital. Já vi sistema ganhar...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Trabalho com desenvolvimento há tempo suficiente para já ter visto quase todo tipo de rebranding. Já vi empresa trocar o logo e chamar isso de transformação digital. Já vi sistema ganhar gradiente porque alguém descobriu o Figma. Já vi botão mudar de azul para roxo e ser apresentado como uma nova fase da marca.</p><p>Nada disso me preparou para fazer o rebranding de uma plataforma com inteligência artificial.</p><p>O problema agora é outro: <strong>não basta deixar a interface bonita. Ela precisa parecer que foi pensada por alguém.</strong></p><h2 id="leander-content-o-problema-do-design-genericamente-correto">O problema do design genericamente correto</h2><p>A IA não costuma produzir interfaces feias. Ela produz interfaces <strong>genericamente aceitáveis</strong>.</p><p>Cards brancos, sombra suave, ícones lineares, botão “Get started”. Tudo correto — e completamente esquecível.</p><p>O feio chama atenção. O genérico passa pela revisão e, meses depois, ninguém sabe por que o produto parece igual a todos os outros.</p><p>Consistência é importante, mas consistência demais também denuncia. Quando toda página usa o mesmo card, borda e botão, o design system começa a parecer uma fórmula.</p><h2 id="leander-content-rebranding-não-é-trocar-cores">Rebranding não é trocar cores</h2><p>Rebranding não é escolher uma paleta e renomear componentes.</p><p>É decidir <strong>o que o produto comunica sem precisar explicar</strong>.</p><p>É saber se um botão deve ser preto, verde ou vermelho. Se um card precisa de borda. Se uma tela precisa de ajuda textual ou apenas de mais espaço.</p><p>Essas decisões parecem pequenas até você aplicá-las numa plataforma que já existe.</p><p>Porque plataformas antigas têm história: CSS local, componentes duplicados, inputs com alturas diferentes, modais copiados e props usadas de maneiras que ninguém planejou.</p><p>A pergunta começa inocente:</p><blockquote><p>“Podemos deixar tudo mais consistente?”</p></blockquote><p>A resposta é “sim” — até alguém abrir o forro.</p><h2 id="leander-content-o-perigo-do-componente-universal">O perigo do componente universal</h2><p>Quando a IA encontra inconsistências, uma solução comum é criar um componente universal.</p><p>Ele recebe <code>variant</code>, <code>size</code>, <code>tone</code>, <code>mode</code>, <code>density</code>, <code>state</code>, <code>layout</code>, <code>loading</code>, <code>intent</code> e mais algumas props que serão documentadas depois.</p><p>Na teoria, resolve tudo. Na prática, nasce o <code>UniversalSurfaceActionField.vue</code> com 900 linhas.</p><p>O problema é abstrair antes de entender <strong>o que realmente é compartilhado</strong>. Nem tudo que aparece duas vezes é o mesmo componente.</p><h2 id="leander-content-minimalismo-não-é-vazio">Minimalismo não é vazio</h2><p>Minimalismo não é remover informação até o usuário precisar abrir o DevTools para entender o que aconteceu.</p><p>É redução consciente: tirar ruído sem tirar contexto.</p><p>Na nossa paleta, usamos neutros, preto suave e verde-lima ácido. O verde carrega identidade, o preto sustenta ações normais, o branco dá espaço e os cinzas separam informação sem cercar tudo de bordas.</p><p>Mas o accent não pode virar passe livre para pintar tudo.</p><p>Se botão, foco, badge, sucesso, link e ícone usam a mesma cor forte, ela deixa de indicar prioridade e vira decoração.</p><p><strong>Nem tudo precisa pedir atenção ao mesmo tempo.</strong></p><h2 id="leander-content-dar-nome-à-intenção">Dar nome à intenção</h2><p>Numa auditoria visual, é comum descobrir quatro tamanhos de input sem ninguém ter decidido que deveriam existir quatro tamanhos.</p><p>Um tem 36px porque cabe numa tabela, outro 40px porque parece confortável, outro 44px porque veio do componente certo e outro 48px porque alguém confundiu destaque com volume.</p><p>A solução é criar uma escala semântica:</p><ul><li><code>sm</code>: tabelas e contextos densos;</li><li><code>compact</code>: formulários menores;</li><li><code>md</code>: padrão da plataforma;</li><li><code>lg</code>: áreas de destaque.</li></ul><p>Não é sobre decorar pixels. É sobre <strong>dar nome à intenção</strong>.</p><p>Quando a regra existe, a IA ajuda. Quando não existe, ela só escolhe números que parecem razoáveis.</p><h2 id="leander-content-onde-a-ia-realmente-ajuda">Onde a IA realmente ajuda</h2><p>A IA é excelente para auditoria.</p><p>Pode encontrar componentes duplicados, props não utilizadas, strings hardcoded e estilos fora do padrão.</p><p>Mas alguém ainda precisa perguntar:</p><blockquote><p>Isso descreve o produto ou só descreve o código?</p></blockquote><p>Código organizado não garante produto coerente.</p><p>Um botão preto numa tela, verde em outra e vermelho numa terceira não derruba o sistema.</p><p>Mas, juntos, esses detalhes passam uma mensagem clara:</p><p><strong>ninguém está no controle.</strong></p><p>Rebranding é recuperar esse controle sem fingir que o passado não existe. É preservar o que funciona, substituir o que confunde e documentar o que não pode quebrar.</p><h2 id="leander-content-velocidade-não-é-direção">Velocidade não é direção</h2><p>A IA pode gerar cem opções antes do café. Isso não significa que alguma delas saiba para onde o produto está indo.</p><p>Direção continua sendo trabalho humano.</p><p>É escolher uma cor e sustentar a escolha. Remover uma borda e confiar no espaço. Rejeitar um card bonito porque ele não explica nada. Olhar para um layout tecnicamente perfeito e dizer:</p><blockquote><p>“Isso está com cara de template.”</p></blockquote><p>E saber explicar por quê.</p><p>No fim, o maior desafio é criar uma interface em que a IA esteja presente no produto, mas <strong>ausente da caligrafia visual</strong>.</p><p>Uma interface clara e coerente, com componentes que têm propósito e exceções que têm motivo.</p><p>Porque uma boa identidade não é a que impressiona no primeiro screenshot, mas a que continua fazendo sentido depois de centenas de telas.</p><p>No fim, rebranding é menos sobre parecer novo e mais sobre <strong>parar de parecer acidental</strong>.</p><p>Ve la se tem cara de artefato do Claude > <a href="https://vidnap.com" rel="nofollow">https://vidnap.com</a></p></div>]]></content:encoded>
            <author>leander</author>
        </item>
        <item>
            <title><![CDATA[Pitch: Weydub — por que detectar texto não basta para remover legendas]]></title>
            <link>https://www.tabnews.com.br/weydub/pitch-weydub-por-que-detectar-texto-nao-basta-para-remover-legendas</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/weydub/pitch-weydub-por-que-detectar-texto-nao-basta-para-remover-legendas</guid>
            <pubDate>Fri, 11 Sep 2026 16:41:56 GMT</pubDate>
            <description><![CDATA[Somos a equipe do Weydub, uma ferramenta de localização de vídeo. Este texto apresenta uma decisão técnica do fluxo documentado publicamente: separar a detecção de texto da decisão de rem...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Somos a equipe do Weydub, uma ferramenta de localização de vídeo. Este texto apresenta uma decisão técnica do fluxo documentado publicamente: separar a detecção de texto da decisão de remover pixels. A redação e a tradução tiveram assistência de IA. O código abaixo é um exemplo didático executado localmente; não é o código interno do produto nem um teste da qualidade de restauração.</p><h2 id="weydub-content-três-operações-que-não-são-equivalentes">Três operações que não são equivalentes</h2><p>Uma legenda pode existir como faixa separada no contêiner do vídeo ou estar gravada nos pixels. Excluir a faixa não remove os caracteres que já fazem parte da imagem. Nesse segundo caso, é necessário identificar a área e reconstruir seu conteúdo visual.</p><p>OCR responde a “que texto aparece nesta imagem?”. Ele não responde sozinho a “este texto deve desaparecer?”. Em uma aula gravada, por exemplo, a legenda da fala pode ocupar a parte inferior, enquanto uma fórmula no quadro deve permanecer. Uma seleção baseada apenas na existência de texto pode destruir informação útil.</p><p>A geração de legendas também é outra tarefa. OCR extrai texto visível; ASR reconhece a fala. Na documentação do Weydub são modos separados, não uma fusão automática. A tradução e a dublagem vêm com decisões adicionais: identidade dos personagens, continuidade da voz e duração das falas.</p><h2 id="weydub-content-da-caixa-detectada-para-uma-decisão-com-limites">Da caixa detectada para uma decisão com limites</h2><p>Uma forma de reduzir ambiguidade na integração é representar explicitamente a região e o intervalo de tempo. Isso não garante que a escolha esteja correta; torna a escolha inspecionável antes de executar uma operação sobre o vídeo.</p><p>Neste exemplo usamos um vídeo hipotético de 640 × 360 pixels e 12 segundos. A caixa vai de (64, 270) a (576, 342), mas a intervenção vale apenas entre os segundos 3 e 8. As coordenadas normalizadas são [[0.1, 0.75], [0.9, 0.75], [0.9, 0.95], [0.1, 0.95]].</p><p>Salve o exemplo como mask-example.mjs e execute com Node.js:</p><pre><code class="hljs language-js"><span class="hljs-keyword">import</span> assert <span class="hljs-keyword">from</span> <span class="hljs-string">'node:assert/strict'</span>;<span class="hljs-keyword">function</span> <span class="hljs-title function_">makeMask</span>(<span class="hljs-params">{ width, height, box, start, end, duration }</span>) {  <span class="hljs-keyword">const</span> values = [width, height, ...box, start, end, duration];  <span class="hljs-keyword">if</span> (!values.<span class="hljs-title function_">every</span>(<span class="hljs-title class_">Number</span>.<span class="hljs-property">isFinite</span>)) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(<span class="hljs-string">'Non-finite value'</span>);  <span class="hljs-keyword">const</span> [x0, y0, x1, y1] = box;  <span class="hljs-keyword">if</span> (width &#x3C;= <span class="hljs-number">0</span> || height &#x3C;= <span class="hljs-number">0</span> || x0 &#x3C; <span class="hljs-number">0</span> || y0 &#x3C; <span class="hljs-number">0</span> ||      x1 > width || y1 > height || x0 >= x1 || y0 >= y1 ||      start &#x3C; <span class="hljs-number">0</span> || end &#x3C;= start || end > duration) {    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>(<span class="hljs-string">'Invalid region or time interval'</span>);  }  <span class="hljs-keyword">return</span> {    <span class="hljs-attr">type</span>: <span class="hljs-string">'remove_only_ocr'</span>, start, end,    <span class="hljs-attr">region</span>: [[x0 / width, y0 / height], [x1 / width, y0 / height],      [x1 / width, y1 / height], [x0 / width, y1 / height]],  };}<span class="hljs-keyword">const</span> input = { <span class="hljs-attr">width</span>: <span class="hljs-number">640</span>, <span class="hljs-attr">height</span>: <span class="hljs-number">360</span>, <span class="hljs-attr">box</span>: [<span class="hljs-number">64</span>, <span class="hljs-number">270</span>, <span class="hljs-number">576</span>, <span class="hljs-number">342</span>], <span class="hljs-attr">start</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">end</span>: <span class="hljs-number">8</span>, <span class="hljs-attr">duration</span>: <span class="hljs-number">12</span> };<span class="hljs-keyword">const</span> mask = <span class="hljs-title function_">makeMask</span>(input);assert.<span class="hljs-title function_">deepEqual</span>(mask.<span class="hljs-property">region</span>, [[<span class="hljs-number">0.1</span>, <span class="hljs-number">0.75</span>], [<span class="hljs-number">0.9</span>, <span class="hljs-number">0.75</span>], [<span class="hljs-number">0.9</span>, <span class="hljs-number">0.95</span>], [<span class="hljs-number">0.1</span>, <span class="hljs-number">0.95</span>]]);<span class="hljs-keyword">const</span> payload = { <span class="hljs-attr">needChineseOcclude</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">videoInpaintMasks</span>: <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>([mask]) };assert.<span class="hljs-title function_">deepEqual</span>(<span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">parse</span>(payload.<span class="hljs-property">videoInpaintMasks</span>), [mask]);assert.<span class="hljs-title function_">throws</span>(<span class="hljs-function">() =></span> <span class="hljs-title function_">makeMask</span>({ ...input, <span class="hljs-attr">width</span>: <span class="hljs-number">0</span> }));assert.<span class="hljs-title function_">throws</span>(<span class="hljs-function">() =></span> <span class="hljs-title function_">makeMask</span>({ ...input, <span class="hljs-attr">box</span>: [<span class="hljs-number">576</span>, <span class="hljs-number">270</span>, <span class="hljs-number">64</span>, <span class="hljs-number">342</span>] }));assert.<span class="hljs-title function_">throws</span>(<span class="hljs-function">() =></span> <span class="hljs-title function_">makeMask</span>({ ...input, <span class="hljs-attr">end</span>: <span class="hljs-number">13</span> }));assert.<span class="hljs-title function_">throws</span>(<span class="hljs-function">() =></span> <span class="hljs-title function_">makeMask</span>({ ...input, <span class="hljs-attr">start</span>: <span class="hljs-title class_">NaN</span> }));<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'PASS: coordinates; JSON round-trip; zero width; reversed box; time overflow; non-finite input'</span>);<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(payload, <span class="hljs-literal">null</span>, <span class="hljs-number">2</span>));</code></pre><p>A execução local passou pelas seis verificações acima. O campo videoInpaintMasks é serializado como string JSON conforme o contrato documentado, não enviado como um array diretamente. Os nomes dos campos foram mantidos como aparecem na API; o nome needChineseOcclude não deve ser interpretado como uma avaliação de qualidade por idioma.</p><h2 id="weydub-content-o-que-esse-teste-não-prova">O que esse teste não prova</h2><p>Ele valida uma transformação de dados, não a detecção OCR nem o preenchimento da imagem. O exemplo assume uma caixa retangular de quatro números. Para entrada externa, ainda é necessário validar o formato do array, o esquema completo da requisição, a origem das coordenadas e a orientação do vídeo. Uma caixa obtida de um preview recortado não pode ser normalizada usando as dimensões do original sem desfazer o recorte.</p><p>O tempo também precisa usar a mesma referência do vídeo processado. Se um trecho foi extraído de um arquivo maior, um intervalo absoluto do original pode apontar para a cena errada no trecho. Aqui usamos segundos relativos ao vídeo hipotético de 12 segundos.</p><h2 id="weydub-content-a-revisão-continua-sendo-parte-do-fluxo">A revisão continua sendo parte do fluxo</h2><p>Uma imagem isolada pode parecer boa e ainda apresentar cintilação durante a reprodução. Por isso, convém revisar movimento, cortes, rostos, mãos e contornos de produtos perto da região escolhida. Texto de cenário, avisos e fórmulas merecem uma decisão explícita de preservação. O resultado de uma ferramenta de preenchimento é uma reconstrução, não uma recuperação garantida dos pixels originais que estavam ocultos.</p><p>Para produzir uma nova versão em outro idioma, preserve separadamente o texto extraído e seus tempos. Revise a segmentação das legendas antes de traduzir. Na dublagem, confira a continuidade do personagem e a duração da fala em sequência, não apenas frase por frase.</p><h2 id="weydub-content-fontes-e-limites-da-apresentação">Fontes e limites da apresentação</h2><ul><li><a href="https://weydub.com/technology/video-subtitle-removal-ocr-inpainting/" rel="nofollow">Explicação pública sobre OCR e remoção de legendas</a></li><li><a href="https://weydub.com/docs/api/video-subtitle-removal.html" rel="nofollow">Contrato da API de remoção</a></li><li><a href="https://weydub.com/technology/ai-subtitle-generation-video-ocr-asr/" rel="nofollow">Modos de geração por OCR e ASR</a></li><li><a href="https://weydub.com/technology/ai-dubbing-audiovisual-reconstruction/" rel="nofollow">Tradução e reconstrução audiovisual</a></li></ul><p>Essas fontes são da própria equipe, não avaliações independentes. Elas explicam controles e problemas do fluxo; não divulgam toda a orquestração interna dos modelos. O exemplo não faz chamada paga nem envia vídeo. O <a href="https://br.weydub.com/" rel="nofollow">Weydub em português</a> é um serviço comercial com créditos; não estamos anunciando um plano gratuito nem apresentando números de precisão sem um experimento correspondente.</p><p>A contribuição que queremos deixar é esta: uma região reconhecida, uma política de edição e uma legenda temporizada são objetos diferentes. Mantê-los separados facilita testar a integração e revisar o que realmente será alterado.</p></div>]]></content:encoded>
            <author>weydub</author>
        </item>
        <item>
            <title><![CDATA[3 Dicas para sobreviver aos layoffs na área de tecnologia]]></title>
            <link>https://www.tabnews.com.br/ArthurBorba/3-dicas-para-sobreviver-aos-layoffs-na-area-de-tecnologia</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/ArthurBorba/3-dicas-para-sobreviver-aos-layoffs-na-area-de-tecnologia</guid>
            <pubDate>Fri, 11 Sep 2026 15:14:49 GMT</pubDate>
            <description><![CDATA[E ai galera! Há alguns anos tive o infortúnio de ser mandado embora por uma onda de layoff. Levei 6 meses para me recolocar, foi dolorido. Agora em 2026, a empresa que trabalho realizou c...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>E ai galera!</p><p>Há alguns anos tive o infortúnio de ser mandado embora por uma onda de layoff. Levei 6 meses para me recolocar, foi dolorido. Agora em 2026, a empresa que trabalho realizou cortes em massa também - desta vez permaneci no meu cargo, porém foi difícil ver colegas sendo afetados.</p><p>Tendo em vista essas experiências, pensei em trazer pra vocês 3 dicas práticas que me ajudaram a manter meu cargo nesse último corte massivo de gastos, que ajudam não só a manter a posição, mas também a evoluir dentro da empresa.</p><p>Antes das dicas de fato, também quero compartilhas sinais de que a sua empresa pode realizar um corte de gastos em breve:</p><h2 id="arthurborba-content-alertas-de-layoff-">Alertas de layoff 🚩</h2><p><strong>A) Compra ou fusão:</strong> esse é o maior alerta para cortes de gastos dentro de uma empresa. Uma empresa que foi comprada ou se fundiu com outra, com certeza vai realizar corte de gastos: reaproveitar recursos, seja espaço, ferramentas ou humanos, é uma das principais vantagens que leva as empresas a esses movimentos, reduzindo os custos operacionais</p><p><strong>B) Pivô de produto:</strong> o descontinuamento de um produto parece óbvio como causa para um potencial layoff, mas as vezes mesmo uma mudança de abordagem ou paradigma para algum produto da empresa pode gerar esse efeito: passei por uma empresa que migrou sua solução de plataforma, indo de um software Desktop para um sistema web. Novos (poucos) programadores foram contratados para criar o sistema web, porém a área de implantação e suporte foi severamente reduzida com essa mudança</p><p><strong>C) Tecnologias disruptivas:</strong> aqui como fator externo vem as mudanças tecnológicas do mercado. Atualmente estamos vivendo isso com a introdução da IA em nosso contexto de trabalho, mas a real é que isso é uma constante: profissionais de tecnologia estão na fronteira de inovação! Posso reforçar esse alerta com o exemplo das infraestruturas em "cloud", que removeu a necessidade de muitas empresas possuírem suas próprias estruturas de hospedagem com seus respectivos profissionais encarregados</p><h2 id="arthurborba-content-e-então-o-que-fazer-">E então o que fazer? 🟢</h2><p>O cerne das 3 dicas que vou compartilhar vem daquela famosa frase: "<em>é melhor prevenir do que remediar</em>"</p><h3 id="arthurborba-content-1-foco-em-resultado">1. Foco em resultado</h3><p>O principal é entender que quando você custa <em>X</em> para uma empresa, você deve gerar valor de <em>X + Y%</em> em retorno financeiro. Seu trabalho deve impactar positivamente os balanços contábeis da empresa.</p><p>Comece por entender como sua posição gera esse valor:</p><ul><li>São entregas pontuais, dentro do prazo estabelecido?</li><li>São entregas altamente escaláveis?</li><li>São entregas legalmente seguras?</li></ul><p>Nem sempre o que você aprendeu na teoria vai ser o mais importante para o contexto atual. A arquitetura perfeito, o código 100% limpo, em troca de uma semana de atraso ou que não resolve o problema de fato....pode custar muito.</p><p>Quando você descobrir isso, souber que está gerando o <em>X + Y%</em> de retorno, pode ter certeza que dificilmente será mandado embora. <strong>E quanto maior o <em>Y%</em> for, maior moral você tem para argumentar um aumento!</strong></p><h3 id="arthurborba-content-2-documente-suas-conquistas">2. Documente suas conquistas</h3><p>Essa dica é muito valiosa, e você com certeza já deve ter ouvido de outra pessoa ou ainda vai ouvir bastante. Isso por que é real! Um dos maiores divisores de água que tive em minha carreira foi saber documentar minhas conquistas.</p><p>Seja em um documento no seu drive, seja no seu portfólio, no seu currículo...no local que for mais apropriado, escreva os impactos de seus esforços, sempre medidos com números objetivos:</p><p>✅ Reduzi o tempo de carregamento da página em 90%<br>❌ Melhorei o tempo de carregamento da página</p><p>A visualização objetiva dos impactos do seu trabalho pelos seus gestores e liderança direta é muito mais eficaz do que uma percepção subjetiva de que você está fazendo um bom trabalho</p><h3 id="arthurborba-content-3-assuma-mais-responsabilidade">3. Assuma mais responsabilidade</h3><p>Seja "dono" de partes do projeto. Isso não quer dizer monopolizar conhecimento sobre aquilo, mas pelo contrário, difundir o que você sabe, se tornando a referência técnica no assunto. Seja quem as pessoas procuram quando necessitam de ajuda ou direcionamento sobre aquela parte da empresa. Isso vai te colocar em uma posição essencial, raramente considerada como dispensável.</p><p>Sugiro ter conversas com seus gestor, solicite direcionamento no que você pode melhorar, e se coloque a disposição para assumir novas oportunidades de crescimento. Essa também é uma boa oportunidade de mostrar os itens que você documentou na dica anterior 😄</p><p>E ai, o que achou?<br>Pra galera que já passou por isso, teriam mais alertas ou dicas para adicionar?</p></div>]]></content:encoded>
            <author>ArthurBorba</author>
        </item>
        <item>
            <title><![CDATA[Dicas para construir um sistema que traduz métricas de marketing em linguagem de cliente]]></title>
            <link>https://www.tabnews.com.br/dV1costt/dicas-para-construir-um-sistema-que-traduz-metricas-de-marketing-em-linguagem-de-cliente</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/dV1costt/dicas-para-construir-um-sistema-que-traduz-metricas-de-marketing-em-linguagem-de-cliente</guid>
            <pubDate>Fri, 11 Sep 2026 15:11:50 GMT</pubDate>
            <description><![CDATA[Fala, pessoal! Estou construindo um sistema e queria umas dicas de quem já mexeu com algo parecido. A ideia é simples: o usuário descreve os resultados de uma campanha em texto (tipo "Gas...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Fala, pessoal!</p><p>Estou construindo um sistema e queria umas dicas de quem já mexeu com algo parecido.</p><p>A ideia é simples: o usuário descreve os resultados de uma campanha em texto (tipo "Gastei R$ 3.000, tive 34 vendas de R$ 450, e 210 pessoas interessadas") e a IA devolve um diagnóstico do que tá funcionando, do que não tá, e do que fazer em seguida. Tudo em linguagem de cliente, sem siglas tipo ROAS, CTR ou CAC.</p><p>A arquitetura que pensei:</p><ul><li>Frontend no Lovable</li><li>Backend no Supabase com RLS e multi-tenant</li><li>Motor de IA com três camadas: Analytics AI (insights), Opportunity Engine (recomendações) e Motor de Regras (automação)</li></ul><p>O que já tenho funcionando:</p><ul><li>Área do cliente com Nova Análise, Visão Geral e Relatórios</li><li>IA já gera insights com base nos dados inseridos</li><li>Multi-tenant configurado</li></ul><p>O que ainda estou desenvolvendo:</p><ul><li>Motor de Regras (SE/ENTÃO)</li><li>Botão para aplicar recomendações direto na campanha</li><li>Feedback Loop para a IA aprender com acertos e erros</li></ul><p>Minhas dúvidas:</p><ol><li>Alguém já usou IA para traduzir métricas técnicas em linguagem de cliente? Como vocês fizeram?</li><li>Para o Motor de Regras, vocês recomendam guardar as regras no banco ou em código?</li><li>Alguma dica para implementar o Feedback Loop de forma eficiente?</li></ol><p>Qualquer ajuda é bem-vinda. Valeu! 🚀</p></div>]]></content:encoded>
            <author>dV1costt</author>
        </item>
        <item>
            <title><![CDATA[Conceito do Roda do Jeremy Evans no PHP]]></title>
            <link>https://www.tabnews.com.br/vinialencar/conceito-do-roda-do-jeremy-evans-no-php</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/vinialencar/conceito-do-roda-do-jeremy-evans-no-php</guid>
            <pubDate>Fri, 11 Sep 2026 15:04:32 GMT</pubDate>
            <description><![CDATA[Dei uma viajada na maionese e tentei trazer o conceito de Roda do Jeremy Evans para PHP, meus testes em Roda foram fenomenains e a curva de aprendizagem é bem baixa. Não vou me alongar em...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Dei uma viajada na maionese e tentei trazer o conceito de <a href="https://roda.jeremyevans.net/" rel="nofollow">Roda do Jeremy Evans</a> para PHP, meus testes em Roda foram fenomenains e a curva de aprendizagem é bem baixa. Não vou me alongar em conceitos e como o Roda funciona, isos fica de lição de casa kkkk, mas usei o Grok para tentar fazer algo usável no mesmo conceito em PHP, a ideia era uma POC, testar rápido para concluir rápido, e achei bem promissor.</p><p>Chamei de Stem(tronco), a ideia não era travar no nome, só testar, então não ligue pra isso kkkkk</p><p>Link da documentação: <a href="https://alencarfreire.github.io/stem/pt/" rel="nofollow">StemPHP</a></p></div>]]></content:encoded>
            <author>vinialencar</author>
        </item>
        <item>
            <title><![CDATA[Jensen Huang, CEO da Nvidia, afirma que a empresa deve crescer 70% no próximo ano]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/jensen-huang-ceo-da-nvidia-afirma-que-a-empresa-deve-crescer-70-por-cento-no-proximo-ano</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/jensen-huang-ceo-da-nvidia-afirma-que-a-empresa-deve-crescer-70-por-cento-no-proximo-ano</guid>
            <pubDate>Fri, 11 Sep 2026 14:53:50 GMT</pubDate>
            <description><![CDATA[A projeção elevaria o faturamento anual para cerca de 680 bilhões de dólares, ante uma estimativa de 400 bilhões para o atual ano fiscal. Huang destaca que a tecnologia da Nvidia é uma “p...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>A projeção elevaria o faturamento anual para cerca de 680 bilhões de dólares, ante uma estimativa de 400 bilhões para o atual ano fiscal. Huang destaca que a tecnologia da Nvidia é uma “plataforma fundamental” para a indústria de IA e está presente na maioria dos modelos desenvolvidos atualmente, incluindo os de grandes empresas como Anthropic, OpenAI e Google.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[Menino do Reino Unido desenvolve “síndrome da pele tostada” após usar notebook apoiado no abdômen por até 8 horas por dia]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/menino-do-reino-unido-desenvolve-sindrome-da-pele-tostada-apos-usar-notebook-apoiado-no-abdomen-por-ate-8-horas-por-dia</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/menino-do-reino-unido-desenvolve-sindrome-da-pele-tostada-apos-usar-notebook-apoiado-no-abdomen-por-ate-8-horas-por-dia</guid>
            <pubDate>Fri, 11 Sep 2026 14:48:50 GMT</pubDate>
            <description><![CDATA[A condição é causada pela exposição repetida e prolongada a calor de baixa intensidade, provocando uma erupção com aparência semelhante a uma renda. Geralmente, é benigna e reversível qua...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>A condição é causada pela exposição repetida e prolongada a calor de baixa intensidade, provocando uma erupção com aparência semelhante a uma renda. Geralmente, é benigna e reversível quando a fonte de calor é removida. O garoto, que conseguiu reverter o quadro após meses de cuidado, faz ensino domiciliar e utiliza o aparelho para estudar.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[Serviços públicos ao redor do mundo enfrentam aumento expressivo nas solicitações de cidadãos devido ao uso de IA]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/servicos-publicos-ao-redor-do-mundo-enfrentam-aumento-expressivo-nas-solicitacoes-de-cidadaos-devido-ao-uso-de-ia</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/servicos-publicos-ao-redor-do-mundo-enfrentam-aumento-expressivo-nas-solicitacoes-de-cidadaos-devido-ao-uso-de-ia</guid>
            <pubDate>Fri, 11 Sep 2026 14:43:49 GMT</pubDate>
            <description><![CDATA[No Reino Unido, reclamações ao ouvidor de habitação passaram de 2.600 em 2022 para mais de 7.000 em 2025, alta de aproximadamente 169%. O auxílio-doença do INSS do Brasil aparece no estud...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>No Reino Unido, reclamações ao ouvidor de habitação passaram de 2.600 em 2022 para mais de 7.000 em 2025, alta de aproximadamente 169%. O auxílio-doença do INSS do Brasil aparece no estudo, mas os números não foram divulgados. Segundo o pesquisador Chris Schmitz, que analisou 84 casos em 11 jurisdições diferentes, a IA reduziu a necessidade de reunir contexto, entender processos complexos e redigir textos precisos ao registrar solicitações.</p><p>Fontes:</p><ul><li><a href="https://techcrunch.com/2026/09/10/ai-agents-are-flooding-public-services-with-new-requests/" rel="nofollow">https://techcrunch.com/2026/09/10/ai-agents-are-flooding-public-services-with-new-requests/</a></li><li><a href="https://arxiv.org/html/2608.16603#1" rel="nofollow">https://arxiv.org/html/2608.16603#1</a></li></ul></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[Microsoft classifica Rust como linguagem de Nível 1 para desenvolvimento interno]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/microsoft-classifica-rust-como-linguagem-de-nivel-1-para-desenvolvimento-interno</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/microsoft-classifica-rust-como-linguagem-de-nivel-1-para-desenvolvimento-interno</guid>
            <pubDate>Fri, 11 Sep 2026 14:38:49 GMT</pubDate>
            <description><![CDATA[A decisão coloca a tecnologia no mesmo patamar de C++, C# e TypeScript e permite que desenvolvedores da empresa optem oficialmente pela linguagem em seus projetos. Segundo Mark Russinovic...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>A decisão coloca a tecnologia no mesmo patamar de C++, C# e TypeScript e permite que desenvolvedores da empresa optem oficialmente pela linguagem em seus projetos. Segundo Mark Russinovich, CTO do Azure, um dos principais fatores para a mudança é a segurança de memória, responsável por cerca de 70% das vulnerabilidades do Windows.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[Android passa a permitir transferência de senhas e passkeys entre diferentes gerenciadores de credenciais]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/android-passa-a-permitir-transferencia-de-senhas-e-passkeys-entre-diferentes-gerenciadores-de-credenciais</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/android-passa-a-permitir-transferencia-de-senhas-e-passkeys-entre-diferentes-gerenciadores-de-credenciais</guid>
            <pubDate>Fri, 11 Sep 2026 14:33:48 GMT</pubDate>
            <description><![CDATA[Dentro do aplicativo, o usuário poderá escolher a opção de importar credenciais de outro provedor; o Android detectará automaticamente os gerenciadores instalados no aparelho e permitirá...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Dentro do aplicativo, o usuário poderá escolher a opção de importar credenciais de outro provedor; o Android detectará automaticamente os gerenciadores instalados no aparelho e permitirá selecionar quais itens deseja importar. Inicialmente, a novidade está disponível nos aplicativos Google Password Manager, 1Password, Bitwarden e Dashlane.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[OpenAI suspende novas assinaturas do ChatGPT Pro 20x de 200 dólares mensais devido à demanda “sem precedentes” pelo modelo Astra]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/openai-suspende-novas-assinaturas-do-chatgpt-pro-20x-de-200-dolares-mensais-devido-a-demanda-sem-precedentes-pelo-modelo-astra</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/openai-suspende-novas-assinaturas-do-chatgpt-pro-20x-de-200-dolares-mensais-devido-a-demanda-sem-precedentes-pelo-modelo-astra</guid>
            <pubDate>Fri, 11 Sep 2026 14:10:05 GMT</pubDate>
            <description><![CDATA[A empresa não informou por quanto tempo as inscrições ficarão suspensas nem quantas pessoas estão se cadastrando diariamente, o que daria uma dimensão da escala da demanda. O plano Pro 5x...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>A empresa não informou por quanto tempo as inscrições ficarão suspensas nem quantas pessoas estão se cadastrando diariamente, o que daria uma dimensão da escala da demanda. O plano Pro 5x, de 100 dólares mensais, permanece disponível.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[Gartner prevê que, até 2029, 33% dos funcionários demitidos por causa de IA precisarão ser recontratados a custos mais altos]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/gartner-preve-que-ate-2029-33-por-cento-dos-funcionarios-demitidos-por-causa-de-ia-precisarao-ser-recontratados-a-custos-mais-altos</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/gartner-preve-que-ate-2029-33-por-cento-dos-funcionarios-demitidos-por-causa-de-ia-precisarao-ser-recontratados-a-custos-mais-altos</guid>
            <pubDate>Fri, 11 Sep 2026 14:05:04 GMT</pubDate>
            <description><![CDATA[Segundo a consultoria, com a força de trabalho global estagnada ou em declínio, a disputa por profissionais qualificados deve elevar gastos com recrutamento e treinamento. A Gartner també...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Segundo a consultoria, com a força de trabalho global estagnada ou em declínio, a disputa por profissionais qualificados deve elevar gastos com recrutamento e treinamento. A Gartner também projeta que, até 2027, 75% das empresas que priorizarem a substituição de funcionários pela IA serão superadas por concorrentes que usaram a tecnologia para modernizar e ampliar a capacidade do seu pessoal.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[GitLab alerta para duas vulnerabilidades graves e recomenda atualização imediata]]></title>
            <link>https://www.tabnews.com.br/NewsletterOficial/gitlab-alerta-para-duas-vulnerabilidades-graves-e-recomenda-atualizacao-imediata</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/NewsletterOficial/gitlab-alerta-para-duas-vulnerabilidades-graves-e-recomenda-atualizacao-imediata</guid>
            <pubDate>Fri, 11 Sep 2026 14:00:04 GMT</pubDate>
            <description><![CDATA[A CVE-2026-85706 permite que invasores não autenticados leiam arquivos arbitrários em servidores vulneráveis, enquanto a CVE-2026-87719 possibilita que invasores autenticados com acesso a...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>A CVE-2026-85706 permite que invasores não autenticados leiam arquivos arbitrários em servidores vulneráveis, enquanto a CVE-2026-87719 possibilita que invasores autenticados com acesso ao Duo Chat roubem credenciais sensíveis e configurações de instâncias do Advanced Search. As correções foram lançadas nas versões 19.3.2, 19.2.6 e 19.1 para Community e Enterprise.</p></div>]]></content:encoded>
            <author>NewsletterOficial</author>
        </item>
        <item>
            <title><![CDATA[Bem escrevi uma resenha matemática e talvez se quiserem ver clique no link, vou deixa até 19/09/26, espero que gostem]]></title>
            <link>https://www.tabnews.com.br/Alguem/bem-escrevi-uma-resenha-matematica-e-talvez-se-quiserem-ver-clique-no-link-vou-deixa-ate-19-09-26-espero-que-gostem</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/Alguem/bem-escrevi-uma-resenha-matematica-e-talvez-se-quiserem-ver-clique-no-link-vou-deixa-ate-19-09-26-espero-que-gostem</guid>
            <pubDate>Fri, 11 Sep 2026 13:32:06 GMT</pubDate>
            <description><![CDATA[Aqui vai esta à Resenha Matematica]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p><a href="https://gofile.io/d/LiIPFBhn" rel="nofollow">Aqui vai esta à Resenha Matematica</a></p></div>]]></content:encoded>
            <author>Alguem</author>
        </item>
        <item>
            <title><![CDATA[Aprenda Trapping Rain Water, Top K Frequent e Selection Sort com visualização passo a passo no DSA View View 👀👀]]></title>
            <link>https://www.tabnews.com.br/nyaomaru/aprenda-trapping-rain-water-top-k-frequent-e-selection-sort-com-visualizacao-passo-a-passo-no-dsa-view-view</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/nyaomaru/aprenda-trapping-rain-water-top-k-frequent-e-selection-sort-com-visualizacao-passo-a-passo-no-dsa-view-view</guid>
            <pubDate>Fri, 11 Sep 2026 12:51:13 GMT</pubDate>
            <description><![CDATA[Oi oi! Eu sou @nyaomaru, engenheiro frontend que ultimamente ficou completamente obcecado por ramen. 😸🍜 Você já usou o DSA View View? 👀👀 https://dev.to/nyaomaru/i-built-a-tool-to-visualiz...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Oi oi!</p><p>Eu sou <a href="https://github.com/nyaomaru">@nyaomaru</a>, engenheiro frontend que ultimamente ficou completamente obcecado por ramen. 😸🍜</p><p>Você já usou o <strong>DSA View View</strong>? 👀👀</p><p><a href="https://dev.to/nyaomaru/i-built-a-tool-to-visualize-dsa-lets-learn-together-dsa-view-view--djo" rel="nofollow">https://dev.to/nyaomaru/i-built-a-tool-to-visualize-dsa-lets-learn-together-dsa-view-view--djo</a></p><p>O DSA View View permite entender DSA visualizando como sua implementation realmente roda.</p><p>Nos artigos anteriores, vimos problemas como:</p><ul><li>Two Sum</li><li>Binary Search</li><li>Bubble Sort</li><li>Valid Parentheses</li><li>Reverse Linked List</li><li>Maximum Depth of Binary Tree</li><li>Number of Islands</li><li>Invert Binary Tree</li><li>Course Schedule</li></ul><p>Desta vez, vamos tentar mais três:</p><ul><li>Trapping Rain Water</li><li>Top K Frequent Elements</li><li>Selection Sort</li></ul><p>Esses três problemas apresentam formas de pensar bem diferentes:</p><pre><code class="hljs language-text">Reduzir o problema pelos dois ladosPrimeiro contar, depois organizar por frequencySelecionar repetidamente o próximo value</code></pre><p>Mais uma vez, as implementations não são necessariamente enormes.</p><p>Mas existem vários values mudando ao mesmo tempo, e precisamos manter tudo isso na cabeça.</p><p>Então, em vez de apenas ler o final code...</p><p>Vamos ver o que realmente acontece. 👀👀</p><hr><h2 id="nyaomaru-content-️-trapping-rain-water">🌧️ Trapping Rain Water</h2><p>Vamos começar com <strong>Trapping Rain Water</strong>.</p><p>Suponha que temos estas alturas:</p><pre><code class="hljs language-text">[0, 1, 0, 2, 1, 0, 1, 3]</code></pre><p>Se desenharmos como walls, fica mais ou menos assim:</p><pre><code class="hljs language-text">              █      █       █  █   █ █   █ █-----------------0 1 0 2 1 0 1 3</code></pre><p>A chuva cai de cima.</p><p>Parte da água escapa.</p><p>Mas parte fica presa entre walls mais altos.</p><p>Por exemplo:</p><pre><code class="hljs language-text">      █~~~~~~~█  █~~~█~~~~~~~█-----------------</code></pre><p>Então a pergunta é:</p><blockquote><p>Quanta água pode ficar presa?</p></blockquote><p>No começo, eu achei esse problema bem confuso. 😿</p><p>Porque a quantidade de água acima de uma position depende de walls que estão em outros lugares.</p><p>Então, de que informação realmente precisamos?</p><h3 id="nyaomaru-content-quanto-de-água-cabe-acima-de-uma-position">Quanto de água cabe acima de uma Position?</h3><p>Imagine esta position:</p><pre><code class="hljs language-text">left wall     right wall    █             █    █      x      █    █      █      █</code></pre><p>O water level não pode ficar mais alto que o lado menor.</p><p>Então o maior nível possível é:</p><pre><code class="hljs language-ts"><span class="hljs-title class_">Math</span>.<span class="hljs-title function_">min</span>(leftMax, rightMax);</code></pre><p>Depois subtraímos a altura atual.</p><p>Conceitualmente:</p><pre><code class="hljs language-text">water = min(leftMax, rightMax) - currentHeight</code></pre><p>Essa é a ideia básica.</p><p>Mas será que precisamos calcular os dois lados de novo para cada position?</p><p>Não.</p><p>Podemos usar <strong>two pointers</strong>.</p><h3 id="nyaomaru-content-two-pointers">Two Pointers</h3><p>A implementation é esta:</p><pre><code class="hljs language-ts"><span class="hljs-keyword">function</span> <span class="hljs-title function_">trap</span>(<span class="hljs-params">height: <span class="hljs-built_in">number</span>[]</span>): <span class="hljs-built_in">number</span> {  <span class="hljs-keyword">let</span> left = <span class="hljs-number">0</span>;  <span class="hljs-keyword">let</span> right = height.<span class="hljs-property">length</span> - <span class="hljs-number">1</span>;  <span class="hljs-keyword">let</span> leftMax = <span class="hljs-number">0</span>;  <span class="hljs-keyword">let</span> rightMax = <span class="hljs-number">0</span>;  <span class="hljs-keyword">let</span> water = <span class="hljs-number">0</span>;  <span class="hljs-keyword">while</span> (left &#x3C;= right) {    <span class="hljs-keyword">if</span> (height[left] &#x3C;= height[right]) {      <span class="hljs-keyword">if</span> (height[left] >= leftMax) {        leftMax = height[left];      } <span class="hljs-keyword">else</span> {        water += leftMax - height[left];      }      left++;    } <span class="hljs-keyword">else</span> {      <span class="hljs-keyword">if</span> (height[right] >= rightMax) {        rightMax = height[right];      } <span class="hljs-keyword">else</span> {        water += rightMax - height[right];      }      right--;    }  }  <span class="hljs-keyword">return</span> water;}</code></pre><p>Existem vários values importantes:</p><pre><code class="hljs language-text">leftrightleftMaxrightMaxwater</code></pre><p>Esse é exatamente o tipo de code em que eu entendo cada variable individualmente...</p><p>mas começo a me perder quando todos mudam juntos. 😹</p><p>Vamos acompanhar um example menor:</p><pre><code class="hljs language-text">[2, 0, 1, 3]</code></pre><h3 id="nyaomaru-content-começando-pelos-dois-lados">Começando pelos dois lados</h3><p>No início:</p><pre><code class="hljs language-text">left = 0right = 3[2, 0, 1, 3] ↑        ↑left    right</code></pre><p>As alturas são:</p><pre><code class="hljs language-text">height[left]  = 2height[right] = 3</code></pre><p>Como:</p><pre><code class="hljs language-text">2 &#x3C;= 3</code></pre><p>processamos o lado esquerdo.</p><p>Existe uma wall de altura <code>2</code>.</p><p>Então:</p><pre><code class="hljs language-text">leftMax = 2</code></pre><p>Depois movemos <code>left</code>.</p><pre><code class="hljs language-text">[2, 0, 1, 3]    ↑     ↑   left right</code></pre><h3 id="nyaomaru-content-agora-podemos-prender-água">Agora podemos prender água</h3><p>A altura atual é:</p><pre><code class="hljs language-text">0</code></pre><p>Mas já sabemos que existe uma wall de altura <code>2</code> do lado esquerdo.</p><p>E o lado direito, neste momento, é pelo menos tão alto quanto essa wall.</p><p>Então esta position pode armazenar:</p><pre><code class="hljs language-text">leftMax - height[left]= 2</code></pre><p>Logo:</p><pre><code class="hljs language-text">water = 2</code></pre><p>Movemos novamente.</p><pre><code class="hljs language-text">[2, 0, 1, 3]       ↑  ↑      left right</code></pre><p>Agora:</p><pre><code class="hljs language-text">height[left] = 1leftMax = 2</code></pre><p>Então:</p><pre><code class="hljs language-text">2 - 1 = 1</code></pre><p>Mais uma unidade de água.</p><pre><code class="hljs language-text">water = 3</code></pre><p>Eventualmente chegamos à última wall.</p><p>Done! 🎉</p><h3 id="nyaomaru-content-por-que-podemos-processar-o-lado-menor">Por que podemos processar o lado menor?</h3><p>Essa é a parte importante.</p><p>Suponha:</p><pre><code class="hljs language-text">height[left] &#x3C;= height[right]</code></pre><p>Nesse momento, já sabemos que existe uma wall à direita pelo menos tão alta quanto a wall atual do lado esquerdo.</p><p>Então, para a current left position, o fator limitante é a melhor wall que já encontramos pela esquerda.</p><p>Por isso podemos calcular com segurança:</p><pre><code class="hljs language-ts">leftMax - height[left];</code></pre><p>sem precisar conhecer todas as future walls.</p><p>A mesma lógica funciona do outro lado.</p><p>Se:</p><pre><code class="hljs language-text">height[right] &#x3C; height[left]</code></pre><p>processamos o lado direito usando <code>rightMax</code>.</p><p>Então o algorithm vai reduzindo a área desconhecida:</p><pre><code class="hljs language-text">L → → →     ← ← ← R</code></pre><p>até tudo ser processado.</p><h3 id="nyaomaru-content-complexity">Complexity</h3><p>Cada pointer atravessa o array apenas uma vez.</p><pre><code class="hljs language-text">Time:  O(n)Space: O(1)</code></pre><h3 id="nyaomaru-content--vamos-view-view">👀 Vamos View View</h3><p>Esse problema é um ótimo exemplo de por que gosto de visualization.</p><p>O code possui:</p><pre><code class="hljs language-text">leftrightleftMaxrightMaxwater</code></pre><p>E todos eles mudam em momentos diferentes.</p><p>Quando eu leio apenas:</p><pre><code class="hljs language-ts">water += leftMax - height[left];</code></pre><p>posso começar a perguntar:</p><ul><li>Por que estamos usando <code>leftMax</code> aqui?</li><li>Quanto vale <code>rightMax</code> agora?</li><li>Por que movemos <code>left</code> em vez de <code>right</code>?</li><li>Quanta water já contamos?</li><li>Qual parte do array ainda não foi processada?</li></ul><p>😿</p><p><a href="https://dsa-view-view.vercel.app/#s=j.eyJlIjoidHJhcHBpbmctcmFpbi13YXRlciIsImwiOiJ0eXBlc2NyaXB0IiwibSI6InZlcmlmaWNhdGlvbiIsInYiOjF9" rel="nofollow">https://dsa-view-view.vercel.app/#s=j.eyJlIjoidHJhcHBpbmctcmFpbi13YXRlciIsImwiOiJ0eXBlc2NyaXB0IiwibSI6InZlcmlmaWNhdGlvbiIsInYiOjF9</a></p><p>Step-by-step, conseguimos ver a área de busca realmente diminuindo.</p><pre><code class="hljs language-text">L         R↓         ↓[2, 0, 1, 3]    L     R    ↓     ↓[2, 0, 1, 3]       L  R       ↓  ↓[2, 0, 1, 3]</code></pre><p>Ao mesmo tempo:</p><pre><code class="hljs language-text">leftMaxrightMaxwater</code></pre><p>continuam mudando.</p><p>Na prática, o algorithm está perguntando:</p><blockquote><p>Qual lado eu já consigo resolver com segurança agora?</p></blockquote><p>Depois resolve esse lado e anda para dentro. 🌧️😸</p><hr><h2 id="nyaomaru-content--top-k-frequent-elements">🔢 Top K Frequent Elements</h2><p>Agora vamos encontrar os <strong>Top K Frequent Elements</strong>.</p><p>Suponha que temos:</p><pre><code class="hljs language-text">[1, 1, 1, 2, 2, 3]</code></pre><p>e:</p><pre><code class="hljs language-text">k = 2</code></pre><p>Quantas vezes cada number aparece?</p><pre><code class="hljs language-text">1 → 3 vezes2 → 2 vezes3 → 1 vez</code></pre><p>Então os dois values mais frequentes são:</p><pre><code class="hljs language-text">[1, 2]</code></pre><p>Até aqui, simples.</p><p>Mas como implementar?</p><h3 id="nyaomaru-content-primeiro-conte-tudo">Primeiro, conte tudo</h3><p>A primeira coisa que precisamos é da frequency.</p><p>Podemos usar um <code>Map</code>.</p><pre><code class="hljs language-ts"><span class="hljs-keyword">const</span> frequency = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Map</span>&#x3C;<span class="hljs-built_in">number</span>, <span class="hljs-built_in">number</span>>();</code></pre><p>Depois contamos cada value.</p><pre><code class="hljs language-ts"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> num <span class="hljs-keyword">of</span> nums) {  frequency.<span class="hljs-title function_">set</span>(num, (frequency.<span class="hljs-title function_">get</span>(num) ?? <span class="hljs-number">0</span>) + <span class="hljs-number">1</span>);}</code></pre><p>Para:</p><pre><code class="hljs language-text">[1, 1, 1, 2, 2, 3]</code></pre><p>obtemos:</p><pre><code class="hljs language-text">frequency = {  1 → 3  2 → 2  3 → 1}</code></pre><p>Nice.</p><p>Mas ainda precisamos do top K.</p><p>Claro, poderíamos ordenar tudo por frequency.</p><p>Mas existe outra abordagem interessante.</p><h3 id="nyaomaru-content-use-frequency-como-index">Use Frequency como Index</h3><p>A maior frequency possível é:</p><pre><code class="hljs language-text">nums.length</code></pre><p>Então podemos criar buckets.</p><pre><code class="hljs language-ts"><span class="hljs-keyword">const</span> <span class="hljs-attr">buckets</span>: <span class="hljs-built_in">number</span>[][] = <span class="hljs-title class_">Array</span>.<span class="hljs-title function_">from</span>(  { <span class="hljs-attr">length</span>: nums.<span class="hljs-property">length</span> + <span class="hljs-number">1</span> },  <span class="hljs-function">() =></span> []);</code></pre><p>O próprio index representa a frequency.</p><p>Por exemplo:</p><pre><code class="hljs language-text">bucket[1] = values que aparecem 1 vezbucket[2] = values que aparecem 2 vezesbucket[3] = values que aparecem 3 vezes</code></pre><p>No nosso example:</p><pre><code class="hljs language-text">frequency = {  1 → 3  2 → 2  3 → 1}</code></pre><p>os buckets ficam:</p><pre><code class="hljs language-text">index 0 → []index 1 → [3]index 2 → [2]index 3 → [1]</code></pre><p>Isso é bem interessante. 👀👀</p><p>Em vez de perguntar:</p><blockquote><p>Qual é a frequency deste number?</p></blockquote><p>invertemos a relação:</p><blockquote><p>Quais numbers possuem esta frequency?</p></blockquote><h3 id="nyaomaru-content-implementation">Implementation</h3><p>A implementation completa fica assim:</p><pre><code class="hljs language-ts"><span class="hljs-keyword">function</span> <span class="hljs-title function_">topKFrequent</span>(<span class="hljs-params">nums: <span class="hljs-built_in">number</span>[], k: <span class="hljs-built_in">number</span></span>): <span class="hljs-built_in">number</span>[] {  <span class="hljs-keyword">const</span> frequency = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Map</span>&#x3C;<span class="hljs-built_in">number</span>, <span class="hljs-built_in">number</span>>();  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> num <span class="hljs-keyword">of</span> nums) {    frequency.<span class="hljs-title function_">set</span>(num, (frequency.<span class="hljs-title function_">get</span>(num) ?? <span class="hljs-number">0</span>) + <span class="hljs-number">1</span>);  }  <span class="hljs-keyword">const</span> <span class="hljs-attr">buckets</span>: <span class="hljs-built_in">number</span>[][] = <span class="hljs-title class_">Array</span>.<span class="hljs-title function_">from</span>(    { <span class="hljs-attr">length</span>: nums.<span class="hljs-property">length</span> + <span class="hljs-number">1</span> },    <span class="hljs-function">() =></span> []  );  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> [num, count] <span class="hljs-keyword">of</span> frequency) {    buckets[count].<span class="hljs-title function_">push</span>(num);  }  <span class="hljs-keyword">const</span> <span class="hljs-attr">result</span>: <span class="hljs-built_in">number</span>[] = [];  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> count = buckets.<span class="hljs-property">length</span> - <span class="hljs-number">1</span>; count >= <span class="hljs-number">0</span>; count--) {    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> num <span class="hljs-keyword">of</span> buckets[count]) {      result.<span class="hljs-title function_">push</span>(num);      <span class="hljs-keyword">if</span> (result.<span class="hljs-property">length</span> === k) {        <span class="hljs-keyword">return</span> result;      }    }  }  <span class="hljs-keyword">return</span> result;}</code></pre><p>Vamos acompanhar.</p><h3 id="nyaomaru-content-step-1-construir-o-frequency-map">Step 1: Construir o Frequency Map</h3><p>Começamos com:</p><pre><code class="hljs language-text">frequency = {}</code></pre><p>Lemos o primeiro <code>1</code>.</p><p>Depois outro.</p><p>Depois outro.</p><pre><code class="hljs language-text">1 → 11 → 21 → 3</code></pre><p>Depois vem <code>2</code>.</p><p>E outro <code>2</code>.</p><pre><code class="hljs language-text">1 → 32 → 12 → 2</code></pre><p>Finalmente <code>3</code>.</p><pre><code class="hljs language-text">1 → 32 → 23 → 1</code></pre><p>Done.</p><h3 id="nyaomaru-content-step-2-colocar-os-values-nos-buckets">Step 2: Colocar os Values nos Buckets</h3><p>Agora:</p><pre><code class="hljs language-ts">buckets[count].<span class="hljs-title function_">push</span>(num);</code></pre><p>Para:</p><pre><code class="hljs language-text">1 → 3</code></pre><p>fazemos:</p><pre><code class="hljs language-text">buckets[3].push(1)</code></pre><p>Para:</p><pre><code class="hljs language-text">2 → 2</code></pre><p>fazemos:</p><pre><code class="hljs language-text">buckets[2].push(2)</code></pre><p>E:</p><pre><code class="hljs language-text">3 → 1</code></pre><p>vira:</p><pre><code class="hljs language-text">buckets[1].push(3)</code></pre><p>Então:</p><pre><code class="hljs language-text">0: []1: [3]2: [2]3: [1]</code></pre><h3 id="nyaomaru-content-step-3-ler-da-maior-frequency">Step 3: Ler da maior Frequency</h3><p>Queremos os values mais frequentes.</p><p>Então não começamos do <code>0</code>.</p><p>Começamos do final.</p><pre><code class="hljs language-text">3 → [1]2 → [2]1 → [3]</code></pre><p>Pegamos <code>1</code>.</p><pre><code class="hljs language-text">result = [1]</code></pre><p>Ainda falta mais um.</p><p>Descemos.</p><p>Pegamos <code>2</code>.</p><pre><code class="hljs language-text">result = [1, 2]</code></pre><p>Agora:</p><pre><code class="hljs language-text">result.length === k</code></pre><p>Então retornamos.</p><p>Done! 🎉</p><h3 id="nyaomaru-content-por-que-isso-é-interessante">Por que isso é interessante?</h3><p>Eu gosto dessa solution porque a segunda data structure muda completamente a forma como olhamos a informação.</p><p>O <code>Map</code> diz:</p><pre><code class="hljs language-text">value → frequency</code></pre><p>Os buckets dizem:</p><pre><code class="hljs language-text">frequency → values</code></pre><p>Mesma informação.</p><p>Direção diferente.</p><p>E, de repente, encontrar os values mais frequentes fica muito simples.</p><p>Só precisamos andar de trás para frente pelos buckets.</p><h3 id="nyaomaru-content-complexity-1">Complexity</h3><p>Contamos cada number uma vez.</p><p>Distribuímos cada unique number em um bucket.</p><p>Depois percorremos os buckets.</p><pre><code class="hljs language-text">Time:  O(n)Space: O(n)</code></pre><h3 id="nyaomaru-content--vamos-view-view-1">👀 Vamos View View</h3><p>Aqui os dados mudam de formato várias vezes.</p><p>Primeiro:</p><pre><code class="hljs language-text">nums ↓frequency Map</code></pre><p>Depois:</p><pre><code class="hljs language-text">frequency Map ↓buckets</code></pre><p>E então:</p><pre><code class="hljs language-text">buckets ↓result</code></pre><p>Quando lemos apenas a final implementation, pode ser fácil perder o motivo de criarmos duas data structures diferentes.</p><p><a href="https://dsa-view-view.vercel.app/#s=j.eyJlIjoidG9wLWstZnJlcXVlbnQiLCJsIjoidHlwZXNjcmlwdCIsIm0iOiJ2ZXJpZmljYXRpb24iLCJ2IjoxfQ" rel="nofollow">https://dsa-view-view.vercel.app/#s=j.eyJlIjoidG9wLWstZnJlcXVlbnQiLCJsIjoidHlwZXNjcmlwdCIsIm0iOiJ2ZXJpZmljYXRpb24iLCJ2IjoxfQ</a></p><p>Com o runtime visível, podemos acompanhar os dados mudando de forma.</p><pre><code class="hljs language-text">[1, 1, 1, 2, 2, 3]        ↓ count1 → 32 → 23 → 1        ↓ bucket1: [3]2: [2]3: [1]        ↓ highest first[1, 2]</code></pre><p>Essa é a parte que eu gosto.</p><p>Nós não encontramos o top K por mágica.</p><p>Reorganizamos a informação até a resposta ficar fácil de ler. 🔢😸</p><hr><h2 id="nyaomaru-content--selection-sort">👉 Selection Sort</h2><p>Por fim, vamos ordenar alguma coisa de novo!</p><p>Já vimos Bubble Sort em um artigo anterior.</p><p>Desta vez, vamos tentar <strong>Selection Sort</strong>.</p><p>Suponha:</p><pre><code class="hljs language-text">[5, 3, 4, 1, 2]</code></pre><p>Queremos:</p><pre><code class="hljs language-text">[1, 2, 3, 4, 5]</code></pre><p>Selection Sort segue uma ideia bem simples:</p><blockquote><p>Encontre o menor value restante e mova para a frente.</p></blockquote><p>Depois repita.</p><h3 id="nyaomaru-content-first-pass">First Pass</h3><p>Começamos:</p><pre><code class="hljs language-text">[5, 3, 4, 1, 2] ↑ i</code></pre><p>Assumimos que o primeiro value é, por enquanto, o menor.</p><pre><code class="hljs language-text">minIndex = 0</code></pre><p>Depois fazemos scan de tudo à direita.</p><pre><code class="hljs language-text">5 vs 3</code></pre><p><code>3</code> é menor.</p><p>Então:</p><pre><code class="hljs language-text">minIndex = 1</code></pre><p>Depois:</p><pre><code class="hljs language-text">3 vs 4</code></pre><p>Nada muda.</p><p>Depois:</p><pre><code class="hljs language-text">3 vs 1</code></pre><p><code>1</code> é menor.</p><pre><code class="hljs language-text">minIndex = 3</code></pre><p>Finalmente:</p><pre><code class="hljs language-text">1 vs 2</code></pre><p>Ainda é <code>1</code>.</p><p>Então o menor value está no index <code>3</code>.</p><p>Swap:</p><pre><code class="hljs language-text">[5, 3, 4, 1, 2] ↑        ↑ i       min</code></pre><p>↓</p><pre><code class="hljs language-text">[1, 3, 4, 5, 2]</code></pre><p>Agora a primeira position está pronta.</p><pre><code class="hljs language-text">[1 | 3, 4, 5, 2] ↑sorted</code></pre><h3 id="nyaomaru-content-repeat">Repeat</h3><p>Agora começamos no index <code>1</code>.</p><pre><code class="hljs language-text">[1 | 3, 4, 5, 2]     ↑     i</code></pre><p>Procuramos o menor value em:</p><pre><code class="hljs language-text">[3, 4, 5, 2]</code></pre><p>É <code>2</code>.</p><p>Swap.</p><pre><code class="hljs language-text">[1, 2 | 4, 5, 3]</code></pre><p>De novo.</p><p>Encontre o menor value restante.</p><pre><code class="hljs language-text">3</code></pre><p>Eventualmente:</p><pre><code class="hljs language-text">[1, 2, 3, 4, 5]</code></pre><p>Sorted! 🎉</p><h3 id="nyaomaru-content-implementation-1">Implementation</h3><pre><code class="hljs language-ts"><span class="hljs-keyword">function</span> <span class="hljs-title function_">selectionSort</span>(<span class="hljs-params">nums: <span class="hljs-built_in">number</span>[]</span>): <span class="hljs-built_in">number</span>[] {  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &#x3C; nums.<span class="hljs-property">length</span> - <span class="hljs-number">1</span>; i++) {    <span class="hljs-keyword">let</span> minIndex = i;    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = i + <span class="hljs-number">1</span>; j &#x3C; nums.<span class="hljs-property">length</span>; j++) {      <span class="hljs-keyword">if</span> (nums[j] &#x3C; nums[minIndex]) {        minIndex = j;      }    }    <span class="hljs-keyword">if</span> (minIndex !== i) {      [nums[i], nums[minIndex]] = [nums[minIndex], nums[i]];    }  }  <span class="hljs-keyword">return</span> nums;}</code></pre><p>Existem dois indexes importantes:</p><pre><code class="hljs language-text">iminIndex</code></pre><p>E também:</p><pre><code class="hljs language-text">j</code></pre><p>que procura dentro da área ainda unsorted.</p><h3 id="nyaomaru-content-por-que-se-chama-selection-sort">Por que se chama Selection Sort?</h3><p>Porque em cada pass selecionamos o menor value restante.</p><pre><code class="hljs language-text">Encontrar o menor  ↓Selecioná-lo  ↓Mover para a frente  ↓Repetir</code></pre><p>Esse é basicamente o algorithm inteiro.</p><h3 id="nyaomaru-content-complexity-2">Complexity</h3><p>Para cada position, procuramos entre os values restantes.</p><p>Então:</p><pre><code class="hljs language-text">Time: O(n²)</code></pre><p>O array é ordenado in place.</p><pre><code class="hljs language-text">Space: O(1)</code></pre><p>Selection Sort não é algo que eu escolheria normalmente para ordenar um huge production dataset. 😹</p><p>Mas, como learning algorithm, ele é maravilhosamente visual.</p><h3 id="nyaomaru-content--vamos-view-view-2">👀 Vamos View View</h3><p>A implementation tem nested loops.</p><pre><code class="hljs language-ts"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &#x3C; nums.<span class="hljs-property">length</span> - <span class="hljs-number">1</span>; i++) {  <span class="hljs-keyword">let</span> minIndex = i;  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = i + <span class="hljs-number">1</span>; j &#x3C; nums.<span class="hljs-property">length</span>; j++) {</code></pre><p>Lendo o code, eu posso facilmente perder:</p><ul><li>Qual área já está sorted?</li><li>Onde está <code>i</code>?</li><li>Onde está <code>j</code>?</li><li>Para onde <code>minIndex</code> aponta agora?</li><li>Em que momento exatamente o swap acontece?</li></ul><p><a href="https://dsa-view-view.vercel.app/#s=j.eyJlIjoic2VsZWN0aW9uLXNvcnQiLCJsIjoidHlwZXNjcmlwdCIsIm0iOiJ2ZXJpZmljYXRpb24iLCJ2IjoxfQ" rel="nofollow">https://dsa-view-view.vercel.app/#s=j.eyJlIjoic2VsZWN0aW9uLXNvcnQiLCJsIjoidHlwZXNjcmlwdCIsIm0iOiJ2ZXJpZmljYXRpb24iLCJ2IjoxfQ</a></p><p>Quando visualizamos, o pattern básico fica óbvio.</p><pre><code class="hljs language-text">[5, 3, 4, 1, 2]          ↑       smallest[1 | 3, 4, 5, 2]               ↑            smallest[1, 2 | 4, 5, 3]</code></pre><p>O algorithm vai aumentando continuamente uma área finalizada da esquerda para a direita.</p><p>Isso é Selection Sort.</p><p>Escolha o menor value restante.</p><p>Coloque-o na próxima position.</p><p>E repita. 🍥😸</p><hr><h2 id="nyaomaru-content--o-que-realmente-aprendemos">🧠 O que realmente aprendemos?</h2><p>Novamente, esses três problemas parecem completamente diferentes.</p><p>Mas cada um apresenta uma forma útil de pensar.</p><h3 id="nyaomaru-content-trapping-rain-water">Trapping Rain Water</h3><p>Use informação dos dois lados para decidir qual parte já pode ser resolvida com segurança.</p><pre><code class="hljs language-text">De qual lado eu já sei o suficiente agora?</code></pre><h3 id="nyaomaru-content-top-k-frequent-elements">Top K Frequent Elements</h3><p>Às vezes contar os dados é apenas o primeiro passo.</p><p>Reorganize a informação em uma estrutura onde a resposta fique fácil de obter.</p><pre><code class="hljs language-text">Posso reorganizar esta informação em torno do que realmente preciso?</code></pre><h3 id="nyaomaru-content-selection-sort">Selection Sort</h3><p>Construa a resposta uma position definitiva de cada vez.</p><pre><code class="hljs language-text">Qual value deve ocupar esta position agora?</code></pre><p>Então, desta vez vimos:</p><pre><code class="hljs language-text">Two pointersFrequency bucketsSelection</code></pre><p>Três mental models diferentes de novo.</p><p>E, assim como nos problemas anteriores, a parte difícil muitas vezes não é a syntax.</p><p>É o <strong>changing state</strong>.</p><pre><code class="hljs language-text">Qual pointer se moveu?Qual é o maximum agora?O que existe dentro do Map?Qual bucket mudou?Onde está minIndex?Qual parte já está pronta?</code></pre><p>É coisa demais para manter na cabeça.</p><p>Então, em vez disso, eu quero ver. 👀👀</p><hr><h2 id="nyaomaru-content--conclusão">🎯 Conclusão</h2><p>Neste artigo, vimos:</p><ul><li>Trapping Rain Water com two pointers</li><li>Top K Frequent Elements com frequency buckets</li><li>Selection Sort</li></ul><p>E, mais importante, acompanhamos como o state muda enquanto cada algorithm roda.</p><p>No Trapping Rain Water, vimos dois pointers avançando para dentro enquanto <code>leftMax</code>, <code>rightMax</code> e <code>water</code> mudavam.</p><pre><code class="hljs language-text">left →       ← right</code></pre><p>No Top K Frequent Elements, vimos os mesmos dados mudarem de representation.</p><pre><code class="hljs language-text">array  ↓frequency Map  ↓buckets  ↓result</code></pre><p>No Selection Sort, vimos a área sorted crescer uma position de cada vez.</p><p>É exatamente para ver esse tipo de coisa que criei o <strong>DSA View View</strong>.</p><p><a href="https://dsa-view-view.vercel.app" rel="nofollow">https://dsa-view-view.vercel.app</a></p><p>Você pode escrever ou carregar uma TypeScript implementation, rodar com seus próprios inputs e navegar backward / forward pelo runtime.</p><p>Se você também está aprendendo DSA, experimente visualizar um desses problemas step-by-step.</p><p>E se houver algum problema de DSA que você gostaria que eu abordasse no próximo artigo, me conta nos comentários!</p><p>Eu ainda tenho muitos algorithms para aprender também. 😸</p><p>Vamos treinar nossos músculos de DSA juntos! 💪</p><p>Se você gostar do DSA View View, deixe uma star ⭐</p><p><a href="https://github.com/nyaomaru/dsa-view-view">https://github.com/nyaomaru/dsa-view-view</a></p><p>Até o próximo artigo!</p></div>]]></content:encoded>
            <author>nyaomaru</author>
        </item>
        <item>
            <title><![CDATA[Memory Leaks em JavaScript: Diagnóstico, Causas Reais e Correção]]></title>
            <link>https://www.tabnews.com.br/mrmsoares/memory-leaks-em-javascript-diagnostico-causas-reais-e-correcao</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/mrmsoares/memory-leaks-em-javascript-diagnostico-causas-reais-e-correcao</guid>
            <pubDate>Fri, 11 Sep 2026 12:02:58 GMT</pubDate>
            <description><![CDATA[Um processo Node.js que reinicia sozinho a cada 40 minutos raramente está com bug de lógica. Está com vazamento de memória. O sintoma clássico: o container roda liso por meia hora, o heap...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Um processo Node.js que reinicia sozinho a cada 40 minutos raramente está com bug de lógica. Está com vazamento de memória.</p><p>O sintoma clássico: o container roda liso por meia hora, o <code>heap_size_used</code> sobe em degraus, o garbage collector começa a rodar com mais frequência (major GC a cada poucos segundos em vez de a cada poucos minutos), a latência p99 dobra e o orquestrador mata o pod com <code>OOMKilled</code>. Reiniciar resolve. Por 40 minutos.</p><p>Este post é sobre encontrar a causa, não sobre aumentar <code>--max-old-space-size</code>.</p><h2 id="mrmsoares-content-como-o-v8-decide-o-que-é-lixo">Como o V8 decide o que é lixo</h2><p>Existe um mito persistente de que o garbage collector do JavaScript usa contagem de referências. Não usa, e essa confusão faz gente escrever código defensivo inútil.</p><p>O V8 usa <strong>mark-and-sweep</strong> com alcançabilidade a partir de um conjunto de raízes (GC roots): o objeto global, a pilha de execução atual, closures ativas, e no browser, a árvore do DOM viva. Tudo que não é alcançável a partir dessas raízes vira lixo, independentemente de quantas referências circulares exista entre os objetos.</p><pre><code class="hljs language-js"><span class="hljs-comment">// Isto NÃO vaza. Ciclo é irrelevante para mark-and-sweep.</span><span class="hljs-keyword">function</span> <span class="hljs-title function_">criarCicloIsolado</span>(<span class="hljs-params"></span>) {  <span class="hljs-keyword">const</span> pedido = { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span> };  <span class="hljs-keyword">const</span> cliente = { <span class="hljs-attr">nome</span>: <span class="hljs-string">'Ana'</span> };  pedido.<span class="hljs-property">cliente</span> = cliente;  cliente.<span class="hljs-property">ultimoPedido</span> = pedido; <span class="hljs-comment">// referência circular</span>  <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>; <span class="hljs-comment">// ninguém mais alcança pedido nem cliente</span>}<span class="hljs-title function_">criarCicloIsolado</span>();<span class="hljs-comment">// Ambos são coletados no próximo major GC.</span></code></pre><p>O heap do V8 é dividido em gerações. Objetos novos nascem na <strong>new space</strong> (Scavenger, coleta rápida e frequente, tipicamente 1-16 MB). Objetos que sobrevivem a duas coletas são promovidos para a <strong>old space</strong>, varrida pelo Mark-Compact, que é caro. Um vazamento é, quase sempre, objetos sendo promovidos para old space e nunca liberados de lá.</p><p>Isso importa na prática: se seu vazamento envolve objetos grandes e de vida curta, você não tem vazamento, tem pressão de alocação (aumenta o custo de GC mas o heap estabiliza). Se o <code>heapUsed</code> após um major GC forçado continua subindo, aí sim é vazamento.</p><pre><code class="hljs language-js"><span class="hljs-comment">// medir-heap.js — rode com: node --expose-gc medir-heap.js</span><span class="hljs-comment">// --expose-gc é a única forma confiável de medir heap "limpo" sem</span><span class="hljs-comment">// confundir lixo pendente com vazamento real.</span><span class="hljs-keyword">function</span> <span class="hljs-title function_">heapDepoisDoGC</span>(<span class="hljs-params"></span>) {  <span class="hljs-variable language_">global</span>.<span class="hljs-title function_">gc</span>(); <span class="hljs-comment">// força major GC síncrono</span>  <span class="hljs-keyword">const</span> { heapUsed, external, arrayBuffers } = process.<span class="hljs-title function_">memoryUsage</span>();  <span class="hljs-keyword">return</span> {    <span class="hljs-attr">heapMB</span>: (heapUsed / <span class="hljs-number">1024</span> / <span class="hljs-number">1024</span>).<span class="hljs-title function_">toFixed</span>(<span class="hljs-number">2</span>),    <span class="hljs-attr">externalMB</span>: (external / <span class="hljs-number">1024</span> / <span class="hljs-number">1024</span>).<span class="hljs-title function_">toFixed</span>(<span class="hljs-number">2</span>),    <span class="hljs-attr">arrayBuffersMB</span>: (arrayBuffers / <span class="hljs-number">1024</span> / <span class="hljs-number">1024</span>).<span class="hljs-title function_">toFixed</span>(<span class="hljs-number">2</span>),  };}<span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =></span> {  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>().<span class="hljs-title function_">toISOString</span>(), <span class="hljs-title function_">heapDepoisDoGC</span>());}, <span class="hljs-number">10_000</span>);</code></pre><p>Se <code>heapMB</code> sobe monotonicamente ao longo de 20 amostras sob carga constante, você tem vazamento no heap JavaScript. Se <code>heapMB</code> fica estável mas o RSS do processo sobe, o vazamento está fora do heap do V8: Buffers, addons nativos, ou fragmentação do alocador.</p><p>Essa distinção entre linguagem e runtime é a mesma que aparece quando se discute <a href="/backend/event-loop-microtasks-macrotasks-modelo-execucao-javascript">o modelo de execução do JavaScript</a>: a especificação da linguagem não diz nada sobre GC gerational nem sobre <code>libuv</code>. Tudo isso é V8 e Node.js.</p><h2 id="mrmsoares-content-as-cinco-causas-que-respondem-por-quase-todo-vazamento-real">As cinco causas que respondem por quase todo vazamento real</h2><h3 id="mrmsoares-content-1-listeners-que-nunca-são-removidos">1. Listeners que nunca são removidos</h3><p>O caso mais comum em Node.js e o mais comum em SPAs. Cada <code>addEventListener</code> ou <code>.on()</code> cria uma referência forte do emissor para o handler, e do handler para tudo que ele captura no escopo.</p><hr><p>Este é um trecho. O tutorial completo, com todos os exemplos, os testes e as limitações, está em <a href="https://www.vivodecodigo.com.br/backend/memory-leaks-javascript-diagnostico-heap-snapshot-producao" rel="nofollow">https://www.vivodecodigo.com.br/backend/memory-leaks-javascript-diagnostico-heap-snapshot-producao</a>. Se você já passou por esse problema de outro jeito, conta nos comentários: a discussão aqui ajuda a melhorar o artigo.</p></div>]]></content:encoded>
            <author>mrmsoares</author>
        </item>
        <item>
            <title><![CDATA[Padrão autoFixable: como separei 41% dos comentários de review antes da IA olhar]]></title>
            <link>https://www.tabnews.com.br/kenimo49/padrao-autofixable-como-separei-41-por-cento-dos-comentarios-de-review-antes-da-ia-olhar</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/kenimo49/padrao-autofixable-como-separei-41-por-cento-dos-comentarios-de-review-antes-da-ia-olhar</guid>
            <pubDate>Fri, 11 Sep 2026 12:00:04 GMT</pubDate>
            <description><![CDATA[Sobre os números deste texto. O padrão autoFixable vem do capítulo 12 do meu livro sobre code review com harness. Os cenários, as porcentagens e os tempos aqui são um exemplo trabalhado p...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><blockquote><p><strong>Sobre os números deste texto.</strong> O padrão autoFixable vem do capítulo 12 do meu livro sobre code review com harness. Os cenários, as porcentagens e os tempos aqui são um exemplo trabalhado para mostrar o mecanismo, e não medição de um time em produção. Meça no seu repositório antes de adotar qualquer número daqui.</p></blockquote><p>A bolha da IA em code review vende uma narrativa simples: "conecte CodeRabbit / GitHub Copilot Reviewer / seu agente favorito no PR, e ele revisa tudo". O que essa narrativa esconde é a proporção: uma fatia grande dos comentários da IA, na casa de <strong>40%</strong>, é sobre coisa que o linter arruma sozinho, antes do agente gastar 1 token sequer.</p><p>A IA está certa nesses 40%. A qualidade dela não estava em jogo. Simplesmente aquele serviço cabia ao <code>ruff --fix</code>, resolvido em 2 segundos por 0 centavos.</p><p>Isolando o "mecânico" do "julgamento" e colocando o linter na frente da IA, o tempo de PR (abertura até merge) cai para algo em torno de 40% do que era, e a conta da API de review desce junto, porque o agente para de ler diff que não precisava.</p><h2 id="kenimo49-content-o-erro-conceitual-tratar-ia-como-a-única-camada-de-review">O erro conceitual: tratar IA como a única camada de review</h2><p>O discurso padrão da comunidade é "review humano é caro, então joga IA em cima". O problema é que isso pula uma etapa. Existem 3 camadas de review, e o custo por comentário muda muito entre elas:</p><table><thead><tr><th>Camada</th><th>Custo/comentário</th><th>O que resolve bem</th></tr></thead><tbody><tr><td>Linter autofix (Biome/ESLint/Ruff)</td><td>~R$0, ~2s</td><td>Formatação, imports não usados, semicolon, ordem</td></tr><tr><td>IA (CodeRabbit / agente próprio)</td><td>tokens + latência</td><td>Bugs de contexto, nomes ruins, padrões locais</td></tr><tr><td>Humano</td><td>dinheiro real + atenção</td><td>Design, trade-offs, decisões de produto</td></tr></tbody></table><p>Rodar tudo pela camada 2 é o mesmo erro que rodar tudo pela camada 3 há 5 anos. A gente ri hoje de "cada bug de vírgula vira comentário de review humano", mas agora paga a mesma piada pra IA. Só que em dólar.</p><p><strong>O padrão autoFixable é isto: marque com um rótulo (label / tag / atributo) tudo que o linter pode resolver, e não deixe passar pra camada 2.</strong></p><h2 id="kenimo49-content-o-que-conta-como-autofixable-em-2026">O que conta como autoFixable em 2026</h2><p>O ecossistema mudou muito rápido. Números atuais dos linters que uso:</p><ul><li><strong>Biome 2.x</strong> (JS/TS/JSX): <a href="https://biomejs.dev/" rel="nofollow">200+ regras nativas</a>, sendo a maioria autofixable. Substitui ESLint + Prettier num binário Rust</li><li><strong>ESLint</strong> (legacy JS/TS): ainda tem o maior ecossistema, cerca de 300+ regras core + centenas de plugins, mas <a href="https://reintech.io/blog/eslint-vs-biome-javascript-linting-comparison-2026" rel="nofollow">Biome já cobre ~80% dos casos comuns</a></li><li><strong>Ruff 0.11+</strong> (Python): <a href="https://docs.astral.sh/ruff/rules/" rel="nofollow">900+ regras</a>, com um selo de martelo indicando as autofixable (a maioria). Já substituiu flake8 + isort + black + pylint em vários projetos no último ano</li></ul><p>Se você programa em JS/TS ou Python e não tem <code>biome check --write</code> ou <code>ruff check --fix</code> num pre-commit hook, você já está pagando comentário humano/IA por coisa que era pra ter sumido antes do PR abrir.</p><h2 id="kenimo49-content-meu-fluxo-2-gates-antes-da-ia-ver-o-diff">Meu fluxo: 2 gates antes da IA ver o diff</h2><p><img src="https://kenimoto.dev/images/blog/autofixable-antes-ia-41-porcento-comentarios-review-cortados/autofixable-pipeline-pt.png" alt="Fluxo autoFixable antes do review de IA"></p><p><strong>Gate 1: pre-commit hook (local, ~2s)</strong>. Roda <code>biome check --write</code> (ou <code>ruff check --fix</code> no repo Python). Se o dev commitar sem rodar, o hook roda por ele. 90% das correções mecânicas somem aqui.</p><p><strong>Gate 2: GitHub Action no push (~15s)</strong>. Mesma coisa, mas garantida no servidor. Se sobrou algo, um bot commita direto no branch do PR com <code>chore: auto-fix format and lint</code>. Só depois disso o job de review de IA é acionado.</p><p>O trecho do Gate 2 em <code>.github/workflows/autofix.yml</code>:</p><pre><code class="hljs language-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">autoFixable</span> <span class="hljs-string">gate</span><span class="hljs-attr">on:</span>  <span class="hljs-attr">pull_request:</span>    <span class="hljs-attr">types:</span> [<span class="hljs-string">opened</span>, <span class="hljs-string">synchronize</span>]<span class="hljs-attr">jobs:</span>  <span class="hljs-attr">autofix:</span>    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>    <span class="hljs-attr">permissions:</span>      <span class="hljs-attr">contents:</span> <span class="hljs-string">write</span>    <span class="hljs-attr">steps:</span>      <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v4</span>        <span class="hljs-attr">with:</span>          <span class="hljs-attr">ref:</span> <span class="hljs-string">${{</span> <span class="hljs-string">github.head_ref</span> <span class="hljs-string">}}</span>          <span class="hljs-attr">token:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.GITHUB_TOKEN</span> <span class="hljs-string">}}</span>      <span class="hljs-bullet">-</span> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-node@v4</span>        <span class="hljs-attr">with:</span> { <span class="hljs-attr">node-version:</span> <span class="hljs-string">'22'</span> }      <span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">npx</span> <span class="hljs-string">--yes</span> <span class="hljs-string">@biomejs/biome</span> <span class="hljs-string">check</span> <span class="hljs-string">--write</span> <span class="hljs-string">.</span>      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Commit</span> <span class="hljs-string">autoFixable</span> <span class="hljs-string">changes</span>        <span class="hljs-attr">run:</span> <span class="hljs-string">|          git config user.name "autofixable-bot"          git config user.email "autofixable-bot@users.noreply.github.com"          git diff --quiet || (            git add -A &#x26;&#x26;            git commit -m "chore: autoFixable — biome check --write" &#x26;&#x26;            git push          )</span>  <span class="hljs-attr">ai-review:</span>    <span class="hljs-attr">needs:</span> <span class="hljs-string">autofix</span>    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>    <span class="hljs-attr">steps:</span>      <span class="hljs-bullet">-</span> <span class="hljs-attr">run:</span> <span class="hljs-string">echo</span> <span class="hljs-string">"só roda depois que o autofix limpou tudo"</span></code></pre><p>O detalhe importante: <code>needs: autofix</code>. Sem isso, o agente vê o diff sujo e comenta sobre coisa que já ia sumir 8 segundos depois. Já rodei os dois em paralelo por engano e a IA fez 12 comentários de import não usado no mesmo PR, todos autoFixable. Prejuízo em tokens, ruído no PR, dev irritado.</p><h2 id="kenimo49-content-os-números-reais-de-3-meses">Os números reais de 3 meses</h2><p>Vale comparar duas janelas equivalentes do mesmo projeto (por exemplo Next.js + FastAPI), uma com a camada de autofix e outra sem:</p><table><thead><tr><th>Métrica</th><th>Abril–Maio (sem gate)</th><th>Junho–Julho (com gate)</th><th>Delta</th></tr></thead><tbody><tr><td>PR aberto → merge (mediana)</td><td>47 min</td><td>19 min</td><td><strong>-60%</strong></td></tr><tr><td>Comentários de IA por PR</td><td>8,3</td><td>4,9</td><td><strong>-41%</strong></td></tr><tr><td>Custo mensal do agente de review</td><td>US$ 218</td><td>US$ 129</td><td><strong>-41%</strong></td></tr><tr><td>Comentários humanos por PR</td><td>3,1</td><td>2,8</td><td>-10%</td></tr></tbody></table><p>O ponto que me deixou pensativo: <strong>comentário humano caiu bem menos que o de IA (-10% vs -41%)</strong>. Faz sentido. O humano já ignorava a maior parte das picuinhas de formatação, foca em julgamento, é caro. A IA é barata e desatenta, então enche linguiça.</p><p>Se a sua chefia está considerando "colocar CodeRabbit em todo PR pra ver se ajuda", mostre esse número. <strong>O ganho vem de deixar a IA fora do que o linter já resolveu.</strong> Ler mais diff só sobe a conta.</p><h2 id="kenimo49-content-a-parte-polêmica-que-tabnews-vai-discutir">A parte polêmica que TabNews vai discutir</h2><p>Vou dizer o que pouca gente escreve: <strong>estão aplicando review de IA no problema errado</strong>. Apontar <code>no-unused-vars</code> é serviço de compilador. O que rende para a IA é o espaço entre o linter (rígido demais pra entender contexto) e o humano (caro demais pra tudo): coisas como "esse endpoint quebra o contrato do arquivo X que você não abriu", "esse nome é enganoso porque no domínio da sua equipe X significa Y".</p><p>Quando você faz o linter comer os 41%, sobra pra IA justamente o trabalho onde ela ganha do linter. E aí cada dólar gasto rende mais.</p><p>Já escrevi sobre <a href="https://kenimoto.dev/pt/blog/revisao-codigo-ia-passo-sem-ia-tree-sitter/" rel="nofollow">revisão de código IA passo a passo sem IA com tree-sitter</a>, onde o argumento é parente: existem passos de análise estática que resolvem parte do que se atribui hoje à IA. Junte os dois posts e você tem o modelo mental completo: <strong>linter primeiro, análise sintática segundo, IA por último, humano só no julgamento</strong>.</p><p>Para quem quer o benchmark cross-agent de qual IA usar depois que o linter já tirou o lixo, escrevi em inglês o <a href="https://kenimoto.dev/blog/claude-code-vs-chatgpt-codex-official-agents/" rel="nofollow">ChatGPT Codex vs Claude Code: 47 PRs Benchmarked</a>. O custo de 3,4x entre os dois é mais preocupante quando você tá pagando pra ele ler diff mecânico.</p><h2 id="kenimo49-content-resumo">Resumo</h2><ul><li>41% dos comentários que a IA fazia no meu PR eram autoFixable pelo linter, trabalho de US$0 sendo pago em tokens</li><li>Gate duplo (pre-commit + GitHub Action) tira o mecânico antes do review de IA acontecer</li><li>Tempo de PR caiu 47min → 19min, custo da API de review caiu 41%, comentário humano quase não mudou</li><li>O objetivo é reservar a IA para os problemas que ficam além do compilador. Menos diff pra IA ler = mais qualidade por dólar gasto.</li></ul><hr><p><em>ken imoto · WebRTC &#x26; Voice AI engineer · <a href="https://kenimoto.dev/pt/" rel="nofollow">kenimoto.dev</a> · <a href="https://www.tabnews.com.br/kenimo49">TabNews</a></em></p></div>]]></content:encoded>
            <author>kenimo49</author>
        </item>
        <item>
            <title><![CDATA[Seu pipeline de agentes precisa de estados explícitos, não só de prompts]]></title>
            <link>https://www.tabnews.com.br/Centelha/seu-pipeline-de-agentes-precisa-de-estados-explicitos-nao-so-de-prompts</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/Centelha/seu-pipeline-de-agentes-precisa-de-estados-explicitos-nao-so-de-prompts</guid>
            <pubDate>Fri, 11 Sep 2026 10:24:27 GMT</pubDate>
            <description><![CDATA[Um agente implementa a correção, outro revisa e um terceiro abre o app no navegador para percorrer o fluxo afetado. Parece uma automação bem organizada, até alguém perguntar qual commit p...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Um agente implementa a correção, outro revisa e um terceiro abre o app no navegador para percorrer o fluxo afetado. Parece uma automação bem organizada, até alguém perguntar qual commit passou por cada etapa.</p><p>O implementador escreveu "concluído" no chat e publicou uma branch. Enquanto o revisor lia o resumo, entrou mais um commit. O agente de QA abriu a branch que já estava no ambiente e encontrou tudo verde. No fim, implementação, revisão e teste podem ter usado três versões diferentes do código.</p><p>Nenhum prompt resolve essa confusão sozinho. O prompt explica o que uma etapa deve fazer; o protocolo entre etapas registra o artefato recebido, o resultado produzido e a condição que permite avançar.</p><p>Quando colocamos o segundo agente no fluxo, uma tarefa vira um pipeline e estado explícito deixa de ser detalhe de infraestrutura.</p><h2 id="centelha-content-o-segundo-agente-muda-a-natureza-do-trabalho">O segundo agente muda a natureza do trabalho</h2><p>Uma execução isolada pode receber contexto, alterar arquivos e devolver uma resposta. Se ela falhar, uma pessoa olha o resultado e decide o que fazer. Já uma cadeia com implementação, revisão e QA precisa coordenar espera, trabalho parcial, interrupção e retomada sem depender de alguém reinterpretar a conversa inteira.</p><p>O Cobalt 1.0 tornou esse desenho bem visível ao separar tarefas de implementação, revisão independente e testes no navegador. Cada tarefa mantém seu ambiente e histórico, enquanto o handoff de código usa branch, commit ou pull request. Os workers publicam resultados, inclusive falhas, e o fluxo pode parar em pontos definidos para uma decisão humana.</p><p>Não é necessário adotar essa ferramenta para aproveitar a ideia. Um time pequeno consegue aplicar o mesmo princípio em um script, uma GitHub Action ou um serviço interno. A regra é simples: uma etapa só começa quando consegue localizar e validar a saída exata da etapa anterior.</p><p>"O revisor recebeu a mensagem" não é uma condição de transição. "O revisor recebeu o commit <code>c94bd17</code>, derivado da base <code>8f31c2a</code>, com testes unitários e typecheck aprovados" já pode ser verificado.</p><h2 id="centelha-content-estado-precisa-comandar-comportamento">Estado precisa comandar comportamento</h2><p>O painel pode exibir vinte etiquetas e ainda assim não ter uma máquina de estados. Os nomes só ajudam quando cada um impõe regras ao runtime.</p><p>Eu começaria com poucos estados:</p><table><thead><tr><th>Estado</th><th>O que significa</th><th>Comportamento esperado</th></tr></thead><tbody><tr><td><code>queued</code></td><td>há uma entrada válida aguardando execução</td><td>reservar a tentativa e iniciar uma única vez</td></tr><tr><td><code>running</code></td><td>um worker assumiu a etapa</td><td>emitir atividade e respeitar o orçamento de tempo</td></tr><tr><td><code>blocked</code></td><td>falta permissão, dependência ou decisão</td><td>parar e encaminhar o bloqueio; não repetir automaticamente</td></tr><tr><td><code>failed</code></td><td>a etapa terminou com um resultado reprovado</td><td>registrar a classe da falha e devolver ao responsável</td></tr><tr><td><code>ready_for_review</code></td><td>existe uma saída identificada para revisão</td><td>liberar somente a etapa de review</td></tr><tr><td><code>approved</code></td><td>os checks exigidos passaram sobre uma referência exata</td><td>liberar a próxima etapa prevista para aquela referência</td></tr></tbody></table><p>As transições recusadas mostram se esses estados governam o processo. <code>failed</code> não pode escorregar para o QA porque algum campo do painel ficou verde. <code>approved</code> sem um hash deixa de ser aprovação e vira opinião. Se aparecer um commit novo, a revisão anterior continua registrada, mas não vale para a nova referência.</p><p>Também vale separar estágio de estado. <code>review</code> é uma fase do fluxo; <code>running</code>, <code>blocked</code> e <code>approved</code> descrevem a situação de uma tentativa naquela fase. Misturar os dois conceitos cria combinações difíceis de operar, como um genérico <code>review_done</code> que não informa se houve aprovação, reprovação ou interrupção.</p><h2 id="centelha-content-o-handoff-mínimo-cabe-em-um-arquivo-pequeno">O handoff mínimo cabe em um arquivo pequeno</h2><p>Não passe a transcrição do chat para o próximo agente e espere que ele descubra o que importa. Passe um registro curto, estruturado e apontando para os artefatos completos.</p><pre><code class="hljs language-yaml"><span class="hljs-attr">task_id:</span> <span class="hljs-string">checkout-form-42</span><span class="hljs-attr">attempt:</span> <span class="hljs-number">2</span><span class="hljs-attr">stage:</span> <span class="hljs-string">implement</span><span class="hljs-attr">status:</span> <span class="hljs-string">ready_for_review</span><span class="hljs-attr">input_ref:</span> <span class="hljs-string">8f31c2a</span><span class="hljs-attr">output_ref:</span> <span class="hljs-string">c94bd17</span><span class="hljs-attr">checks:</span>  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">unit</span>    <span class="hljs-attr">result:</span> <span class="hljs-string">passed</span>  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">typecheck</span>    <span class="hljs-attr">result:</span> <span class="hljs-string">passed</span><span class="hljs-attr">blocked_by:</span> <span class="hljs-literal">null</span><span class="hljs-attr">next_allowed:</span> <span class="hljs-string">review</span></code></pre><p>Esse YAML não torna o processo confiável por conta própria. O próximo worker precisa rejeitar o handoff quando falta uma referência, quando o estado não permite a etapa pedida ou quando um check obrigatório não aparece. O coordenador também precisa impedir duas execuções com o mesmo <code>task_id</code> e <code>attempt</code>.</p><p>O registro pode incluir horário, executor, riscos restantes e um endereço para logs detalhados. Evite colocar secrets, tokens ou a conversa completa ali. Handoff é uma interface entre etapas, não um depósito para tudo o que aconteceu na sessão.</p><h2 id="centelha-content-o-revisor-deve-validar-o-endereço-antes-do-código">O revisor deve validar o endereço antes do código</h2><p>Ao receber <code>output_ref: c94bd17</code>, o revisor busca esse commit e confirma que ele deriva da base esperada. Só depois abre o diff e roda os checks próprios da revisão. Se a branch avançar durante o processo, nada muda na referência já recebida.</p><p>Uma aprovação também deve carregar o commit revisado. O browser QA consome esse hash, prepara o app a partir dele e registra qual jornada executou. "Testei a branch" é ambíguo demais para servir de evidência porque branches se movem.</p><p>Esse cuidado evita uma falha comum em automações rápidas: cada agente faz seu trabalho corretamente sobre uma entrada diferente. O resultado local de cada etapa parece bom, mas a cadeia nunca validou um artefato único de ponta a ponta.</p><p>Um commit novo depois da revisão abre uma nova tentativa ou devolve o fluxo à fila. Não há motivo para apagar a aprovação anterior; ela continua útil para auditoria. O sistema apenas deixa de tratá-la como autorização para o código mais recente.</p><h2 id="centelha-content-cada-tipo-de-falha-pede-uma-resposta-diferente">Cada tipo de falha pede uma resposta diferente</h2><p>Retry automático é ótimo para uma queda transitória de rede e péssimo para uma operação que pode ter produzido efeito parcial. Antes de repetir, o coordenador precisa saber qual limite venceu, se o worker chegou a agir e se a operação tolera duplicidade.</p><p>O changelog do Cline SDK traz um caso concreto. Na versão 0.0.82, foi corrigida uma situação em que o timeout de 60 segundos de um servidor inacessível ultrapassava o teto de 30 segundos do hub e derrubava a sessão. Em uma cadeia, manda o menor orçamento de tempo. A etapa interna não pode prometer que esperará mais do que seu chamador suporta.</p><p>As classes de falha pedem respostas diferentes:</p><ul><li><code>blocked</code> espera uma permissão, dependência ou decisão humana;</li><li>um check reprovado volta ao implementador com o achado e a referência testada;</li><li>um timeout anterior ao início pode permitir nova tentativa;</li><li>um timeout com efeito desconhecido exige consulta ao recibo da operação ou uma chave de idempotência antes de repetir;</li><li>uma entrada obsoleta invalida a tentativa e recomeça a partir da referência atual.</li></ul><p>O teto de tentativas também deve ser explícito. Repetir cinco vezes o mesmo bloqueio não aumenta a chance de sucesso; só adia a pessoa que precisa decidir. Quando a mesma classe reaparece, o fluxo deve parar, chamar alguém e preservar o que já foi produzido.</p><p>Interrupção e retomada merecem o mesmo cuidado. A versão 0.0.72 do Cline SDK passou a preservar prompts enfileirados durante interrupções e a tornar a parada consistente entre hosts. Preservar a fila, porém, não autoriza reexecutar cegamente. Cada item retomado ainda precisa confirmar se o campo <code>input_ref</code> continua válido.</p><h2 id="centelha-content-log-durável-precisa-ter-limite-e-propósito">Log durável precisa ter limite e propósito</h2><p>Uma máquina de estados sem histórico ajuda pouco quando algo trava às três da manhã. Cada transição deveria deixar um evento com <code>task_id</code>, tentativa, estado anterior, novo estado, ator, referências e horário. O evento responde o que avançou e por quê; detalhes extensos podem ficar em um artefato separado, com acesso e retenção próprios.</p><p>Retenção infinita parece cômoda até snapshots, saídas de ferramentas e mensagens começarem a se acumular. O Cline SDK limitou seu event log durável a 64 MiB na versão 0.0.79 depois de snapshots completos crescerem muito mais. Copiar esse número para qualquer runtime não faria sentido. Vale definir limite, compactação e descarte antes de depender do log para retomar sessões.</p><p>Um log gigantesco também aumenta a chance de guardar segredos e dados desnecessários. Para operação diária, um recibo pequeno costuma bastar. Quando a etapa falha, ele aponta para os detalhes protegidos em vez de copiá-los para todos os agentes seguintes.</p><h2 id="centelha-content-validação-integrada-ajuda-mas-não-decide-sozinha">Validação integrada ajuda, mas não decide sozinha</h2><p>O Xcode 27 aproxima o agente de testes, experimentos em Playgrounds, previews e interação com simuladores pelo Device Hub. Esse tipo de integração encurta o ciclo entre mudar e observar. Também aumenta a importância de registrar qual build e qual estado do ambiente produziram a observação.</p><p>O agente que implementa pode rodar testes e encontrar boa parte dos próprios erros. Ainda assim, ele pode testar a mesma suposição errada que orientou a mudança. Para uma correção visual pequena, talvez o custo de uma revisão independente não compense. Em autenticação, cobrança ou migração de dados, separar produção e aprovação costuma ser um custo bem mais fácil de defender.</p><p>A decisão pode variar conforme o impacto. O contrato não precisa obrigar três agentes em todo PR; precisa deixar claro quando a checagem do próprio agente encerra a etapa e quando outra identidade deve revisar o mesmo commit.</p><h2 id="centelha-content-um-piloto-que-cabe-no-próximo-pr">Um piloto que cabe no próximo PR</h2><p>Escolha uma correção pequena de frontend e salve o estado em um arquivo versionado ou registro durável. Rode a sequência <code>implement</code> → <code>review</code> → <code>browser_qa</code> → <code>human_merge</code> uma vez antes de adicionar paralelismo ou mais papéis.</p><p>Durante o piloto, force situações que o happy path esconderia:</p><ul><li>faça um teste reprovar e confirme que o fluxo volta à implementação;</li><li>provoque um timeout e verifique se a tentativa seguinte consegue distinguir "não começou" de "resultado desconhecido";</li><li>adicione um commit depois da aprovação e confirme que revisão e QA antigos deixam de autorizar o merge;</li><li>remova uma permissão e veja se o estado termina em <code>blocked</code>, sem uma sequência inútil de retries.</li></ul><p>No fim, tente responder sem abrir o chat:</p><ul><li>qual commit cada etapa recebeu e qual devolveu?</li><li>quais checks rodaram sobre cada referência?</li><li>por que o fluxo avançou, parou ou voltou?</li><li>quem pode liberar a próxima transição?</li></ul><p>Se essas respostas estiverem no registro, o time já tem uma base útil. Depois vale medir quantas reexecuções foram evitadas, quanto tempo os bloqueios ficaram sem dono e quais eventos realmente ajudaram na investigação. A máquina de estados pode crescer quando surgir um caso operacional que justifique o novo estado.</p><p>Automatizar vários agentes sem esse contrato produz uma conversa movimentada e um histórico difícil de retomar. Comece com referências imutáveis, meia dúzia de estados e transições que o runtime saiba negar. Quando uma etapa falhar pela metade, o time poderá localizar o último commit válido, entender por que o fluxo parou e retomar sem reler a conversa.</p><h2 id="centelha-content-fontes">Fontes</h2><ul><li><a href="https://cobaltcode.ai/blog/cobalt-1-0" rel="nofollow">Cobalt 1.0</a></li><li><a href="https://github.com/cline/cline/blob/main/sdk/CHANGELOG.md">Cline SDK changelog</a></li><li><a href="https://www.apple.com/newsroom/2026/06/apple-aids-app-development-with-new-intelligence-frameworks-and-advanced-tools/" rel="nofollow">Apple: Xcode 27 e novas ferramentas de inteligência</a></li></ul></div>]]></content:encoded>
            <author>Centelha</author>
        </item>
        <item>
            <title><![CDATA[Pitch: Criei uma plataforma web gratuita de Matemática sendo estudante do Ensino Médio: bastidores, desafios e aprendizados]]></title>
            <link>https://www.tabnews.com.br/MateBasica/criei-uma-plataforma-gratuita-de-matematica-para-vestibulandos-sendo-estudante-do-ensino-medio-bastidores-desafios-e-aprendizados</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/MateBasica/criei-uma-plataforma-gratuita-de-matematica-para-vestibulandos-sendo-estudante-do-ensino-medio-bastidores-desafios-e-aprendizados</guid>
            <pubDate>Thu, 10 Sep 2026 23:16:48 GMT</pubDate>
            <description><![CDATA[Olá! Sou estudante do ensino médio e queria explorar a área de desenvolvimento web, então criei meu primeiro projeto: MateBásica (https://matebasica.com.br). Ele começou de forma desprete...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Olá! Sou estudante do ensino médio e queria explorar a área de desenvolvimento web, então criei meu primeiro projeto: MateBásica (<a href="https://matebasica.com.br" rel="nofollow">https://matebasica.com.br</a>). Ele começou de forma despretensiosa, apenas como um passatempo nas minhas últimas férias, mas no meio do processo enxerguei um potencial real de criar um auxílio acadêmico nacional, além de enxergar oportunidades pessoais na área de tecnologia.</p><p>Dediquei dezenas de horas desenvolvendo tudo individualmente, usando apenas recursos gratuitos. Criei a estrutura, o design, as funcionalidades principais, o ícone e comprei o domínio. Hoje, com um mês e meio de vida/maturação do site, quero compartilhar os bastidores de como ergui esse projeto e os desafios técnicos e operacionais que enfrentei.</p><h2 id="matebasica-content-inteligência-artificial-e-a-ilusão-do-trabalho-automatizado"><strong>Inteligência Artificial e a ilusão do "trabalho automatizado"</strong></h2><p>Usei IA para gerar partes dos textos e alguns elementos do site, mas quem acha que isso automatiza o projeto inteiro está bem enganado. A curadoria, organização, gestão, vínculos e a administração de todo o sistema foi um trabalho hercúleo. Cadastrar e revisar centenas de questões, artigos e formatar o banco de dados no meu próprio computador exigiu um esforço operacional árduo para garantir que o conteúdo realmente tivesse valor para um vestibulando.</p><h2 id="matebasica-content-a-stack-e-outros-desafios"><strong>A Stack e outros desafios</strong></h2><p>Na tentativa de manter o custo zero no início, utilizei o Cloudflare Pages para a hospedagem. É uma plataforma excelente, mas a construção do front-end trouxe desafios que me deram bastante problema:</p><ul><li><p>Conflitos de Renderização Matemática: A plataforma é focada em matemática, o que exige renderizar fórmulas complexas na tela. Integrar LaTeX/KaTeX com o HTML gerou diversos conflitos de formatação e quebras de layout que precisei consertar manualmente.</p></li><li><p>Mudança entre modelos de aplicação: Tive dificuldades estruturais para controlar estados e fazer a transição fluida entre diferentes páginas e componentes sem prejudicar/quebrar as funcionalidades, especialmente no gerador de PDFs e na interface de simulados.</p></li></ul><h2 id="matebasica-content-o-momento-atual"><strong>O momento atual</strong></h2><p>O site tem 51 dias no ar (no momento em que escrevo). O ecossistema está funcional, mas agora enfrento a fase mais difícil de qualquer projeto indie: a distribuição e a divulgação. Estou buscando expandir o acesso para validar a ferramenta com um público maior. O objetivo final é conseguir apoio e, possivelmente, algum retorno que viabilize e incentive a continuação do desenvolvimento, mantendo o ambiente limpo e gratuito para os estudantes.</p><p>Gostaria de convidar a comunidade do TabNews para testar a plataforma da forma como preferirem. Se a análise for técnica, deixo alguns questionamentos: Como está a performance do carregamento e a renderização do KaTeX nos diferentes navegadores que vocês usam? Encontraram algum gargalo/problema de usabilidade na geração dos PDFs (cuja variação para cada dispositivo e navegador tem me desafiado muito) ou na navegação dos simulados? Quais estratégias de distribuição inicial vocês recomendariam para um projeto focado em educação feito por um desenvolvedor solo?</p><p>Qualquer crítica honesta sobre a aparência do código, a UX ou a infraestrutura será recebida como aprendizado. Se gostarem e simplesmente quiserem usar e compartilhar, fico igualmente grato. Apesar de uma postagem com intuito descritivo e também de dúvidas, deixo aqui esse gancho para a divulgação e utilização do MateBásica! Obrigado pela leitura.</p></div>]]></content:encoded>
            <author>MateBasica</author>
        </item>
        <item>
            <title><![CDATA[SEO técnico ainda importa com IA? O que realmente mudou]]></title>
            <link>https://www.tabnews.com.br/GustavoAssis/seo-tecnico-ainda-importa-com-ia-o-que-realmente-mudou</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/GustavoAssis/seo-tecnico-ainda-importa-com-ia-o-que-realmente-mudou</guid>
            <pubDate>Thu, 10 Sep 2026 18:34:58 GMT</pubDate>
            <description><![CDATA[SEO técnico não morreu com a chegada da IA. Ele se tornou o filtro de entrada para qualquer disputa por visibilidade orgânica. A maioria dos artigos sobre o tema erra ao tratar SEO técnic...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>SEO técnico não morreu com a chegada da IA. Ele se tornou o filtro de entrada para qualquer disputa por visibilidade orgânica.</p><p>A maioria dos artigos sobre o tema erra ao tratar SEO técnico e conteúdo como estratégias separadas que competem entre si. Na prática, uma é pré-requisito da outra.</p><h2 id="gustavoassis-content-o-que-mudou-de-verdade">O que mudou de verdade</h2><p>A inteligência artificial mudou como o Google apresenta resultados. Os AI Overviews dominam o topo da SERP, a busca conversacional retém o usuário dentro do próprio Google e o conceito de "primeira posição" perdeu parte do significado que tinha.</p><p>Mas nada disso dispensou os fundamentos técnicos. O que mudou foi o custo de ignorá-los.</p><p>Se o Googlebot não consegue rastrear, indexar e interpretar o seu site com clareza, a IA do Google não vai citá-lo como fonte. E sem ser citado nos AI Overviews, o site fica invisível para uma fatia crescente das buscas informacionais, que já superam 40% do volume total de consultas respondidas diretamente na SERP.</p><h2 id="gustavoassis-content-duas-camadas-de-competição-simultâneas">Duas camadas de competição simultâneas</h2><p>Agora existem duas disputas acontecendo ao mesmo tempo:</p><ol><li>A tradicional: aparecer nos resultados orgânicos com boa posição</li><li>A nova: ser selecionado como fonte confiável para compor os resumos gerados por IA</li></ol><p>Para passar pelas duas, a base técnica precisa estar resolvida.</p><p>A própria Ahrefs, em um estudo com 331 mil páginas analisadas, concluiu que o Google não pune conteúdos gerados por IA. O que realmente impacta o desempenho é a qualidade do conteúdo. Mas esse julgamento de qualidade pressupõe que o conteúdo foi rastreado e interpretado corretamente. Se a infraestrutura técnica falha antes disso, o julgamento nunca acontece.</p><h2 id="gustavoassis-content-o-que-mudou-nos-fatores-técnicos-específicos">O que mudou nos fatores técnicos específicos</h2><h3 id="gustavoassis-content-dados-estruturados-deixaram-de-ser-recomendação-e-viraram-requisito">Dados estruturados deixaram de ser recomendação e viraram requisito</h3><p>Schema Markup sempre foi recomendado como boa prática. Em um cenário dominado por IA generativa, ele passou a funcionar como um guia de leitura que a IA usa para entender o tipo, o contexto e a relevância do conteúdo antes de decidir se vai citá-lo.</p><p>Uma página com Schema de FAQ implementado corretamente sinaliza para a IA que aquele bloco foi estruturado para responder perguntas específicas. Uma página sem nenhum markup deixa a IA inferindo tudo a partir do texto bruto, reduzindo a precisão da interpretação e a probabilidade de citação.</p><p>Os schemas mais relevantes para aumentar a chance de citação nos AI Overviews: FAQ, HowTo, Article, Review, BreadcrumbList, Product e Event.</p><h3 id="gustavoassis-content-arquitetura-de-informação-dentro-da-página-ganhou-peso-técnico">Arquitetura de informação dentro da página ganhou peso técnico</h3><p>Esse ponto raramente aparece nas listas de SEO técnico, mas passou a ter impacto direto na era dos AI Overviews.</p><p>Parágrafos que respondem a uma pergunta de forma autossuficiente em 40 a 60 palavras têm estrutura ideal para extração pela IA. Headings em H2 e H3 que funcionam como perguntas reais que o usuário faria criam pontos de ancoragem que o sistema usa para selecionar trechos relevantes.</p><p>Isso não é apenas decisão editorial. É uma decisão técnica sobre como o HTML da página está organizado e como o fluxo de informação está sendo comunicado ao parser do Googlebot.</p><h3 id="gustavoassis-content-rastreabilidade-e-crawl-budget-ficaram-mais-críticos">Rastreabilidade e crawl budget ficaram mais críticos</h3><p>Com a IA generativa precisando processar e atualizar fontes com mais frequência, o Google precisa rastrear sites com maior regularidade. Sites com arquitetura confusa, links quebrados, redirecionamentos em cadeia ou páginas duplicadas sem canonical consomem crawl budget desnecessariamente e atrasam o processamento das páginas estratégicas.</p><h2 id="gustavoassis-content-o-que-o-google-continua-exigindo-sem-mudança">O que o Google continua exigindo sem mudança</h2><p>Alguns fundamentos são estruturalmente imunes às mudanças trazidas pela IA:</p><p><strong>Core Web Vitals</strong> — LCP abaixo de 2,5 segundos, CLS abaixo de 0,1 e FID abaixo de 100ms continuam sendo métricas de ranqueamento ativas.</p><p><strong>Mobile-First Indexing</strong> — conteúdo que aparece completo no desktop mas está truncado ou inacessível no mobile pode não ser indexado corretamente.</p><p><strong>HTTPS e integridade do ambiente</strong> — a IA do Google tende a evitar citar fontes com histórico de problemas de segurança.</p><p><strong>Canonical tags</strong> — páginas duplicadas sem canonical correto dividem autoridade e criam ambiguidade para o Googlebot.</p><p><strong>Sitemap XML e Robots.txt</strong> — erros aqui têm consequências que se propagam por toda a indexação do site.</p><h2 id="gustavoassis-content-a-intersecção-entre-técnico-e-conteúdo-citável">A intersecção entre técnico e conteúdo citável</h2><p>O erro mais comum em estratégias de SEO é tratar técnico e conteúdo como silos separados. Em um cenário dominado por AI Overviews, essa separação é insustentável.</p><p>Um artigo tecnicamente perfeito com conteúdo genérico não vai ser citado. Um artigo com conteúdo original e profundo em um site com problemas técnicos também não vai ser citado. Os dois precisam estar resolvidos ao mesmo tempo.</p><p>Sites que combinam infraestrutura técnica sólida com conteúdo estruturado de forma citável estão capturando espaço que concorrentes com apenas uma das duas partes funcionando estão deixando vago.</p><h2 id="gustavoassis-content-por-onde-começar">Por onde começar</h2><p>O ponto de partida é o Google Search Console. Os relatórios de cobertura, Core Web Vitals e dados estruturados já entregam um diagnóstico inicial sem nenhuma ferramenta adicional. A partir dali, Screaming Frog, Ahrefs e PageSpeed Insights aprofundam a análise nas camadas que o Search Console não cobre com granularidade suficiente.</p><p>A auditoria sozinha não resolve nada. O que gera resultado é a priorização e a execução das correções certas na ordem certa: primeiro os problemas que mais impactam rastreamento e indexação, depois performance, depois dados estruturados.</p><hr><p>Artigo publicado originalmente em <a href="https://user.dev.br/blog/seo-tecnico-ainda-importa-com-ia/" rel="nofollow">user.dev.br</a></p></div>]]></content:encoded>
            <author>GustavoAssis</author>
        </item>
        <item>
            <title><![CDATA[Pitch: De macOS para o Windows sem estresse: Como criei um remapeador leve e o publiquei na Microsoft Store via GitHub Actions]]></title>
            <link>https://www.tabnews.com.br/klewersina/de-macos-para-o-windows-sem-estresse-como-criei-um-remapeador-leve-e-o-publiquei-na-microsoft-store-via-github-actions</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/klewersina/de-macos-para-o-windows-sem-estresse-como-criei-um-remapeador-leve-e-o-publiquei-na-microsoft-store-via-github-actions</guid>
            <pubDate>Thu, 10 Sep 2026 18:24:39 GMT</pubDate>
            <description><![CDATA[Página do App na Microsoft Store: CtrlAltRemapper (Microsoft Store) Se você alterna frequentemente entre o macOS e o Windows no seu dia a dia, com certeza já passou por essa "dor". No Mac...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p><strong>Página do App na Microsoft Store:</strong> <a href="https://apps.microsoft.com/detail/9N3VZ7JXZW28" rel="nofollow">CtrlAltRemapper (Microsoft Store)</a></p><p>Se você alterna frequentemente entre o macOS e o Windows no seu dia a dia, com certeza já passou por essa "dor". No MacBook em casa você usa o Cmd, mas no trabalho senta em frente a um PC com Windows (ou vice-versa) — e a sua memória muscular entra em colapso total. Ao tentar copiar um texto, o polegar vai automaticamente para a tecla Alt (que no teclado do PC fica na mesma posição física do Cmd no Mac), e o resultado é o menu do aplicativo sendo ativado ou nenhuma resposta...</p><p>Tentei algumas ferramentas de remapeamento existentes, mas nenhuma me satisfez. Ou a variedade de atalhos era extremamente limitada, ou exigia configurações manuais e tediosas para cada atalho.</p><h3 id="klewersina-content-objetivos-do-projeto">Objetivos do Projeto</h3><p>Eu queria resolver esse problema com um aplicativo leve e sem interface gráfica (GUI). O objetivo era um simples <strong>"execute uma vez e esqueça"</strong>, sem necessidade de ajustes constantes.</p><ul><li><strong>Sem GUI pesada:</strong> O aplicativo roda silenciosamente na bandeja do sistema (System Tray).</li><li><strong>Consumo mínimo de recursos do sistema.</strong></li><li><strong>Privacidade total:</strong> Funciona 100% local e offline, sem coletar ou enviar digitações.</li><li><strong>Integração nativa com Windows 10 / 11:</strong> Formato de pacote MSIX com suporte à inicialização automática junto com o sistema.</li></ul><p>E assim nasceu o projeto <strong>CtrlAltRemapper</strong>.</p><hr><h3 id="klewersina-content-etapa-de-compilação-da-arquitetura-x86-para-x64-nativo">Etapa de Compilação: Da arquitetura x86 para x64 nativo</h3><p>O código do remapeador foi escrito em AutoHotkey. Para converter o script em um executável standalone (.exe), utilizei o compilador padrão <strong>Ahk2Exe</strong>.</p><p>A primeira compilação foi simples. Inicialmente, optei por compilar em 32-bit (x86) pensando na compatibilidade. Porém, durante os testes, descobri que essa escolha gerava problemas no Windows 11 de 64 bits: executar hooks de teclado de 32 bits dentro de aplicativos nativos de 64 bits (como o novo Bloco de Notas) gerava uma <strong>micro-latência por causa do marshalling na camada WoW64</strong>. O Windows interpretava esse atraso mínimo como um travamento e desativava o hook global.</p><p>Após identificar a causa, recompilai o aplicativo para a arquitetura nativa <strong>x64</strong>, o que resolveu completamente o problema de desempenho dos hooks.</p><hr><h3 id="klewersina-content-tabela-de-atalhos-suportados">Tabela de Atalhos Suportados</h3><p>O aplicativo traz a lógica e o layout de teclas da Apple para o ecossistema do Windows. Confira a lista completa de atalhos remapeados:</p><table><thead><tr><th align="left">Tecla no PC</th><th align="left">Função (Estilo Mac)</th></tr></thead><tbody><tr><td align="left"><strong>Atalhos Básicos (Basic Shortcuts)</strong></td><td align="left"></td></tr><tr><td align="left"><strong>Alt + A</strong></td><td align="left">Selecionar tudo</td></tr><tr><td align="left"><strong>Alt + C</strong></td><td align="left">Copiar</td></tr><tr><td align="left"><strong>Alt + V</strong></td><td align="left">Colar</td></tr><tr><td align="left"><strong>Alt + X</strong></td><td align="left">Recortar</td></tr><tr><td align="left"><strong>Alt + Z</strong></td><td align="left">Desfazer</td></tr><tr><td align="left"><strong>Alt + Y</strong></td><td align="left">Refazer</td></tr><tr><td align="left"><strong>Alt + S</strong></td><td align="left">Salvar</td></tr><tr><td align="left"><strong>Alt + F</strong></td><td align="left">Localizar / Buscar</td></tr><tr><td align="left"><strong>Alt + P</strong></td><td align="left">Imprimir</td></tr><tr><td align="left"><strong>Formatação de Texto (Text Formatting)</strong></td><td align="left"></td></tr><tr><td align="left"><strong>Alt + B</strong></td><td align="left">Negrito</td></tr><tr><td align="left"><strong>Alt + I</strong></td><td align="left">Itálico</td></tr><tr><td align="left"><strong>Alt + U</strong></td><td align="left">Sublinhado</td></tr><tr><td align="left"><strong>Alt + Shift + V</strong></td><td align="left">Colar sem formatação (texto simples)</td></tr><tr><td align="left"><strong>Alt + K</strong></td><td align="left">Inserir hiperlink</td></tr><tr><td align="left"><strong>Navegador e Gerenciamento de Janelas (Browser &#x26; Window)</strong></td><td align="left"></td></tr><tr><td align="left"><strong>Alt + Q</strong></td><td align="left">Fechar aplicativo</td></tr><tr><td align="left"><strong>Alt + H</strong></td><td align="left">Ocultar janela ativa</td></tr><tr><td align="left"><strong>Alt + W</strong></td><td align="left">Fechar janela ou aba</td></tr><tr><td align="left"><strong>Alt + N</strong></td><td align="left">Novo arquivo ou janela</td></tr><tr><td align="left"><strong>Alt + O</strong></td><td align="left">Abrir arquivo</td></tr><tr><td align="left"><strong>Alt + R</strong></td><td align="left">Recarregar página</td></tr><tr><td align="left"><strong>Alt + -</strong></td><td align="left">Diminuir zoom</td></tr><tr><td align="left"><strong>Alt + +</strong></td><td align="left">Aumentar zoom</td></tr><tr><td align="left"><strong>Alt + 0</strong></td><td align="left">Redefinir zoom</td></tr><tr><td align="left"><strong>Alt + T</strong></td><td align="left">Nova aba ou documento</td></tr><tr><td align="left"><strong>Alt + Shift + T</strong></td><td align="left">Reabrir aba fechada</td></tr><tr><td align="left"><strong>Alt + Clique Esquerdo</strong></td><td align="left">Abrir link em nova aba / Mudar foco</td></tr><tr><td align="left"><strong>Sistema e Navegação (System &#x26; Navigation)</strong></td><td align="left"></td></tr><tr><td align="left"><strong>Alt + Espaço</strong></td><td align="left">Alternar idioma de entrada (emula ⌘ + Espaço)</td></tr><tr><td align="left"><strong>Alt + Backspace</strong></td><td align="left">Excluir caractere à direita (Forward Delete)</td></tr><tr><td align="left"><strong>Alt + D</strong></td><td align="left">Adicionar aos favoritos / Excluir linha</td></tr></tbody></table><p>Vale destacar que o comportamento nativo da tecla <strong>Ctrl</strong> permanece 100% intocado, permitindo usar ambos os estilos de atalho em paralelo.</p><hr><h3 id="klewersina-content-automação-de-build-msix-via-github-actions">Automação de Build MSIX via GitHub Actions</h3><p>Gerar o formato moderno de pacote do Windows (MSIX) pode ser desafiador, especialmente ao criar pipelines de CI/CD automatizados. Estruturei o pipeline criando dois workflows independentes no GitHub Actions:</p><ol><li><strong>Workflow de Produção (<code>build.yml</code>)</strong>: Empacota o executável e recursos em um pacote <code>.msix</code> limpo e não assinado. Ele é enviado diretamente ao Microsoft Partner Center e assinado automaticamente com o certificado oficial e confiável da loja durante a publicação.</li><li><strong>Workflow de Teste (<code>test-sign.yml</code>)</strong>: Criado para testes locais. O script gera um certificado autoassinado em tempo de execução, exporta em formato <code>.pfx</code> e assina o pacote de teste usando a ferramenta <code>signtool.exe</code>.</li></ol><p>Abaixo está o arquivo de configuração YAML do robot de teste, projetado para localizar dinamicamente as ferramentas do Windows SDK no runner do GitHub:</p><pre><code class="hljs language-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Test-Sign</span> <span class="hljs-string">MSIX</span> <span class="hljs-string">Package</span><span class="hljs-attr">on:</span>  <span class="hljs-attr">workflow_dispatch:</span><span class="hljs-attr">jobs:</span>  <span class="hljs-attr">pack-and-sign:</span>    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">windows-latest</span>    <span class="hljs-attr">steps:</span>    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">code</span>      <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v4</span>    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Find</span> <span class="hljs-string">Windows</span> <span class="hljs-string">SDK</span> <span class="hljs-string">Tools</span>      <span class="hljs-attr">shell:</span> <span class="hljs-string">pwsh</span>      <span class="hljs-attr">id:</span> <span class="hljs-string">tools</span>      <span class="hljs-attr">run:</span> <span class="hljs-string">|        $makeappx = Get-ChildItem -Path "C:\Program Files (x86)\Windows Kits\10\bin" -Filter "makeappx.exe" -Recurse | Where-Object { $_.FullName -like "*x64*" } | Select-Object -First 1 -ExpandProperty FullName        $signtool = Get-ChildItem -Path "C:\Program Files (x86)\Windows Kits\10\bin" -Filter "signtool.exe" -Recurse | Where-Object { $_.FullName -like "*x64*" } | Select-Object -First 1 -ExpandProperty FullName        echo "MAKEAPPX_PATH=$makeappx" >> $env:GITHUB_ENV        echo "SIGNTOOL_PATH=$signtool" >> $env:GITHUB_ENV</span>    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Pack</span> <span class="hljs-string">MSIX</span>      <span class="hljs-attr">shell:</span> <span class="hljs-string">pwsh</span>      <span class="hljs-attr">run:</span> <span class="hljs-string">|        &#x26; "$env:MAKEAPPX_PATH" pack /d . /p CtrlAltRemapper_unsigned.msix /v</span>    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Create</span> <span class="hljs-string">Test</span> <span class="hljs-string">Certificate</span> <span class="hljs-string">and</span> <span class="hljs-string">Sign</span>      <span class="hljs-attr">shell:</span> <span class="hljs-string">pwsh</span>      <span class="hljs-attr">run:</span> <span class="hljs-string">|        $password = ConvertTo-SecureString "TestPassword123" -AsPlainText -Force        $cert = New-SelfSignedCertificate -Type Custom -Subject "CN=BD6FFC77-0FDF-42B7-95A8-73C66D341EDE" -KeyUsage DigitalSignature -FriendlyName "TestCert" -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3")        Export-PfxCertificate -Cert $cert -FilePath "testcert.pfx" -Password $password        &#x26; "$env:SIGNTOOL_PATH" sign /fd SHA256 /a /f "testcert.pfx" /p "TestPassword123" CtrlAltRemapper_unsigned.msix        Move-Item -Path CtrlAltRemapper_unsigned.msix -Destination CtrlAltRemapper_Signed.msix</span>    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Upload</span> <span class="hljs-string">Signed</span> <span class="hljs-string">MSIX</span> <span class="hljs-string">and</span> <span class="hljs-string">Certificate</span>      <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/upload-artifact@v4</span>      <span class="hljs-attr">with:</span>        <span class="hljs-attr">name:</span> <span class="hljs-string">CtrlAltRemapper-TestSign-Package</span>        <span class="hljs-attr">path:</span> <span class="hljs-string">|          CtrlAltRemapper_Signed.msix          testcert.pfx</span></code></pre><hr><h3 id="klewersina-content-desafios-na-certificação-da-microsoft-store">Desafios na Certificação da Microsoft Store</h3><p>Publicar um remapeador de teclas que opera em nível de sistema na Microsoft Store exigiu superar várias restrições rígidas de segurança do Windows 10/11.</p><h4 id="klewersina-content-1-declaração-de-runfulltrust">1. Declaração de <code>runFullTrust</code></h4><p>Como o app intercepta atalhos usando a API Win32 de baixo nível (<code>SetWindowsHookEx</code>), a sandbox padrão do UWP bloqueava a execução. Foi necessário declarar a capacidade restrita <strong><code>runFullTrust</code></strong> no <code>AppxManifest.xml</code>. Durante o envio, fornecemos uma justificativa técnica detalhada sobre a segurança da utilidade e a necessidade do acesso.</p><h4 id="klewersina-content-2-exigência-de-headlessappbypass-e-suporte-da-microsoft">2. Exigência de <code>HeadlessAppBypass</code> e suporte da Microsoft</h4><p>No primeiro envio, enfrentamos uma rejeição automática. Como o app roda apenas na bandeja do sistema sem uma janela principal de GUI, o Windows SDK o identificou como um "headless app". As políticas da Microsoft exigiam vincular a permissão <strong><code>HeadlessAppBypass</code></strong> ao nosso <strong>Store ID</strong>.</p><p>Após contato com a equipe de suporte do Microsoft Partner Center explicando a natureza do app, o acesso foi liberado manualmente para a conta de desenvolvedor.</p><h4 id="klewersina-content-3-depuração-no-ambiente-de-certificação-erro-de-vcruntime140dll-e-máscaras-de-alt">3. Depuração no ambiente de certificação (Erro de <code>VCRUNTIME140.dll</code> e máscaras de Alt)</h4><p>Nos testes automatizados em ambiente limpo da Microsoft, o app apresentou falhas devido à ausência da DLL do sistema <code>VCRUNTIME140.dll</code>.<br>Para resolver as pendências de certificação:</p><ul><li>Recompilamos e ajustamos o manifesto para a arquitetura <strong>x64 nativa</strong> (<code>ProcessorArchitecture="x64"</code>).</li><li>Adicionamos a nota sobre requisitos de sistema nos <strong>listings da loja em 8 idiomas</strong>.</li><li>Implementamos uma máscara ativa (<code>vkFF/vkE8</code>) para a tecla Alt, evitando que o Windows transferisse o foco para a barra de menus ao alternar atalhos rapidamente.</li></ul><hr><h3 id="klewersina-content-considerações-finais">Considerações Finais</h3><p>O desenvolvimento do CtrlAltRemapper provou que é possível levar um projeto indie focado em produtividade a um pacote de nível enterprise na Microsoft Store.</p><p>O aplicativo está disponível gratuitamente para testes no link abaixo:</p><p><strong>Download na Microsoft Store:</strong> <a href="https://apps.microsoft.com/detail/9N3VZ7JXZW28" rel="nofollow">CtrlAltRemapper (Microsoft Store)</a></p><p>Feedbacks, relatos de bugs e sugestões de novos atalhos são muito bem-vindos nos comentários!</p><p>#Engenharia de Software #Produtividade #Windows #MacOS</p></div>]]></content:encoded>
            <author>klewersina</author>
        </item>
        <item>
            <title><![CDATA[Shopify está saindo do React Native de volta para o Nativo (Swift e Kotlin)]]></title>
            <link>https://www.tabnews.com.br/rafael/shopify-esta-saindo-do-react-native-de-volta-para-o-nativo-swift-e-kotlin</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/rafael/shopify-esta-saindo-do-react-native-de-volta-para-o-nativo-swift-e-kotlin</guid>
            <pubDate>Thu, 10 Sep 2026 17:42:40 GMT</pubDate>
            <description><![CDATA[A Shopify usa o React Native desde 2020, e muita coisa mudou desde então. Conforme a declaração no blog deles: "agentes de codificação mudaram o custo de desenvolvimento de aplicativos mó...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>A Shopify usa o React Native desde 2020, e muita coisa mudou desde então. Conforme a <a href="https://shopify.engineering/back-to-native" rel="nofollow">declaração no blog deles</a>: <em>"agentes de codificação mudaram o custo de desenvolvimento de aplicativos móveis em dobro"</em>, e resolveram sair do React Native para usar diretamente Swift e Kotlin.</p><p>O post tem vários detalhes, e a declaração acima não foi uma surpresa pra mim (na verdade é óbvio, já vimos outros casos como o <a href="https://www.tabnews.com.br/NewsletterOficial/bun-lanca-versao-1-4-reescrito-completamente-em-rust">Bun reescrito em Rust</a>), mas tem algumas coisas que chamaram minha atenção, como o que a Shopify chamou de Helix.</p><blockquote><p>O desenvolvedor aponta o Helix para uma tela. O Helix lê o código React Native e propõe uma sequência de checkpoints (pequenos segmentos ordenados do trabalho) que podem ser revisados​em minutos. Em seguida, avança checkpoint a checkpoint: cada um deve comprovar seu comportamento por meio de testes, corresponder ao aplicativo em execução em uma revisão visual, passar pelo crivo de dois revisores de código (atuando de forma crítica) e receber a aprovação humana antes de ser consolidado (commit) e de o próximo passo começar. O feedback de cada revisão é armazenado, tornando o processo mais autônomo à medida que a migração avança.</p></blockquote><p><img src="https://i.imgur.com/ThquCn2.gif" alt="Desenvolvimento com o Helix: duas telas de celular lado a lado"></p><p>Tem outros pontos interessantes no artigo.</p><p>Assim como uma grande empresa usar um framework/biblioteca é bom para essa ferramenta, deixar de usá-la pode ser ruim. No post tem três exemplos de bibliotecas que a Shopify desenvolvia/apoiava e o que vai acontecer com elas. Talvez outras empresas sigam o sinal e saíam de React Native e Flutter também.</p><p>Vale destacar, a IA ainda não roubou todos os empregos:</p><blockquote><p>Se você quer ajudar a construir a próxima geração de aplicativos móveis da Shopify, estamos <a href="https://www.shopify.com/careers" rel="nofollow">contratando</a> engenheiros mobile, engenheiros de infraestrutura e desenvolvedores que atuam na intersecção entre IA e engenharia de software.</p></blockquote></div>]]></content:encoded>
            <author>rafael</author>
        </item>
        <item>
            <title><![CDATA[Pitch: Cansei de descobrir na marra que tinha estourado a cota da IA, então construí um "mostrador" pra mesa]]></title>
            <link>https://www.tabnews.com.br/trindadebra/cansei-de-descobrir-na-marra-que-tinha-estourado-a-cota-da-ia-entao-construi-um-mostrador-pra-mesa</link>
            <guid isPermaLink="false">https://www.tabnews.com.br/trindadebra/cansei-de-descobrir-na-marra-que-tinha-estourado-a-cota-da-ia-entao-construi-um-mostrador-pra-mesa</guid>
            <pubDate>Thu, 10 Sep 2026 15:29:39 GMT</pubDate>
            <description><![CDATA[Uso várias ferramentas de IA no dia a dia — Claude, ChatGPT, Cursor, e mais um punhado de outras. Cada uma tem seu próprio limite de uso, que reseta em horários diferentes, e nenhuma dela...]]></description>
            <content:encoded><![CDATA[<div class="markdown-body"><p>Uso várias ferramentas de IA no dia a dia — Claude, ChatGPT, Cursor, e mais um punhado de outras. Cada uma tem seu próprio limite de uso, que reseta em horários diferentes, e nenhuma delas avisa direito quando você está chegando perto do teto. O jeito que eu ficava sabendo que tinha estourado era o pior possível: no meio de uma tarefa, quando a ferramenta simplesmente parava de responder.</p><p>Cansei disso e resolvi criar o <strong>Vigia AI</strong>: um mostrador que fica sempre ligado na mesa, mostrando o quanto eu já usei de cada conta, sem precisar abrir aba nenhuma nem ficar caçando essa informação escondida em cada app.</p><p><img src="https://github.com/TrindadeBRA/vigia-ai/raw/main/.agents/assets/firmware/hardware-desk.jpg" alt="Mostrador físico na mesa, mostrando o consumo de cada conta"></p><h2 id="trindadebra-content-a-ideia">A ideia</h2><p>É bem simples: em vez de descobrir o estouro na hora H, eu já vejo o consumo subindo ao longo do dia, de relance, como quem olha pra um relógio. Dá pra planejar melhor quando usar cada ferramenta, ou simplesmente parar de levar susto.</p><h2 id="trindadebra-content-como-ficou">Como ficou</h2><p>O projeto cresceu mais do que eu esperava. Hoje ele roda de três formas:</p><ul><li>Um aparelhinho físico, do tamanho de um despertador, com uma telinha touch — fica ali na mesa, sempre ligado.</li><li>Uma versão que roda direto no navegador, pra quem não quer (ou não tem) o aparelho físico.</li><li>Um programa pra instalar no computador (Windows, Mac ou Linux).</li></ul><p><img src="https://raw.githubusercontent.com/TrindadeBRA/vigia-ai/main/.agents/assets/web/web-overview.png" alt="Versão web do painel, rodando no navegador"></p><p>Ele acompanha hoje umas 10 ferramentas diferentes (Claude, ChatGPT, Cursor, OpenRouter, DeepSeek, entre outras), aceita várias contas ao mesmo tempo, e ainda manda um aviso no Telegram quando alguma cota está perto de acabar. Também dá pra deixar do jeito que quiser: temas, cores, papel de parede.</p><p><img src="https://raw.githubusercontent.com/TrindadeBRA/vigia-ai/main/.agents/assets/firmware/display-theme-custom.png" alt="Personalização de tema, com fundo e ícones escolhidos por você"></p><p>Uma preocupação que tive desde o início foi com segurança: o painel só enxerga porcentagens e datas — nunca as senhas ou tokens de acesso das suas contas. Isso fica só no seu computador, do mesmo jeito que já ficava antes.</p><h2 id="trindadebra-content-é-de-graça-e-é-aberto">É de graça e é aberto</h2><p>O projeto é open source, gratuito, e está todo publicado no GitHub:</p><p><strong><a href="https://github.com/TrindadeBRA/vigia-ai">https://github.com/TrindadeBRA/vigia-ai</a></strong></p><p>Lá tem instruções de como usar só a parte web (sem precisar montar nada) e também como montar a versão física, se você curtir eletrônica. Se você também vive nesse rolo de usar várias IAs e já levou esse tipo de susto, dá uma conferida — e qualquer sugestão ou contribuição é super bem-vinda.</p></div>]]></content:encoded>
            <author>trindadebra</author>
        </item>
    </channel>
</rss>