# Changelog

Todas as mudanças notáveis neste projeto serão documentadas aqui.

O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.0.0/),
e este projeto adere ao [Semantic Versioning](https://semver.org/lang/pt-BR/).

## [Unreleased]

### Fixed
- Docs doctor: `require_once` de `helpers.php` em `docs_doctor.php` para evitar `repo_config_bool()` indefinida se o bootstrap em produção tiver ordem antiga de includes.
- Code review: menos fallbacks por “resposta inválida/truncada” — `max_output_tokens` maior em `ai_review_commit` e heurística `seems_truncated_text` alinhada ao formato com secções (evita rejeitar bullets sem ponto final).
- `bin/repo_manage.php add` deixa de depender de token de workspace do Bitbucket (`BITBUCKET_ADMIN_TOKEN`) como caminho principal — esse recurso é exclusivo do plano Premium. Agora exige `--bb-api-token=<token de repositório>` (disponível no plano Standard) ou, alternativamente, `BITBUCKET_ADMIN_TOKEN` configurado (quem estiver no Premium). Sem nenhum dos dois, erro claro antes de tentar qualquer chamada ao Bitbucket, em vez de falhar tarde com uma mensagem genérica.
- `bin/repo_manage.php migrate`: repositório sem `discord_webhook_url` próprio em `config/repositories.php` agora cai para `DISCORD_WEBHOOK_URL` do `.env` em vez de ser pulado — antes exigia webhook próprio por repo mesmo quando o padrão do `.env` já resolveria.

### Added
- Documentação de escopo: `documentation/validacoes-e-conferencias.md`, regra Cursor `.cursor/rules/escopo-validacoes.mdc`.
- `src/release_notes.php`, tabelas SQLite e bootstrap para releases e docs doctor.
- Severidade estruturada da IA (`src/severity.php`, JSON schema via Responses API) e alerta urgente adicional no Discord para commits classificados como críticos/altos (`AI_URGENT_SEVERITY_THRESHOLD`, `DISCORD_URGENT_MENTION`, overrides por repo).
- Fila assíncrona (`review_jobs` no SQLite, `src/queue.php`, `src/jobs.php`, `bin/worker.php`): `webhook.php` agora só valida e enfileira; todo o processamento (Bitbucket, OpenAI, Discord) roda em `bin/worker.php` via cron. Jobs presos por interrupção são resgatados automaticamente (`requeue_stale_jobs`) e falhas têm retry (até 3 tentativas) antes de virar `dead`. Corrige commits que ficavam presos em `processing` para sempre quando a requisição do webhook era interrompida.
- `src/openai_client.php`: cliente único (`openai_responses_request`) para as 3 chamadas à OpenAI (code review, docs doctor, release notes) — antes cada uma tinha seu próprio curl. Docs doctor e release notes passam a validar texto vazio/truncado da mesma forma que o code review (`is_valid_ai_text`/`seems_truncated_text`), evitando mandar resposta cortada da IA direto pro Discord.
- Alerta de saúde do bot (`src/health.php`, `DISCORD_OPS_WEBHOOK_URL`): se a fila acumular falhas definitivas (`dead`) acima do limiar na última hora, avisa no Discord (com cooldown de 1h entre alertas). Antes, falhas só apareciam em `commit-review.log`.
- Testes automatizados (PHPUnit, `composer.json`, `tests/`): 53 testes cobrindo `analysis_strategy.php`, `severity.php`, `helpers.php`, `docs_doctor.php` e a máquina de estados da fila (`src/queue.php`, `src/health.php`). `composer test` / `composer lint`. CI em `bitbucket-pipelines.yml` roda ambos a cada push neste repositório.
- Prompt: cada bullet da análise passa a citar o arquivo relevante entre crases, facilitando cruzar a resposta da IA com o diff.
- `prepare_analysis_payload()` prioriza blocos de arquivos de alto risco antes de truncar o diff por limite de bytes, para não cortar preferencialmente a parte mais arriscada em diffs grandes.
- Fallback de arquivos a partir do diff (`extract_file_paths_from_diff()`): quando o diffstat da API do Bitbucket não retorna arquivos mas o diff em si tem conteúdo, a lista exibida no Discord é derivada dos cabeçalhos do próprio diff — corrige casos em que a análise cobria arquivos reais mas o campo "Arquivos no diff" aparecia vazio (`—`).
- 12 novos testes (65 no total) cobrindo as mudanças acima e o novo fluxo de notificação (`AnalysisStrategyTest`, `SeverityTest`, `DiscordTest`).
- `bin/repo_manage.php` (CLI: `add`/`list`/`update`/`deactivate`/`migrate`): onboarding de repositório vira um comando — gera o `webhook_secret`, cria o webhook no Bitbucket automaticamente via API (`bb_create_webhook()`, `src/bitbucket.php`, usando `BITBUCKET_ADMIN_TOKEN`) e cadastra no banco. Antes exigia criar o webhook manualmente na UI do Bitbucket + editar `config/repositories.php` + deploy.
- Tabela `repositories` (SQLite) substitui `config/repositories.php` como fonte de configuração em runtime — `load_repo_configs()`/`get_repo_config()` (`src/repositories.php`) mantiveram o mesmo papel para quem já as consumia (`webhook.php`, `src/jobs.php`), só a origem dos dados mudou. `bb_api_token` por repo agora é opcional: sem override, cai para `BITBUCKET_ADMIN_TOKEN` (um token de workspace serve para todos os repos, com override disponível por repo).
- 26 novos testes (91 no total) cobrindo o CLI e a nova camada de armazenamento (`RepoCliTest`, `RepositoriesTest`).
- Mapeamento Bitbucket → Discord (`src/people.php`, tabela `people`, `bin/people_manage.php`): autor de um commit alto/crítico é mencionado diretamente (`<@discord_user_id>`) quando o e-mail do `commit.author` estiver mapeado — combinado, sem se excluir, com a menção de cargo/`@here` já existente (que continua só em `critico`). `build_discord_alert_payload()` (novo, `src/discord.php`) extrai a montagem do payload de `discord_send_alert()` para ficar testável sem rede.
- Auditoria mensal de lógica por domínio (`src/audit.php`, tabela `code_audit_targets`, `bin/audit_manage.php`, `bin/audit_run.php`): lê o conteúdo atual de um diretório configurado (via nova `bb_list_directory_files()`/`bb_get_file_content()` em `src/bitbucket.php` — API de "src" do Bitbucket, não diffstat/diff) e usa a IA para apontar lógica duplicada/inconsistente entre arquivos (o caso motivador: o mesmo cálculo implementado de três formas diferentes no projeto de NPS). Disparo mensal via cron enfileirando `job_type='audit'` na mesma fila já existente — ganha retry/recuperação/alerta de saúde de graça. Relatório sem severidade nem bloqueio, só informativo no Discord.
- 22 novos testes (113 no total) cobrindo o mapeamento de pessoas e a auditoria (`PeopleTest`, `AuditTest`, ampliação de `DiscordTest`).
- Vínculo self-service Bitbucket → Discord (`link_discord.php`, `src/discord_oauth.php`): cada pessoa acessa um link, digita o e-mail que usa nos commits e autentica com o Discord (OAuth2) — o vínculo em `people` é gravado automaticamente, sem um admin rodar `bin/people_manage.php add` por pessoa. `state` assinado (HMAC) carrega o e-mail e faz o papel de proteção contra CSRF, sem precisar de tabela/sessão no servidor. `bin/people_manage.php` continua existindo como fallback manual.
- Auditoria mensal ganha saída estruturada (`audit_report_json_schema()`, `extract_openai_structured_audit()`, `src/audit.php` — mesmo padrão da severidade de commit) em vez de texto livre, permitindo achados discretos.
- Issue no Bitbucket por achado da auditoria (opt-in por alvo, `--create-issues` em `bin/audit_manage.php add-target`/`update-target`): `bb_create_issue()` (`src/bitbucket.php`) cria uma issue por achado novo; dedupe por hash exato do achado (`audit_findings_seen`) evita issue duplicada todo mês pro mesmo problema ainda não corrigido. Falha ao criar issue (ex.: repositório sem issue tracker habilitado) nunca impede o relatório no Discord.
- 14 novos testes (133 no total) cobrindo o vínculo OAuth e a criação de issues (`DiscordOauthTest`, `BitbucketTest`, ampliação de `AuditTest`).
- Suporte a MySQL (`DB_DRIVER=mysql`, `src/db.php` — renomeado de `src/sqlite.php`, função `sqlite()` renomeada para `db()`): SQLite continua sendo o padrão e o que os testes automatizados usam (zero-config); MySQL é o recomendado em produção. As 9 tabelas ganham DDL própria por dialeto (`db_create_tables_sqlite()`/`db_create_tables_mysql()` — `AUTO_INCREMENT`, `VARCHAR` em vez de `TEXT` em colunas com índice único, `ENGINE=InnoDB`). Os poucos pontos com sintaxe divergente (`INSERT OR IGNORE` vs `INSERT IGNORE`; upsert `ON CONFLICT` vs `ON DUPLICATE KEY UPDATE`) passam por `db_insert_ignore()`/`db_upsert()`, novas, testáveis por dialeto sem precisar de conexão real. Validado de ponta a ponta contra um MySQL 5.7 real (fila, upsert de repositório/pessoa, dedupe de achado de auditoria, os três CLIs) além dos testes automatizados.
- 10 novos testes (143 no total) cobrindo o driver e a construção de SQL por dialeto (`DbTest`).

### Changed
- Docs doctor **por defeito ativo**; mensagens Discord distintas de code review (username, título, cor, texto).
- README e docs de integração referem apenas este repositório.
- `webhook.php` responde ao Bitbucket em milissegundos (só enfileira); antes podia levar minutos por push com vários commits, arriscando timeout do webhook.
- **Notificação no Discord agora é só para `alto`/`crítico`** (`AI_DISCORD_MIN_SEVERITY`, padrão `alto`, override por repo em `discord_min_severity`): commits `baixo`/`medio`, e severidade nula (fallback/IA omitida), não geram mais mensagem — antes, todo commit revisado gerava um embed no canal.
- O embed normal e o "alerta urgente" separado (mensagem extra com @mention) foram **fundidos em uma única mensagem** por commit alto/crítico (`build_discord_alert_embed()`/`discord_send_alert()`, `src/discord.php`): título com selo de severidade (🚨 Crítico / ⚠️ Alto), motivo (`severity_reason`) em destaque, @mention só quando a severidade atinge `AI_URGENT_SEVERITY_THRESHOLD` (padrão `critico`, mesmo critério de antes). `build_discord_embed()`, `discord_send_embed()`, `build_discord_urgent_embed()` e `discord_send_urgent_alert()` foram removidos (substituídos pelas funções acima).
- Critério de severidade consolidado numa única fonte (`AI_SEVERITY_CRITERIA` em `src/severity.php`) usada tanto no prompt quanto na description do schema JSON — antes era texto duplicado nos dois lugares, com risco de divergência.
