- Início
- Documentation
- Extensões
- Pipeline de Correspondência de Rulebook
Pipeline de Correspondência de Rulebook
Este documento descreve como o coding-agent descobre regras a partir de formatos de configuração suportados, normaliza-as em uma única estrutura Rule, resolve conflitos de precedência e divide o resultado em:
- Regras de Rulebook (disponíveis para o modelo via system prompt + URLs
rule://) - Regras TTSR (regras de interrupção de stream por viagem no tempo)
Ele reflete a implementação atual, incluindo semânticas parciais e metadados que são analisados mas não aplicados.
Arquivos de implementação
Seção intitulada “Arquivos de implementação”../src/capability/rule.ts../src/capability/index.ts../src/discovery/index.ts../src/discovery/helpers.ts../src/discovery/builtin.ts../src/discovery/cursor.ts../src/discovery/windsurf.ts../src/discovery/cline.ts../src/sdk.ts../src/system-prompt.ts../src/internal-urls/rule-protocol.ts../src/utils/frontmatter.ts
1. Estrutura canônica da regra
Seção intitulada “1. Estrutura canônica da regra”Todos os provedores normalizam os arquivos-fonte em Rule:
interface Rule { name: string; path: string; content: string; globs?: string[]; alwaysApply?: boolean; description?: string; ttsrTrigger?: string; _source: SourceMeta;}A identidade da capability é rule.name (ruleCapability.key = rule => rule.name).
Consequência: precedência e deduplicação são baseadas apenas no nome. Dois arquivos diferentes com o mesmo name são considerados a mesma regra lógica.
2. Fontes de descoberta e normalização
Seção intitulada “2. Fontes de descoberta e normalização”src/discovery/index.ts registra automaticamente os provedores. Para rules, os provedores atuais são:
native(prioridade100)cursor(prioridade50)windsurf(prioridade50)cline(prioridade40)
Provedor nativo (builtin.ts)
Seção intitulada “Provedor nativo (builtin.ts)”Carrega regras .xcsh de:
- projeto:
<cwd>/.xcsh/rules/*.{md,mdc} - usuário:
~/.xcsh/agent/rules/*.{md,mdc}
Normalização:
name= nome do arquivo sem.md/.mdc- frontmatter analisado via
parseFrontmatter content= corpo (frontmatter removido)globs,alwaysApply,description,ttsr_triggermapeados diretamente
Ressalva importante: globs é convertido como string[] | undefined sem filtragem de elementos neste provedor.
Provedor Cursor (cursor.ts)
Seção intitulada “Provedor Cursor (cursor.ts)”Carrega de:
- usuário:
~/.cursor/rules/*.{mdc,md} - projeto:
<cwd>/.cursor/rules/*.{mdc,md}
Normalização (transformMDCRule):
description: mantido apenas se for stringalwaysApply: apenastrueé preservado (falsetorna-seundefined)globs: aceita array (apenas elementos string) ou string únicattsr_trigger: apenas stringnamea partir do nome do arquivo sem extensão
Provedor Windsurf (windsurf.ts)
Seção intitulada “Provedor Windsurf (windsurf.ts)”Carrega de:
- usuário:
~/.codeium/windsurf/memories/global_rules.md(nome de regra fixoglobal_rules) - projeto:
<cwd>/.windsurf/rules/*.md
Normalização:
globs: array de strings ou string únicaalwaysApply,descriptionobtidos do frontmatterttsr_trigger: apenas stringnamea partir do nome do arquivo para regras de projeto
Provedor Cline (cline.ts)
Seção intitulada “Provedor Cline (cline.ts)”Busca ascendentemente a partir de cwd pelo .clinerules mais próximo:
- se diretório: carrega
*.mddentro dele - se arquivo: carrega arquivo único como regra nomeada
clinerules
Normalização:
globs: array de strings ou string únicaalwaysApply: apenas se booleanodescription: apenas stringttsr_trigger: apenas string
3. Comportamento do parsing de frontmatter e ambiguidade
Seção intitulada “3. Comportamento do parsing de frontmatter e ambiguidade”Todos os provedores usam parseFrontmatter (utils/frontmatter.ts) com estas semânticas:
- O frontmatter é analisado apenas quando o conteúdo começa com
---e possui um fechamento\n---. - O corpo é aparado após a extração do frontmatter.
- Se o parsing YAML falhar:
- um aviso é registrado,
- o parser recorre a uma análise simples de linhas
key: value(^(\w+):\s*(.*)$).
Consequências da ambiguidade:
- O parser de fallback não suporta arrays, objetos aninhados, regras de aspas ou chaves com hífen.
- Valores de fallback tornam-se strings (por exemplo
alwaysApply: truetorna-se a string"true"), então provedores que exigem tipos boolean/string podem descartar metadados. ttsr_triggerfunciona no fallback (chave com underscore); chaves comothinking-levelnão funcionariam.- Arquivos sem frontmatter válido ainda são carregados como regras com metadados vazios e corpo de conteúdo completo.
4. Precedência de provedores e deduplicação
Seção intitulada “4. Precedência de provedores e deduplicação”loadCapability("rules") (capability/index.ts) mescla as saídas dos provedores e depois deduplica por rule.name.
Modelo de precedência
Seção intitulada “Modelo de precedência”- Os provedores são ordenados por prioridade decrescente.
- Prioridade igual mantém a ordem de registro (
cursorantes dewindsurfconformediscovery/index.ts). - A deduplicação é por primeiro encontrado: o primeiro nome de regra encontrado é mantido; itens posteriores com o mesmo nome são marcados como
_shadowedemalle excluídos deitems.
A ordem efetiva dos provedores de regras atualmente é:
native(100)cursor(50)windsurf(50)cline(40)
Ressalva sobre ordenação intra-provedor
Seção intitulada “Ressalva sobre ordenação intra-provedor”Dentro de um provedor, a ordem dos itens vem da ordenação do resultado glob de loadFilesFromDir mais a ordem explícita de push. Isso é determinístico o suficiente para uso normal, mas não é explicitamente ordenado no código.
Diferenças notáveis na ordem das fontes:
nativeadiciona diretórios de configuração do projeto e depois do usuário.cursoradiciona resultados do usuário e depois do projeto.windsurfadicionaglobal_rulesdo usuário primeiro, depois regras do projeto.clinecarrega apenas a fonte.clinerulesmais próxima.
5. Divisão em buckets de Rulebook, Always-Apply e TTSR
Seção intitulada “5. Divisão em buckets de Rulebook, Always-Apply e TTSR”Após a descoberta de regras em createAgentSession (sdk.ts):
- Todas as regras descobertas são examinadas.
- Regras com
condition(chave de frontmatter;ttsr_trigger/ttsrTriggeraceitos como fallback) são registradas noTtsrManager. - Uma lista separada
rulebookRulesé construída com este predicado:
!registeredTtsrRuleNames.has(rule.name) && !rule.alwaysApply && !!rule.description- Uma lista
alwaysApplyRulesé construída:
!registeredTtsrRuleNames.has(rule.name) && rule.alwaysApply === trueComportamento dos buckets
Seção intitulada “Comportamento dos buckets”- Bucket TTSR: qualquer regra com
condition(description não é obrigatória). Tem prioridade sobre os outros buckets. - Bucket always-apply:
alwaysApply === true, não é TTSR. Conteúdo completo injetado no system prompt. Resolvível viarule://. - Bucket rulebook: deve ter description, não deve ser TTSR, não deve ser
alwaysApply. Listado no system prompt por nome+descrição; conteúdo lido sob demanda viarule://. - Uma regra com tanto
conditionquantoalwaysApplyvai apenas para TTSR (TTSR tem prioridade). - Uma regra com tanto
alwaysApplyquantodescriptionvai apenas para always-apply (não para rulebook).
6. Como os metadados afetam as superfícies em tempo de execução
Seção intitulada “6. Como os metadados afetam as superfícies em tempo de execução”description
Seção intitulada “description”- Obrigatório para inclusão no rulebook.
- Renderizado no bloco
<rules>do system prompt. - Description ausente significa que a regra não está disponível via
rule://e não é listada nas regras do system prompt.
- Transportado na
Rule. - Renderizado como entradas
<glob>...</glob>no bloco de regras do system prompt. - Exposto no estado da UI de regras (lista de modo
extensions). - Não é aplicado para correspondência automática neste pipeline. Não há matcher de glob em tempo de execução selecionando regras pelo arquivo atual/alvo da ferramenta.
alwaysApply
Seção intitulada “alwaysApply”- Analisado e preservado pelos provedores.
- Usado na exibição da UI (rótulo de trigger
"always"no gerenciador de estado de extensões). - Usado como condição de exclusão de
rulebookRules. - O conteúdo completo da regra é auto-injetado no system prompt (antes da seção de regras do rulebook).
- A regra também é acessível via
rule://<name>para releitura.
ttsr_trigger
Seção intitulada “ttsr_trigger”- Mapeado para
rule.ttsrTrigger. - Se presente, a regra é direcionada ao gerenciador TTSR, não ao rulebook.
7. Caminho de inclusão no system prompt
Seção intitulada “7. Caminho de inclusão no system prompt”buildSystemPromptInternal recebe tanto rules (rulebook) quanto alwaysApplyRules.
As regras always-apply são renderizadas primeiro, injetando seu conteúdo bruto diretamente no prompt.
As regras de rulebook são renderizadas em uma seção # Rules com:
Read rule://<name> when working in matching domain- O
name,descriptione lista opcional de<glob>de cada regra
Isso é consultivo/contextual: o texto do prompt solicita que o modelo leia as regras aplicáveis, mas o código não aplica a correspondência de glob.
8. Comportamento da URL interna rule://
Seção intitulada “8. Comportamento da URL interna rule://”RuleProtocolHandler é registrado com:
new RuleProtocolHandler({ getRules: () => [...rulebookRules, ...alwaysApplyRules] })Implicações:
rule://<name>resolve contra tanto rulebookRules quanto alwaysApplyRules.- Regras exclusivamente TTSR e regras sem description e sem
alwaysApplynão são acessíveis viarule://. - A resolução é por correspondência exata de nome.
- Nomes desconhecidos retornam erro listando os nomes de regras disponíveis.
- O conteúdo retornado é o
rule.contentbruto (frontmatter removido), tipo de conteúdotext/markdown.
9. Semânticas parciais / não aplicadas conhecidas
Seção intitulada “9. Semânticas parciais / não aplicadas conhecidas”- As descrições dos provedores mencionam arquivos legados (
.cursorrules,.windsurfrules), mas os caminhos de código do carregador atual não leem realmente esses arquivos. - Os metadados
globssão expostos ao prompt/UI mas não são aplicados pela lógica de seleção de regras. - A seleção de regras para
rule://inclui regras de rulebook e always-apply, mas não regras exclusivamente TTSR. - Avisos de descoberta (
loadCapability("rules").warnings) são produzidos mascreateAgentSessionatualmente não os exibe/registra neste caminho.