<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Lady{de}bug – Lady{de}bug</title><link>https://deploy-preview-17--ladydebug.netlify.app/</link><description>Recent content on Lady{de}bug</description><generator>Hugo -- gohugo.io</generator><language>pt-BR</language><lastBuildDate>Thu, 27 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://deploy-preview-17--ladydebug.netlify.app/index.xml" rel="self" type="application/rss+xml"/><item><title>Linux Básico</title><link>https://deploy-preview-17--ladydebug.netlify.app/docs/2025/dezembro/linux-basico/</link><pubDate>Mon, 01 Dec 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-17--ladydebug.netlify.app/docs/2025/dezembro/linux-basico/</guid><description>
&lt;h2>Minhas anotações sobre o básicos do Linux&lt;span class="hx:absolute hx:-mt-20" id="minhas-anotações-sobre-o-básicos-do-linux">&lt;/span>
&lt;a href="#minhas-anota%c3%a7%c3%b5es-sobre-o-b%c3%a1sicos-do-linux" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h2></description></item><item><title>Configurando o SonarQube Localmente</title><link>https://deploy-preview-17--ladydebug.netlify.app/docs/2025/setembro/20/configurando-o-sonar-qube-localmente/</link><pubDate>Sat, 20 Sep 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-17--ladydebug.netlify.app/docs/2025/setembro/20/configurando-o-sonar-qube-localmente/</guid><description>
&lt;p>&lt;strong>Isso não é um tutorial,&lt;/strong> é mais para o entendimento e estudo sobre a ferramenta e como aplicar ela em projetos pequenos, até médio porte, em repositórios fechados (código privado). Bom, como eu já tinha o SonarQube instalado na minha máquina, abaixo segue como configurar o Docker.&lt;/p>
&lt;hr>
&lt;h2>&lt;strong>Opção 1: Remover o container existente&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="opção-1-remover-o-container-existente">&lt;/span>
&lt;a href="#op%c3%a7%c3%a3o-1-remover-o-container-existente" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h2>&lt;p>Para um trabalho de Pós-graduação eu tinha configurado para um projeto de estudo de análise de código, neste caso foi reconfigurar para outro projeto (depois eu configuro novamente correto para o projeto de estudo de análise de código).&lt;/p>
&lt;p>&lt;code>docker rm sonarqube&lt;/code>&lt;/p>
&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2025/setembro/20/configurando-o-sonar-qube-localmente/image1.png" alt="image1.png" loading="lazy" />&lt;/p>
&lt;p>Agora posso executar o comando para subir um novo container:&lt;/p>
&lt;p>&lt;code>docker run -d --name sonarqube -p 9000:9000 sonarqube:lts-community&lt;/code>&lt;/p>
&lt;blockquote>
&lt;p>Sim, a versão é gratuíta, para aprendizado antes de sair pagando algo que não sabe usar.&lt;/p>
&lt;/blockquote>
&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2025/setembro/20/configurando-o-sonar-qube-localmente/image2.png" alt="image2.png" loading="lazy" />&lt;/p>
&lt;h3>&lt;strong>Opção 2: Substituir o container automaticamente&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="opção-2-substituir-o-container-automaticamente">&lt;/span>
&lt;a href="#op%c3%a7%c3%a3o-2-substituir-o-container-automaticamente" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;p>Se quiser forçar a substituição, use o parâmetro &amp;ndash;rm (remove ao parar) ou &amp;ndash;replace (caso use Podman). No Docker, geralmente removemos manualmente como acima.&lt;/p>
&lt;h3>&lt;strong>Opção 3: Verificar o status do container&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="opção-3-verificar-o-status-do-container">&lt;/span>
&lt;a href="#op%c3%a7%c3%a3o-3-verificar-o-status-do-container" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;p>&lt;code>docker start sonarqube&lt;/code>&lt;/p>
&lt;p>Para encerrar use o comando:&lt;/p>
&lt;p>&lt;code>docker stop sonarqube&lt;/code>&lt;/p>
&lt;h2>&lt;strong>Executar o SonarQube localmente&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="executar-o-sonarqube-localmente">&lt;/span>
&lt;a href="#executar-o-sonarqube-localmente" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h2>&lt;p>Agora a parte que interessa é configurar localmente o SonarQube, e fazer um escaneamento básico.&lt;/p>
&lt;p>Primeiro um setup de configuração (acho que vale adicionar isso no script de desenvolvimento).&lt;/p>
&lt;h3>&lt;strong>1. Pré-requisitos&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="1-pré-requisitos">&lt;/span>
&lt;a href="#1-pr%c3%a9-requisitos" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;ul>
&lt;li>&lt;strong>Java 11 ou superior&lt;/strong> instalado na máquina (SonarQube precisa do Java para rodar).&lt;/li>
&lt;li>&lt;strong>Docker&lt;/strong> (opcional, mas facilita a execução do SonarQube — realmente).&lt;/li>
&lt;/ul>
&lt;h3>&lt;strong>2. Baixando e rodando o SonarQube&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="2-baixando-e-rodando-o-sonarqube">&lt;/span>
&lt;a href="#2-baixando-e-rodando-o-sonarqube" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;p>Link de download: &lt;a href="https://www.sonarsource.com/open-source-editions/sonarqube-community-edition/"target="_blank" rel="noopener">https://www.sonarsource.com/open-source-editions/sonarqube-community-edition/&lt;/a>&lt;/p>
&lt;p>Aqui a primeira parte de ajustar o docker então precisa se atentar a deixar ele executando, corretamente, sem problemas.&lt;/p>
&lt;p>&lt;code>docker run -d --name sonarqube -p 9000:9000 sonarqube:lts-community&lt;/code>&lt;/p>
&lt;p>Pronto! SonarQube rodando localmente.&lt;/p>
&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2025/setembro/20/configurando-o-sonar-qube-localmente/image3.png" alt="image3.png" loading="lazy" />&lt;/p>
&lt;p>Ajuste as configurações de senha e segue para a página:&lt;/p>
&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2025/setembro/20/configurando-o-sonar-qube-localmente/image4.png" alt="image4.png" loading="lazy" />&lt;/p>
&lt;h3>&lt;strong>Configuração do SonarQube&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="configuração-do-sonarqube">&lt;/span>
&lt;a href="#configura%c3%a7%c3%a3o-do-sonarqube" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;ul>
&lt;li>Acesse &lt;a href="http://localhost:9000/"target="_blank" rel="noopener">http://localhost:9000&lt;/a>&lt;/li>
&lt;li>Login padrão:
&lt;ul>
&lt;li>Usuário: admin&lt;/li>
&lt;li>Senha: admin&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>Agora vamos configurar para fazer um escaneamento do projeto&lt;/p>
&lt;h3>&lt;strong>Gerando um Token de autenticação&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="gerando-um-token-de-autenticação">&lt;/span>
&lt;a href="#gerando-um-token-de-autentica%c3%a7%c3%a3o" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;ol>
&lt;li>No menu superior direito, clique no seu usuário &amp;gt; My Account &amp;gt; Security.&lt;/li>
&lt;li>Em &amp;ldquo;Generate Tokens&amp;rdquo;, crie um novo token (ex: nome-projeto-token).&lt;/li>
&lt;li>Guarde esse token (será usado no scanner).&lt;/li>
&lt;/ol>
&lt;h3>&lt;strong>Instalando o SonarScanner&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="instalando-o-sonarscanner">&lt;/span>
&lt;a href="#instalando-o-sonarscanner" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;p>O &lt;strong>SonarScanner&lt;/strong> é o CLI para enviar seu código ao SonarQube. Ou seja, localmente via terminal vamos falar para ele ler o projeto e então temos a análise.&lt;/p>
&lt;h3>&lt;strong>Instalação via NPM (para projetos Node):&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="instalação-via-npm-para-projetos-node">&lt;/span>
&lt;a href="#instala%c3%a7%c3%a3o-via-npm-para-projetos-node" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;p>&lt;code>npm install -g sonarqube-scanner&lt;/code>&lt;/p>
&lt;p>Para referências de cada projeto segue: &lt;a href="https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/scanners/sonarscanner"target="_blank" rel="noopener">https://docs.sonarsource.com/sonarqube-server/analyzing-source-code/scanners/sonarscanner&lt;/a>&lt;/p>
&lt;h3>&lt;strong>Configurando o SonarScanner no Projeto&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="configurando-o-sonarscanner-no-projeto">&lt;/span>
&lt;a href="#configurando-o-sonarscanner-no-projeto" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;p>Na raiz do projeto, crie um arquivo chamado &lt;code>sonar-project.properties&lt;/code>:&lt;/p>
&lt;p>Exemplo:&lt;/p>
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
&lt;div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-jsx" data-lang="jsx">&lt;span class="line">&lt;span class="cl">&lt;span class="nx">sonar&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">projectKey&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nx">nome&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nx">projeto&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">sonar&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">projectName&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nx">Nome&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nx">projeto&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">sonar&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">projectVersion&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mf">1.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">sonar&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">sources&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">sonar&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">language&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nx">js&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="nx">php&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">sonar&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">sourceEncoding&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nx">UTF&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">8&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">sonar&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">host&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nx">http&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="c1">//localhost:9000
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="nx">sonar&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">login&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nx">SEU_TOKEN_AQUI&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/div>&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copiar código"
aria-label="Copiar código"
data-copied-label="Copiado!"
>
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4">&lt;/div>
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4">&lt;/div>
&lt;/button>
&lt;/div>
&lt;/div>
&lt;h2>&lt;strong>Problemas encontrados&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="problemas-encontrados">&lt;/span>
&lt;a href="#problemas-encontrados" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h2>&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2025/setembro/20/configurando-o-sonar-qube-localmente/problema-encontrado-ao-rodar-o-escaneamento-2025-09-20-09-24.png" alt="problema encontrado ao rodar o escaneamento" loading="lazy" />&lt;/p>
&lt;p>ERROR: You&amp;rsquo;re not authorized to run analysis. Please contact the project administrator.&lt;/p>
&lt;h3>&lt;strong>O que significa esse erro?&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="o-que-significa-esse-erro">&lt;/span>
&lt;a href="#o-que-significa-esse-erro" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;p>O SonarScanner está tentando enviar os resultados da análise para o SonarQube, mas o usuário (ou token) configurado &lt;strong>não tem permissão&lt;/strong> para realizar essa operação no projeto configurado no SonarQube.&lt;/p>
&lt;p>&lt;strong>Perfeito! Vamos ver o que fiz de errado&lt;/strong>: o nome do projeto no arquivo &lt;code>sonar-project.properties&lt;/code> não estava igual ao que eu configurei no SonarQube local.&lt;/p>
&lt;p>Agora pronto: quando executar o comando &lt;code>sonar-scanner&lt;/code> vai executar o escaneamento no projeto e seguida mostrar em tela os resultados.&lt;/p>
&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2025/setembro/20/configurando-o-sonar-qube-localmente/terminal-sucesso-2025-09-20-09-33.png" alt="terminal com sucesso" loading="lazy" />&lt;/p>
&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2025/setembro/20/configurando-o-sonar-qube-localmente/executado-2025-09-20-09-32.png" alt="executado" loading="lazy" />&lt;/p></description></item><item><title>Bot Planner - Projeto para acompanhamento do desenvolvimento pessoal</title><link>https://deploy-preview-17--ladydebug.netlify.app/docs/2026/julho/bot-planner-projeto-para-acompanhamento-do-desenvolvimento-pessoal/</link><pubDate>Mon, 06 Jul 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-17--ladydebug.netlify.app/docs/2026/julho/bot-planner-projeto-para-acompanhamento-do-desenvolvimento-pessoal/</guid><description>
&lt;p>Recentemente estive a desenvolver alguns projetos de estudos com IA, e estava precisando me organizar, de, quanto tempo estive a desenvolver — tempo corrido —&lt;/p>
&lt;p>também ao esta desenvolvendo algo geralmente eu costumo ler a documentação da lingagem para leitura de algumas práticas, links de documentos, docs que eu estou escrevendo para determinada característica do projeto. Criar tarefas que me lembrei no ato que estava a desenvolver, e verifiquei que pode ser terminada logo após a tarefa que estou a fazer. Além de comentários do que foi realizado, esse acompanhamento de forma geral.&lt;/p>
&lt;p>Com base nesse problema, pensei em algo prático que eu possa fazer enquanto estou desenvolvendo. Ou seja comando &lt;code>/inicio&lt;/code> quando inicio a atividade, &lt;code>/link&lt;/code> para adicionar documentações entre outros importantes. &lt;code>/nota&lt;/code> quando eu quiser adicionar notas comentários, &lt;code>task&lt;/code> para quando quiser criar uma tarefas, &lt;code>fim&lt;/code> quando finalizar tudo. Após isso gere um &lt;code>Release notes&lt;/code> com o que foi feito e quais as tarefas ficaram pendentes.&lt;/p>
&lt;p>Então lendo uma &lt;a href="https://akitaonrails.com/2026/02/16/vibe-code-do-zero-a-producao-em-6-dias-the-m-akita-chronicles/#spoiler-do-processo"target="_blank" rel="noopener">postagem em um blog&lt;/a> e pensei em criar o bot com gestão pessoal para auxiliar no ciclo de desenvolvimento pessoal sem fricção e que gere um report notes no fim do trabalho.&lt;/p>
&lt;p>Podendo também aplicar para compartilhar caso queira com alguém do time (desenvolvimento orientado com metodologia XP).&lt;/p>
&lt;hr>
&lt;p>Criei o repositório no github &lt;a href="https://github.com/kellen-xavier/ladydebug-bot-planner"target="_blank" rel="noopener">https://github.com/kellen-xavier/ladydebug-bot-planner&lt;/a> &lt;del>inicialmente privado mas irei liberar em seguida&lt;/del>, open-source — estou a corrigir algumas questões de segurança — e primeiro criar o bot, inicialmente interação é via Discord, mas vai abranger multicanal de comunicação (pensei em slack e dicord principal) as demais particularmente não me interessei muito.&lt;/p>
&lt;h2>Primeira Fase do desenvolvimento&lt;span class="hx:absolute hx:-mt-20" id="primeira-fase-do-desenvolvimento">&lt;/span>
&lt;a href="#primeira-fase-do-desenvolvimento" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h2>&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2026/julho/bot-planner-projeto-para-acompanhamento-do-desenvolvimento-pessoal/image.png" alt="image.png" loading="lazy" />&lt;/p>
&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2026/julho/bot-planner-projeto-para-acompanhamento-do-desenvolvimento-pessoal/image-1.png" alt="image.png" loading="lazy" />&lt;/p>
&lt;p>Nos testes iniciais, ficou bem poluído os comandos no chat unificado, então pensei em criar um segundo “canal de texto”, para que o release-notes separado para acompanhar no dia seguinte, tendo essa visão limpa entre “comandos” e “release notes”.&lt;/p>
&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2026/julho/bot-planner-projeto-para-acompanhamento-do-desenvolvimento-pessoal/image-2.png" alt="image.png" loading="lazy" />&lt;/p>
&lt;hr>
&lt;h3>&lt;strong>Organização do Bot&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="organização-do-bot">&lt;/span>
&lt;a href="#organiza%c3%a7%c3%a3o-do-bot" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;p>Para configurar o bot é simples, deve-se seguir a documentação oficial neste link: &lt;a href="https://docs.discord.com/developers/quick-start/getting-started"target="_blank" rel="noopener">&lt;strong>Building your first Discord Bot&lt;/strong>&lt;/a>&lt;/p>
&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2026/julho/bot-planner-projeto-para-acompanhamento-do-desenvolvimento-pessoal/image-3.png" alt="image.png" loading="lazy" />&lt;/p>
&lt;p>&lt;strong>Para estes estudo de caso | Como configurar o Bot:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Vá no Developer Portal do Discord.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Abrir o app ladydebug-bot-planner.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Vá em Bot.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Clique em Reset Token.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Copie o token novo.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Atualize DISCORD_TOKEN no .env.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Rode de novo:&lt;/p>
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
&lt;div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">set&lt;/span> -a&lt;span class="p">;&lt;/span> &lt;span class="nb">source&lt;/span> .env&lt;span class="p">;&lt;/span> &lt;span class="nb">set&lt;/span> +a
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">python -m daily.main&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/div>&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copiar código"
aria-label="Copiar código"
data-copied-label="Copiado!"
>
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4">&lt;/div>
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4">&lt;/div>
&lt;/button>
&lt;/div>
&lt;/div>
&lt;/li>
&lt;li>
&lt;p>Configuração Mínima Local&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>Seu .env local deve ter pelo menos:&lt;/p>
&lt;p>&lt;code>DISCORD_TOKEN=token_do_bot DISCORD_GUILD_ID=807481361916100628 DB_PATH=daily.db&lt;/code>&lt;/p>
&lt;hr>
&lt;h3>Plano de Testes Bot Planner&lt;span class="hx:absolute hx:-mt-20" id="plano-de-testes-bot-planner">&lt;/span>
&lt;a href="#plano-de-testes-bot-planner" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;p>Visão geral&lt;/p>
&lt;p>&lt;strong>Checklist&lt;/strong>:&lt;/p>
&lt;h4>Todos&lt;span class="hx:absolute hx:-mt-20" id="todos">&lt;/span>
&lt;a href="#todos" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h4>&lt;p>[•] Mapear módulos e funcionalidades existentes em src/daily
[ ] Mapear testes existentes por funcionalidade
[ ] Executar testes/cobertura disponível
[ ] Consolidar lacunas de cobertura e recomendações&lt;/p>
&lt;h3>Funcionalidades Com Testes&lt;span class="hx:absolute hx:-mt-20" id="funcionalidades-com-testes">&lt;/span>
&lt;a href="#funcionalidades-com-testes" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;p>Criei o report em docs/TEST_COVERAGE_REPORT.md aqui ele documenta o seguinte:&lt;/p>
&lt;ul>
&lt;li>Estado atual da suíte: 79 passed.&lt;/li>
&lt;li>Diretrizes para evitar testes enviesados/falso positivo.&lt;/li>
&lt;li>Lacunas restantes por prioridade.&lt;/li>
&lt;li>Cenários exatos que precisam ser implementados.&lt;/li>
&lt;li>Critérios de aceite para novas rodadas.&lt;/li>
&lt;li>Recomendação para adicionar pytest-cov.&lt;/li>
&lt;li>Ordem sugerida de execução.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Principais áreas priorizadas no report:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>CommandRouter&lt;/li>
&lt;li>SqliteStorage&lt;/li>
&lt;li>SimpleFetcher&lt;/li>
&lt;li>VCS adapters&lt;/li>
&lt;li>Report de fim de dia&lt;/li>
&lt;li>Discord adapter callbacks&lt;/li>
&lt;li>Models/DTOs&lt;/li>
&lt;li>Métrica objetiva com coverage&lt;/li>
&lt;/ol>
&lt;hr>
&lt;p>&lt;strong>Erros encontrado:&lt;/strong>&lt;/p>
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
&lt;div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-jsx" data-lang="jsx">&lt;span class="line">&lt;span class="cl">&lt;span class="nx">python&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="nx">m&lt;/span> &lt;span class="nx">daily&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">main&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="mi">2026&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">07&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span> &lt;span class="mi">09&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">45&lt;/span> &lt;span class="nx">INFO&lt;/span> &lt;span class="nx">discord&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">client&lt;/span> &lt;span class="nx">logging&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="nx">using&lt;/span> &lt;span class="kr">static&lt;/span> &lt;span class="nx">token&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="mi">2026&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">07&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span> &lt;span class="mi">09&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">47&lt;/span> &lt;span class="nx">INFO&lt;/span> &lt;span class="nx">discord&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">gateway&lt;/span> &lt;span class="nx">Shard&lt;/span> &lt;span class="nx">ID&lt;/span> &lt;span class="nx">None&lt;/span> &lt;span class="nx">has&lt;/span> &lt;span class="nx">connected&lt;/span> &lt;span class="nx">to&lt;/span> &lt;span class="nx">Gateway&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">Session&lt;/span> &lt;span class="nx">ID&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="nx">b25a5b78274ede64c286f2fc11e8c2e3&lt;/span>&lt;span class="p">).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">Bot&lt;/span> &lt;span class="nx">online&lt;/span> &lt;span class="nx">como&lt;/span> &lt;span class="nx">ladydebug&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nx">bot&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="nx">planner&lt;/span>&lt;span class="err">#&lt;/span>&lt;span class="mi">3088&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="mi">2026&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">07&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">09&lt;/span> &lt;span class="mi">09&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">51&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">05&lt;/span> &lt;span class="nx">ERROR&lt;/span> &lt;span class="nx">discord&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">app_commands&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">tree&lt;/span> &lt;span class="nx">Ignoring&lt;/span> &lt;span class="nx">exception&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="nx">command&lt;/span> &lt;span class="s1">&amp;#39;inicio&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">Traceback&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">most&lt;/span> &lt;span class="nx">recent&lt;/span> &lt;span class="nx">call&lt;/span> &lt;span class="nx">last&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">File&lt;/span> &lt;span class="s2">&amp;#34;/home/kellen/Documents/Projetos github/ladydebug-bot-planner/.venv/lib/python3.14/site-packages/discord/app_commands/commands.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">line&lt;/span> &lt;span class="mi">859&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="nx">_do_call&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kr">await&lt;/span> &lt;span class="nx">self&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">_callback&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">interaction&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">**&lt;/span>&lt;span class="nx">params&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="err">#&lt;/span> &lt;span class="nx">type&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="nx">ignore&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">File&lt;/span> &lt;span class="s2">&amp;#34;/home/kellen/Documents/Projetos github/ladydebug-bot-planner/src/daily/adapters/discord_bot.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">line&lt;/span> &lt;span class="mi">90&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="nx">inicio&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">router&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">inicio&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">str&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">interaction&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">user&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">id&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="nx">str&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">interaction&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">channel_id&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">File&lt;/span> &lt;span class="s2">&amp;#34;/home/kellen/Documents/Projetos github/ladydebug-bot-planner/src/daily/command_router.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">line&lt;/span> &lt;span class="mi">32&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="nx">inicio&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">s&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">self&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">_day&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">start_day&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">user_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">channel_id&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">File&lt;/span> &lt;span class="s2">&amp;#34;/home/kellen/Documents/Projetos github/ladydebug-bot-planner/src/daily/core/day_service.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">line&lt;/span> &lt;span class="mi">32&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="nx">start_day&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">raise&lt;/span> &lt;span class="nx">DayAlreadyOpen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Já existe um dia aberto para este usuário.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">daily&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">core&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">day_service&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">DayAlreadyOpen&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="nx">Já&lt;/span> &lt;span class="nx">existe&lt;/span> &lt;span class="nx">um&lt;/span> &lt;span class="nx">dia&lt;/span> &lt;span class="nx">aberto&lt;/span> &lt;span class="nx">para&lt;/span> &lt;span class="nx">este&lt;/span> &lt;span class="nx">usuário&lt;/span>&lt;span class="p">.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">The&lt;/span> &lt;span class="nx">above&lt;/span> &lt;span class="nx">exception&lt;/span> &lt;span class="nx">was&lt;/span> &lt;span class="nx">the&lt;/span> &lt;span class="nx">direct&lt;/span> &lt;span class="nx">cause&lt;/span> &lt;span class="k">of&lt;/span> &lt;span class="nx">the&lt;/span> &lt;span class="nx">following&lt;/span> &lt;span class="nx">exception&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">Traceback&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">most&lt;/span> &lt;span class="nx">recent&lt;/span> &lt;span class="nx">call&lt;/span> &lt;span class="nx">last&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">File&lt;/span> &lt;span class="s2">&amp;#34;/home/kellen/Documents/Projetos github/ladydebug-bot-planner/.venv/lib/python3.14/site-packages/discord/app_commands/tree.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">line&lt;/span> &lt;span class="mi">1302&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="nx">_call&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">await&lt;/span> &lt;span class="nx">command&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">_invoke_with_namespace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">interaction&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">namespace&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">File&lt;/span> &lt;span class="s2">&amp;#34;/home/kellen/Documents/Projetos github/ladydebug-bot-planner/.venv/lib/python3.14/site-packages/discord/app_commands/commands.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">line&lt;/span> &lt;span class="mi">884&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="nx">_invoke_with_namespace&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kr">await&lt;/span> &lt;span class="nx">self&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">_do_call&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">interaction&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">transformed_values&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">File&lt;/span> &lt;span class="s2">&amp;#34;/home/kellen/Documents/Projetos github/ladydebug-bot-planner/.venv/lib/python3.14/site-packages/discord/app_commands/commands.py&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">line&lt;/span> &lt;span class="mi">877&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">in&lt;/span> &lt;span class="nx">_do_call&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">raise&lt;/span> &lt;span class="nx">CommandInvokeError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">e&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="nx">from&lt;/span> &lt;span class="nx">e&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">discord&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">app_commands&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">errors&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">CommandInvokeError&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="nx">Command&lt;/span> &lt;span class="s1">&amp;#39;inicio&amp;#39;&lt;/span> &lt;span class="nx">raised&lt;/span> &lt;span class="nx">an&lt;/span> &lt;span class="nx">exception&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="nx">DayAlreadyOpen&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="nx">Já&lt;/span> &lt;span class="nx">existe&lt;/span> &lt;span class="nx">um&lt;/span> &lt;span class="nx">dia&lt;/span> &lt;span class="nx">aberto&lt;/span> &lt;span class="nx">para&lt;/span> &lt;span class="nx">este&lt;/span> &lt;span class="nx">usuário&lt;/span>&lt;span class="p">.&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/div>&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copiar código"
aria-label="Copiar código"
data-copied-label="Copiado!"
>
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4">&lt;/div>
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4">&lt;/div>
&lt;/button>
&lt;/div>
&lt;/div>
&lt;p>&lt;strong>Motivo&lt;/strong>:&lt;/p>
&lt;p>DayAlreadyOpen: Já existe um dia aberto para este usuário.
Isso acontece porque você executou /inicio, o bot abriu uma sessão no daily.db, e depois você chamou /inicio de novo sem antes fechar com /fim.&lt;/p>
&lt;p>&lt;strong>Explicação&lt;/strong>:&lt;/p>
&lt;p>Causa Técnica
O core está correto em impedir dois dias abertos:
if self._storage.get_open_session(user_id) is not None:
raise DayAlreadyOpen(&amp;ldquo;Já existe um dia aberto para este usuário.&amp;rdquo;)
O problema é que essa exceção está vazando até o Discord, gerando stack trace. O bot deveria responder algo amigável, como:
Já existe um dia aberto para você. Use /fim para fechar antes de iniciar outro.&lt;/p>
&lt;p>&lt;strong>Correções:&lt;/strong>&lt;/p>
&lt;p>Plano De Ajustes
Ainda em modo planejamento, então não vou editar arquivos agora. O ajuste recomendado é:&lt;/p>
&lt;ol>
&lt;li>Tratar DayAlreadyOpen no CommandRouter.inicio.&lt;/li>
&lt;li>Tratar NoOpenDay em /nota, /link e /fim.&lt;/li>
&lt;li>Evitar que exceções esperadas do core virem erro no Discord.&lt;/li>
&lt;li>Melhorar diagnóstico de ambiente Discord com DISCORD_CLIENT_ID.&lt;/li>
&lt;li>Documentar configuração local e produção no README.&lt;/li>
&lt;li>Adicionar testes para esses casos.&lt;/li>
&lt;/ol>
&lt;h2>Comportamento Esperado Após Ajustes&lt;span class="hx:absolute hx:-mt-20" id="comportamento-esperado-após-ajustes">&lt;/span>
&lt;a href="#comportamento-esperado-ap%c3%b3s-ajustes" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h2>&lt;p>Validar &lt;code>/inicio&lt;/code> com dia já aberto mas sem terminar atividades:
Deve retornar:
Mensagem:
🟡 Já existe um dia aberto para você. Use &lt;code>/continuar&lt;/code> para seguir o seu dia.
Comportamento: ao enviar comando &lt;code>/continue&lt;/code> deve seguir inserindo as atividades, do dia. Ou seja;&lt;/p>
&lt;p>&lt;strong>Cenário&lt;/strong>:
Dado que usuário envia o comando /iniciar no dia 1
E no dia 1 usuário envia o comando /iniciar
Quando retornar a mensagem: 🟡 Já existe um dia aberto para você. Use &lt;code>/continuar&lt;/code> para seguir o seu dia.
Então usuário deve inserir comando /continuar
E deve seguir até finalizar o dia&lt;/p>
&lt;p>Validar &lt;code>/nota&lt;/code> sem dia aberto:
Deve retornar:
Mensagem: ⚠️ Nenhum dia aberto. Use /inicio primeiro.&lt;/p>
&lt;p>Validar &lt;code>/fim&lt;/code> sem dia aberto:
Deve retornar:
Mensagem: ⚠️ Nenhum dia aberto para fechar. Use /inicio para começar.&lt;/p>
&lt;p>Validar &lt;code>/link&lt;/code> sem dia aberto:
Deve retornar:
Mensagem:
⚠️ Nenhum dia aberto. Use /inicio primeiro.&lt;/p>
&lt;ol>
&lt;li>Arquivos Que Devem Mudar&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>src/daily/command_router.py&lt;/li>
&lt;li>src/daily/adapters/discord_bot.py&lt;/li>
&lt;li>src/daily/main.py&lt;/li>
&lt;li>.env.example&lt;/li>
&lt;li>&lt;a href="http://readme.md/"target="_blank" rel="noopener">README.md&lt;/a>&lt;/li>
&lt;li>tests/test_ingest_and_report.py&lt;/li>
&lt;li>tests/test_discord_bot.py&lt;/li>
&lt;li>tests/test_main_config.py&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>O Que Mudou:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>src/daily/command_router.py&lt;/li>
&lt;li>/inicio com dia já aberto agora retorna:
🟡 Já existe um dia aberto para você. Use /continuar para seguir o seu dia.&lt;/li>
&lt;li>Novo método continuar.&lt;/li>
&lt;li>/nota, /link e /fim agora tratam NoOpenDay com mensagens amigáveis.&lt;/li>
&lt;li>/link agora verifica dia aberto antes de buscar/resumir URL.&lt;/li>
&lt;li>src/daily/adapters/discord_bot.py&lt;/li>
&lt;li>Adicionado comando Discord /continuar.&lt;/li>
&lt;li>Melhorado diagnóstico quando o bot não vê o servidor.&lt;/li>
&lt;li>Se DISCORD_CLIENT_ID estiver configurado, o erro imprime URL de convite correta.&lt;/li>
&lt;li>src/daily/main.py&lt;/li>
&lt;li>Adicionada validação de ambiente:
DISCORD_TOKEN obrigatório.
DISCORD_GUILD_ID numérico se informado.
DISCORD_CLIENT_ID numérico se informado.&lt;/li>
&lt;li>.env.example&lt;/li>
&lt;li>Adicionado DISCORD_CLIENT_ID.&lt;/li>
&lt;li>&lt;a href="http://readme.md/"target="_blank" rel="noopener">README.md&lt;/a>&lt;/li>
&lt;li>Documentado /continuar.&lt;/li>
&lt;li>Documentado ambiente local e produção.&lt;/li>
&lt;li>Adicionado troubleshooting do Discord.&lt;/li>
&lt;li>Testes adicionados para:&lt;/li>
&lt;li>/inicio com dia aberto.&lt;/li>
&lt;li>/continuar com e sem dia aberto.&lt;/li>
&lt;li>/nota, /link, /fim sem dia aberto.&lt;/li>
&lt;li>validação de DISCORD_CLIENT_ID e DISCORD_GUILD_ID.&lt;/li>
&lt;li>URL de convite no diagnóstico.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h3>Visão Geral de Testes com Discord&lt;span class="hx:absolute hx:-mt-20" id="visão-geral-de-testes-com-discord">&lt;/span>
&lt;a href="#vis%c3%a3o-geral-de-testes-com-discord" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2026/julho/bot-planner-projeto-para-acompanhamento-do-desenvolvimento-pessoal/image-4.png" alt="image.png" loading="lazy" />&lt;/p>
&lt;hr>
&lt;h3>&lt;strong>Updates e Melhorias&lt;/strong>&lt;span class="hx:absolute hx:-mt-20" id="updates-e-melhorias">&lt;/span>
&lt;a href="#updates-e-melhorias" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;p>Foi colocado um segundo canal de texto onde que, com o comando &lt;code>/fim&lt;/code> finaliza o report e adiciona no canal que fez a chamada, o release-notes do dia.&lt;/p>
&lt;p>Agora foi visto que precisa ser finalizada as atividades criadas no dia. Para isso segue a nova funcionalidade.&lt;/p>
&lt;p>&lt;strong>Funcionalidade&lt;/strong>: Dado que o usuário conclua e foi finalizada a “Tarefa” criada, Então deve adicionar o comando &lt;code>/fim-task&lt;/code> com a seguinte ação:&lt;/p>
&lt;p>&lt;strong>Comportamento esperado:&lt;/strong>&lt;/p>
&lt;p>URL: para adicionar o link de uma atividade concluida
Titulo Tarefa: Nome da Minha task aqui
Tempo da atividade aberta: xx minutos / xx horas / xx dias&lt;/p>
&lt;p>Dado que a atividade contém comentário,
Quando concluir ação
Então release notes deve mostrar comentários adicionada a ação&lt;/p>
&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2026/julho/bot-planner-projeto-para-acompanhamento-do-desenvolvimento-pessoal/image-5.png" alt="image.png" loading="lazy" />&lt;/p>
&lt;hr>
&lt;h3>Fluxo De Produção&lt;span class="hx:absolute hx:-mt-20" id="fluxo-de-produção">&lt;/span>
&lt;a href="#fluxo-de-produ%c3%a7%c3%a3o" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h3>&lt;ol>
&lt;li>Criar canal #release-notes.&lt;/li>
&lt;li>Copiar o ID do canal.&lt;/li>
&lt;li>Criar app/bot no Discord.&lt;/li>
&lt;li>Convidar o bot com bot applications.commands.&lt;/li>
&lt;li>Criar projeto Railway conectado ao GitHub.&lt;/li>
&lt;li>Configurar secrets no Railway.&lt;/li>
&lt;li>Configurar volume persistente.&lt;/li>
&lt;li>Start command: python -m daily.main.&lt;/li>
&lt;li>Fazer deploy.&lt;/li>
&lt;li>Testar no Discord:&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>/inicio&lt;/li>
&lt;li>/nota&lt;/li>
&lt;li>/pr url:&lt;a href="https://github.com/.../pull/"target="_blank" rel="noopener">https://github.com/&amp;hellip;/pull/&lt;/a>&amp;hellip;&lt;/li>
&lt;li>/fim&lt;/li>
&lt;/ul></description></item><item><title>Cypress e Boas Práticas de Automação</title><link>https://deploy-preview-17--ladydebug.netlify.app/docs/2024/outubro/cypress-e-boas-praticas-de-automacao/</link><pubDate>Thu, 24 Oct 2024 13:07:00 -0300</pubDate><guid>https://deploy-preview-17--ladydebug.netlify.app/docs/2024/outubro/cypress-e-boas-praticas-de-automacao/</guid><description>
&lt;p>Evitando o uso de &lt;em>Falsos Positivos&lt;/em> com Cypress. Segue abaixo um exemplo de um código, e um arquivo commands com um simples login na aplicação:&lt;/p>
&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2024/outubro/cypress-e-boas-praticas-de-automacao/exemplo-praticas-ruins.png" alt="exemplo-praticas-ruins" loading="lazy" />&lt;/p>
&lt;p>Essa aplicação estava ocorrendo um certo erro ao realizar o login, e foi adicionado o seguinte trecho de código na automação para poder realizar o login com sucesso:&lt;/p>
&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2024/outubro/cypress-e-boas-praticas-de-automacao/o_que_o_erro_faz.png" alt="o que o erro faz?" loading="lazy" />&lt;/p>
&lt;p>Mas o que esse trecho diz? Serve para suprimir os erros que ocorrem na aplicação durante a execução dos testes do Cypress.&lt;/p>
&lt;p>Como assim? Ao usar &lt;code>cy.on('uncaught:exception')&lt;/code> e retornar false, está instruindo o Cypress a ignorar qualquer erro que ocorra na sua aplicação. Isso permite que o teste continue mesmo que a página ainda não esteja totalmente carregada, dando tempo para que os elementos sejam renderizados antes que o Cypress tente interagir com eles.&lt;/p>
&lt;p>Por que remover &lt;code>cy.on('uncaught:exception')&lt;/code> é importante? Nesse caso, como está sendo manipulado o teste, forçando a “ignorar esse erro retornando que ele seja falso” é adicionado um falso positivo no nosso teste. Segue abaixo:&lt;/p>
&lt;p>&lt;img src="https://deploy-preview-17--ladydebug.netlify.app/docs/2024/outubro/cypress-e-boas-praticas-de-automacao/login_com_sucesso.png" alt="alt text" loading="lazy" />&lt;/p>
&lt;h2>Alternativas e soluções para lidar com o tempo de carregamento e evitar adicionar “falso positivo”&lt;span class="hx:absolute hx:-mt-20" id="alternativas-e-soluções-para-lidar-com-o-tempo-de-carregamento-e-evitar-adicionar-falso-positivo">&lt;/span>
&lt;a href="#alternativas-e-solu%c3%a7%c3%b5es-para-lidar-com-o-tempo-de-carregamento-e-evitar-adicionar-falso-positivo" class="subheading-anchor" aria-label="Link permanente para esta secção">&lt;/a>&lt;/h2>&lt;p>Em vez de suprimir erros, deve-se usar as ferramentas do Cypress para garantir que os elementos estejam presentes e prontos para interação antes de tentar acessá-los. Algumas opções incluem:&lt;/p>
&lt;p>&lt;code>cy.wait()&lt;/code>: Aguarde um determinado tempo ou até que um elemento ou condição específica seja atendida antes de prosseguir com o teste.&lt;/p>
&lt;p>OBS: cuide as más práticas ao usar o comando &lt;code>cy.wait(número)&lt;/code> , leia a documentação sobre Anti-Pattern.&lt;/p>
&lt;p>&lt;a href="https://docs.cypress.io/app/core-concepts/best-practices#Unnecessary-Waiting"target="_blank" rel="noopener">Unnecessary Waiting aqui&lt;/a>&lt;/p>
&lt;p>Em vez disso, use:&lt;/p>
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code">
&lt;div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">cy.intercept&lt;span class="o">(&lt;/span>&lt;span class="s1">&amp;#39;GET&amp;#39;&lt;/span>, &lt;span class="s1">&amp;#39;/users&amp;#39;&lt;/span>, &lt;span class="o">[{&lt;/span> name: &lt;span class="s1">&amp;#39;Maggy&amp;#39;&lt;/span> &lt;span class="o">}&lt;/span>, &lt;span class="o">{&lt;/span> name: &lt;span class="s1">&amp;#39;Joan&amp;#39;&lt;/span> &lt;span class="o">}])&lt;/span>.as&lt;span class="o">(&lt;/span>&lt;span class="s1">&amp;#39;getUsers&amp;#39;&lt;/span>&lt;span class="o">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cy.get&lt;span class="o">(&lt;/span>&lt;span class="s1">&amp;#39;[data-testid=&amp;#34;fetch-users&amp;#34;]&amp;#39;&lt;/span>&lt;span class="o">)&lt;/span>.click&lt;span class="o">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cy.wait&lt;span class="o">(&lt;/span>&lt;span class="s1">&amp;#39;@getUsers&amp;#39;&lt;/span>&lt;span class="o">)&lt;/span> // &amp;lt;--- &lt;span class="nb">wait&lt;/span> explicitly &lt;span class="k">for&lt;/span> this route to finish&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/div>&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0">
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="Copiar código"
aria-label="Copiar código"
data-copied-label="Copiado!"
>
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4">&lt;/div>
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4">&lt;/div>
&lt;/button>
&lt;/div>
&lt;/div>
&lt;p>&lt;code>cy.get(...).should('exist')&lt;/code> ou&lt;/p>
&lt;p>&lt;code>cy.get(...).should('be.visible')&lt;/code>&lt;/p>
&lt;p>Precisa garantir de que o elemento existe e está visível na página antes de tentar interagir com ele.&lt;/p></description></item></channel></rss>