O registro de alterações é parte do produto, não um git log

Product

Existem dois tipos de registro de alterações.

O primeiro é gerado a partir das mensagens de commit. Ele tem linhas como fix: handle null in resolver e chore: bump deps. Tecnicamente, é um registro completo do que mudou, e nenhum usuário jamais o leu duas vezes.

O segundo é escrito para quem usa o seu produto. Ele diz o que dá para fazer agora e não dava na semana passada. É curto. As pessoas assinam para acompanhar.

A diferença não está nas ferramentas. Está em alguém ter decidido que o registro de alterações faz parte do produto.

Dê um tipo a cada entrada

A mudança que mais rende é dar um tipo a cada entrada. O Kookee usa sete:

feature · fix · improvement · breaking · security · deprecated · other

Isso não é enfeite. É o tipo que torna o registro filtrável, e é o filtro que o torna útil para mais de um público:

TypeScript
// Novidades — para os usuários
const features = await kookee.changelog.list({
  filter: { changelogType: 'feature' },
  limit: 10,
});

// O que vai quebrar — para quem integra
const breaking = await kookee.changelog.list({ filter: { changelogType: 'breaking' } });

Um engenheiro que integra a sua API se importa com breaking e deprecated, e com mais nada. Um usuário se importa com feature. Uma equipe de segurança quer security numa página só dela. Uma lista com tipos atende os três; uma lista sem tipos não atende bem nenhum deles.

O tipo é um campo estruturado, e não uma coluna da entrada, o que faz diferença na hora de renderizar. entry.type é a string 'changelog'; o tipo da mudança vem do array de campos:

TypeScript
import { fieldOptionKey, fieldStringValue } from '@kookee/sdk';

const releaseType = fieldOptionKey(entry.fields, 'changelogType'); // 'feature'
const version = fieldStringValue(entry.fields, 'version');         // '1.6.0'

Dê uma versão a cada entrada

O tipo responde “que tipo de mudança é essa”. A versão responde “eu já tenho isso?”, e é essa a pergunta que o usuário faz quando chega de uma conversa com o suporte.

A versão é texto livre, então aceita o esquema que você usar: 1.6.0, 2024.11, v3-beta. Dois hábitos fazem as versões valerem a pena: colocar uma em cada entrada e usar o mesmo esquema em todas. Um registro de alterações em que só metade das entradas tem versão parece descuido, e é descuido.

Filtre por uma versão exata quando alguém perguntar o que saiu numa versão específica:

TypeScript
const release = await kookee.changelog.list({ filter: { version: '1.6.0' } });

As entradas vêm da mais nova para a mais antiga. Se você quer a ordem estrita das versões (e numa página de versões provavelmente quer, já que as datas enganam quando há patches portados para versões antigas e lançamentos que atrasam), ordene você mesmo, porque uma ordenação de strings coloca 1.10.0 antes de 1.9.0:

TypeScript
const { data } = await kookee.changelog.list({ limit: 100 });

const byVersion = [...data].sort((a, b) =>
  (fieldStringValue(b.fields, 'version') ?? '').localeCompare(
    fieldStringValue(a.fields, 'version') ?? '',
    undefined,
    { numeric: true },
  ),
);

É o numeric: true que faz 1.10.0 vir depois de 1.9.0.

Deixe as pessoas reagirem

Toda entrada do registro de alterações aceita reações com emoji:

TypeScript
await kookee.changelog.react(entryId, { reactionType: 'fire', action: 'add' });

Parece um pequeno recurso social. Na prática, é o ciclo de feedback de produto mais barato que você vai montar. Lançar dez coisas num mês e ver quais duas levaram todas as reações mostra onde investir o mês seguinte, e custa ao usuário um clique em vez de uma pesquisa.

Escreva a entrada junto com o lançamento

Na prática, o problema não é escrever entradas ruins, é escrevê-las uma semana depois, de memória, todas de uma vez. A essa altura ninguém lembra por que a mudança importava, e você acaba com o registro de mensagens de commit sem ter escolhido isso.

No Kookee, a entrada nasce como rascunho enquanto o pull request ainda está aberto e é publicada quando o lançamento sai, sem deploy, sem rebuild, sem esperar um gerador de site estático. Escreva os rascunhos no painel ou com um assistente de programação conectado por MCP: ele lê as últimas entradas e escreve a próxima no mesmo tom, com tipo e versão, para você revisar.

Depois disso, basta um fetch para levá-la aonde você quiser:

TypeScript
const { data } = await kookee.changelog.list({ limit: 5 });

O seu site de marketing, o painel “Novidades” dentro do app, o e-mail de lançamento. Uma fonte só, escrita uma vez, pela pessoa que fez a mudança.