Aliyansayz/agent-skills

Melhore a qualidade do código TypeScript substituindo nomes obscuros, tipos inseguros, lógica duplicada, responsabilidades misturadas, valores mágicos e tratamento frágil de erros por código legível, sustentável e fortemente tipado. Use ao revisar, refatorar, depurar ou estender aplicações TypeScript existentes, especialmente sistemas CRM de vendas.

O que é agent-skills?

Este skill capacita um agente de IA, como Claude Code ou Cursor, a atuar como um especialista em qualidade de código TypeScript, com foco na melhoria de código existente para torná-lo mais compreensível, sustentável e testável. Ao invés de refatorar por mera sofisticação, a skill orienta o agente a priorizar nomes específicos do domínio, tipagem forte e separação clara de responsabilidades, especialmente em sistemas CRM de vendas. O skill fornece um workflow passo a passo que inclui entender o contexto, registrar o comportamento atual, melhorar nomenclatura, refinar tipos e estruturas de dados, extrair regras de negócio, separar responsabilidades, lidar com erros de forma explícita e adicionar testes. Apoiado em uma tabela detalhada de problemas comuns do TypeScript, o skill transforma o agente em uma ferramenta robusta para revisão e refatoração de código, garantindo que comportamentos intencionais sejam preservados durante a melhoria da qualidade.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Aliyansayz/agent-skills/tree/HEAD/typescript-code-quality

Installed? Explore more Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Qualidade de Código Contextual — Skill para Agente TypeScript

1. Propósito

Aja como um agente de qualidade de código TypeScript que torna o código existente mais fácil de entender, manter, testar e estender.

Não refatore o código apenas para parecer sofisticado. Melhore-o para que os desenvolvedores possam entender:

  • O que cada função faz.
  • Por que uma regra de negócio existe.
  • O que cada variável representa.
  • Quais dados uma função espera e retorna.
  • O que acontece quando os dados estão ausentes ou são inválidos.
  • Quais partes da aplicação são responsáveis pela lógica de negócio, acesso a dados e interação com o usuário.
  • Como uma alteração afeta o comportamento existente da aplicação.

Use linguagem específica do domínio em vez de nomes de variáveis e funções vagos.

Ao trabalhar com código CRM de Vendas, use conceitos de negócio claros como Lead, Contact, Opportunity, SalesRepresentative, LeadStatus, PipelineStage e FollowUpDate.

O objetivo é um software compreensível, fortemente tipado, confiável, testável e sustentável.

2. Quando Ativar

Use este skill quando:

  • O código TypeScript contém variáveis como x, data, obj, temp, thing ou result sem contexto suficiente.
  • Funções têm nomes vagos como process(), handle(), manage() ou doStuff().
  • Uma função realiza validação, cálculos de negócio, atualizações de banco de dados, notificações e logging tudo de uma vez.
  • A aplicação depende de any, asserções de tipo inseguras, strings inexplicadas ou números mágicos.
  • Regras de negócio estão duplicadas em vários lugares.
  • Erros são engolidos silenciosamente ou convertidos em respostas de sucesso enganosas.
  • Funções contêm condições profundamente aninhadas ou ramificações excessivas.
  • A terminologia CRM é inconsistente entre componentes, endpoints de API e modelos de banco de dados.
  • O código é difícil de testar sem conectar-se a um banco de dados real ou serviço externo.
  • Um desenvolvedor deseja melhorar o código existente sem alterar seu comportamento pretendido.

3. Princípios Fundamentais

3.1 Prefira nomes específicos do domínio

Os nomes devem explicar seu significado na aplicação.

Prefira:

const leadId = "lead_123";
const salesRepresentativeId = "user_456";
const nextFollowUpDate = new Date();
const qualifiedLeadCount = 12;

Evite:

const id = "lead_123";
const user = "user_456";
const date = new Date();
const count = 12;

Nomes curtos são aceitáveis quando seu significado é óbvio dentro de um escopo pequeno, como i em um loop curto. Não expanda cada nome mecanicamente; expanda nomes quando contexto adicional melhora a compreensão.

3.2 Use TypeScript para representar conceitos de negócio

Prefira tipos explícitos, interfaces, uniões discriminadas e modelos de domínio nomeados em vez de objetos não estruturados.

Evite usar any como uma saída de emergência. Use unknown para dados genuinamente não confiáveis e valide-os antes de usar.

3.3 Separe responsabilidades

Cada função ou módulo deve ter uma responsabilidade primária clara.

Um serviço CRM não deve ter que construir respostas HTTP, manipular componentes de UI, enviar e-mails e executar consultas de banco de dados em uma única função.

3.4 Preserve o comportamento pretendido

Antes de refatorar, identifique as regras de negócio existentes e os resultados esperados.

Não altere silenciosamente:

  • Critérios de qualificação de Lead.
  • Regras de transição de Pipeline.
  • Atribuições de Representantes de Vendas.
  • Regras de agendamento de Follow-up.
  • Comportamento de detecção de duplicatas.
  • Permissões e controles de acesso.
  • Formatos de resposta da API.
  • Semântica do banco de dados.

Se o comportamento existente parecer incorreto ou ambíguo, identifique a preocupação explicitamente em vez de disfarçar uma mudança comportamental como uma refatoração.

3.5 Prefira código simples a abstrações desnecessárias

Não introduza padrões de design, classes, genéricos, fábricas ou dependências adicionais, a menos que resolvam um problema real.

Uma função direta com um nome descritivo é muitas vezes melhor do que uma abstração desnecessariamente elaborada.


4. Exemplo de CRM de Vendas Mal Escrito

O código a seguir é intencionalmente problemático. Ilustra problemas comuns de qualidade de código em uma aplicação de gerenciamento de leads.

4.1 Antes: Código mal escrito

// bad-crm.ts

export async function go(d: any, db: any, mail: any) {
    try {
        let x = d.name;
        let e = d.email;
        let p = d.phone || "";
        let s = d.status || "new";
        let v = Number(d.value || 0);
        let u = d.user || null;

        if (!x || !e) {
            return { ok: false, msg: "bad data" };
        }

        let old = await db.leads.findOne({ email: e });

        if (old && old.status != "lost") {
            old.v = old.v + v;
            old.s = v > 5000 ? "hot" : old.s;
            old.p = p || old.p;
            await db.leads.update(old.id, old);

            if (old.s == "hot") {
                await mail.send(
                    old.email,
                    "Hot lead",
                    "Lead is hot!"
                );
            }

            return { ok: true, data: old };
        }

        let a = {
            name: x,
            email: e,
            phone: p,
            status: s,
            value: v,
            user: u,
            created: new Date(),
            updated: new Date(),
        };

        let r = await db.leads.insert(a);

        if (v > 5000) {
            await mail.send(
                e,
                "Hot lead",
                "Lead is hot!"
            );
        }

        return { ok: true, data: r };
    } catch (e) {
        console.log(e);
        return { ok: false, msg: "error" };
    }
}

4.2 Problemas que o agente deve identificar

ProblemaExemploPor que é importanteMelhoria
Nome de função pouco clarogo()Não comunica a operação de negócioUse createOrUpdateLead() se descrever com precisão o comportamento
Variáveis pouco clarasd, x, e, p, s, v, u, a, rDesenvolvedores devem inferir o propósito de cada variávelUse nomes específicos do domínio
Tipos insegurosany para entrada, banco de dados e serviço de e-mailRemove a capacidade do TypeScript de detectar muitos errosDefina interfaces e tipos de entrada explícitos
Regra de negócio ocultav > 5000O limite de qualificação não é explicadoDefina uma constante nomeada ou regra de negócio documentada
Terminologia inconsistentestatus, hot, lostStatus do lead e qualificação podem representar conceitos diferentesDefina um modelo explícito de status de lead
Responsabilidades misturadasUma função valida, consulta, atualiza, cria, envia e-mail e trata errosComportamentos individuais são difíceis de testarSepare responsabilidades de aplicação, domínio e infraestrutura
Potencial inconsistência de dadosUma atualização de banco de dados pode ser bem-sucedida antes de um e-mail falharO chamador pode receber um erro mesmo que o lead tenha sido salvoDefina o comportamento de falha de notificação explicitamente
Validação fracaApenas verifica x e eEndereços de e-mail inválidos, valores ruins e campos malformados podem entrar no sistemaValide a entrada e invariantes de negócio
Regras de status implícitasLeads existentes são atualizados a menos que seu status seja "lost"O significado desta regra está ocultoNomeie e documente a política de atualização
Contrato de persistência pouco clarodb.leads.findOne() e .update() usam formas não documentadasSuposições de banco de dados são difíceis de verificarDefina uma interface de repositório
Resposta de erro genérica"error"Perde contexto útil e complica a solução de problemasTrate falhas esperadas explicitamente e registre falhas inesperadas apropriadamente
Respostas inconsistentes{ ok, msg } e { ok, data }Os chamadores devem inferir quais campos existem em cada casoUse um tipo de resultado discriminado ou modelo de erro de aplicação consistente
Dados mutáveis e com forma frouxaold.v, old.s, old.pNomes de campos não correspondem ao modelo persistido aparenteDefina um tipo Lead consistente
Política de duplicatas pouco claraRegistros existentes são mesclados por e-mailO significado exato da mesclagem está ocultoDocumente quais campos podem ser atualizados e como o valor é agregado
Dependências difíceis de testarBanco de dados e serviço de e-mail são passados como anyContratos e casos de falha não são verificados pelo compiladorDefina interfaces estreitas e injete dependências

Importante: Este é um exemplo ilustrativo, não uma implementação CRM de produção completa. Uma refatoração deve primeiro confirmar o comportamento real do CRM existente, modelo de dados, semântica de persistência e regras de negócio.


5. Fluxo de Trabalho de Refatoração

Siga este fluxo de trabalho ao melhorar o código TypeScript existente.

Passo 1: Entenda o contexto

Inspecione o código relevante antes de modificá-lo.

Identifique:

  • O propósito da função.
  • Seus chamadores e dependências.
  • Seus formatos de entrada e saída.
  • O esquema do banco de dados ou contrato do repositório.
  • Entidades de domínio e terminologia de negócio.
  • Regras de validação e autorização existentes.
  • Testes atuais e comportamento esperado.
  • Tratamento de erros e efeitos colaterais.

Leia os módulos circundantes quando necessário. Não infira o contrato completo de uma função apenas pelo seu nome.

Passo 2: Registre o comportamento atual

Descreva a lógica existente em linguagem simples.

Para o exemplo acima, o comportamento observado é:

  1. Ler detalhes do lead da entrada.
  2. Rejeitar uma solicitação se o nome ou e-mail estiver ausente.
  3. Encontrar um lead existente por e-mail.
  4. Se um lead correspondente existir e seu status não for "lost", adicionar o valor submetido ao valor existente.
  5. Marcar esse lead existente como "hot" quando o valor resultante exceder o limite.
  6. Substituir seu número de telefone quando um novo número de telefone não vazio for fornecido.
  7. Atualizar o registro e enviar uma notificação se o status resultante for "hot".
  8. Caso contrário, criar um novo registro com timestamps.
  9. Notificar o lead quando seu valor submetido exceder o limite.
  10. Retornar um objeto de sucesso ou falha.

Esta descrição distingue intencionalmente comportamento de implementação observado de comportamento de negócio pretendido. Por exemplo, o código testa o valor resultante do registro existente para um caminho de notificação, mas o valor submetido para outro. Não trate silenciosamente essas regras como equivalentes.

Passo 3: Melhore a nomenclatura

Substitua nomes genéricos por nomes que expressem seu papel.

Nome ruimNome melhor
gocreateOrUpdateLead
dleadInput
xleadName
eemailAddress, ou error em um bloco catch
pphoneNumber
sleadStatus
vleadValue
usalesRepresentativeId
oldexistingLead
anewLead
rcreatedLead
dbleadRepository ou databaseClient, dependendo de seu papel real
mailemailNotificationService

O nome melhorado deve representar com precisão o valor. Não renomeie um valor para salesRepresentative se for apenas um identificador de string.

Passo 4: Refine tipos e estruturas de dados

Substitua any por tipos explícitos.

Defina uma interface para a entrada do lead:

interface LeadInput {
  name: string;
  email: string;
  phone?: string;
  status?: LeadStatus;
  value?: number;
  salesRepresentativeId?: string;
}

Defina um tipo para status do lead:

type LeadStatus = "new" | "contacted" | "qualified" | "hot" | "lost" | "closed";

Defina um modelo para o lead persistido:

interface Lead {
  id: string;
  name: string;
  email: string;
  phone: string;
  status: LeadStatus;
  value: number;
  salesRepresentativeId: string | null;
  createdAt: Date;
  updatedAt: Date;
}

Defina uma interface para o repositório:

interface LeadRepository {
  findByEmail(email: string): Promise<Lead | null>;
  update(id: string, lead: Partial<Lead>): Promise<Lead>;
  insert(lead: Omit<Lead, "id">): Promise<Lead>;
}

Defina uma interface para o serviço de notificação:

interface NotificationService {
  send(email: string, subject: string, body: string): Promise<void>;
}

Passo 5: Extraia regras de negócio

Defina constantes e funções que expliquem as regras de negócio.

const HOT_LEAD_VALUE_THRESHOLD = 5000;

function isLeadHot(leadValue: number): boolean {
  return leadValue > HOT_LEAD_VALUE_THRESHOLD;
}

function isExistingLeadUpdatable(status: LeadStatus): boolean {
  return status !== "lost";
}

function mergeLeadValues(existingLead: Lead, submittedValue: number): number {
  return existingLead.value + submittedValue;
}

Passo 6: Separe responsabilidades

Divida a função em camadas de aplicação, domínio e infraestrutura.

  • Camada de aplicação: orquestra o fluxo de trabalho. Contém a função createOrUpdateLead.
  • Camada de domínio: contém regras de negócio. Contém funções como isLeadHot, isExistingLeadUpdatable, mergeLeadValues.
  • Camada de infraestrutura: lida com persistência e comunicação externa. Contém implementações de LeadRepository e NotificationService.

Passo 7: Lide com erros explicitamente

Evite blocos catch genéricos que engolem todas as exceções.

Use tipos de resultado ou tipos de união para representar sucesso e falha:

type Result<T> =
  | { success: true; data: T }
  | { success: false; error: string };

async function createOrUpdateLead(
  leadInput: LeadInput,
  leadRepository: LeadRepository,
  notificationService: NotificationService
): Promise<Result<Lead>> {
  // ... validação e lógica de negócio ...
}

Passo 8: Teste o comportamento, não a implementação

Escreva testes que verifiquem as regras de negócio e os cenários de erro, não a estrutura interna do código.

// Exemplo de teste (framework: vitest ou jest)
import { describe, it, expect } from "vitest";

describe("createOrUpdateLead", () => {
  it("deve criar um novo lead quando o e-mail não existe", async () => {
    // ... setup e asserções ...
  });

  it("deve atualizar um lead existente quando o status não é 'lost'", async () => {
    // ... setup e asserções ...
  });

  it("deve retornar erro quando nome ou e-mail estão ausentes", async () => {
    // ... setup e asserções ...
  });
});

6. Notas Adicionais

  • Sempre confirme o comportamento real do sistema antes de refatorar. O código existente pode conter bugs que os usuários esperam ou nos quais confiam.
  • Consulte a documentação existente, testes e outros desenvolvedores para garantir uma compreensão completa.
  • Se uma regra de negócio não estiver documentada, levante uma questão em vez de assumir.
  • Refatore em etapas pequenas e verificáveis. Execute testes após cada alteração.
  • Prefira simplicidade. Se uma função de 10 linhas com um bloco if-else for suficiente, não introduza uma máquina de estados ou padrão estratégia.

Este skill foi adaptado de princípios de engenharia de software para melhorar a qualidade de código TypeScript, com ênfase na clareza de domínio e sustentabilidade.

Habilidades Relacionadas