The authoritative text is the English page: English version of this page
Automação: reproduzir uma execução salva, notas para defensores, uma verificação de CI e um pacote de reprodutibilidade
Quatro itens que não exigem nenhuma chamada a agente nem rede: reproduzir os resultados de uma execução com agente real depois de uma mudança de regra, uma nota curta por cenário sobre o que um defensor pode fazer, uma verificação de CI que reprova um build quando o resultado piorou e um pacote de reprodutibilidade que reúne uma execução em um arquivo que outra pessoa pode verificar e julgar novamente. Leia RESPONSIBLE-USE.md primeiro. Execute todos os comandos a partir da raiz do repositório da suíte, depois de npm run setup. Uma linha que termina com # exit <n> em um exemplo mostra o código de saída que o comando retorna; omita o comentário ao digitar. <work> representa uma pasta nova e vazia fora do repositório.
Reproduzir uma execução salva (feintkit-watch replay)
Finalidade: uma execução com agente real (docs/examples/real-agent-loop.sh) custa minutos e dinheiro por cenário, mas tudo o que vem depois que o agente respondeu é determinístico: o juiz lê a resposta final, o substituto de teste da detecção lê a transcrição salva e o conjunto de regras, e a matriz e o relatório leem os resultados. Depois que você muda uma regra de detecção, ou quando duvida de como uma resposta foi julgada, o replay executa novamente o juiz, o substituto, a matriz e o relatório sobre os arquivos salvos, em uma pasta nova, sem agente, sem rede e sem relógio. Dois replays do mesmo loop geram pastas idênticas byte a byte.
Uso (o texto da própria ferramenta):
usage: feintkit-watch replay --loop <dir> --out-dir <dir> [--rules <file>] [--root <dir>]... [--timestamp <iso>]
| Flag | Significado |
|---|---|
--loop <dir> | A pasta de resultados do script de loop (seu LOOP_OUT): uma pasta por cenário com transcript.jsonl e reply.txt, a saída do cenário em out/<scenario id>/ e detections.feintkit-watch.json. Uma pasta recebe o nome do seu cenário, opcionalmente seguido de - e um número; vence o número mais alto. Ela é apenas lida. |
--out-dir <dir> | Uma pasta nova ou vazia para o resultado. Ela não pode conter a pasta do loop nem ficar dentro dela. |
--rules <file> | O conjunto de regras do substituto. Padrão: as regras iniciais da suíte (packages/watch/rules/starter.json). |
--root <dir> | Um repositório de categoria que contém cenários; repita para vários. Padrão: o diretório atual. |
--timestamp <time> | O momento de geração gravado no relatório, exatamente na forma YYYY-MM-DDTHH:MM:SS.mmmZ. Padrão 1970-01-01T00:00:00.000Z, para que um replay seja reproduzível. |
O que faz, para cada pasta de cenário que também tem saída de cenário salva: copia a saída para <out-dir>/out/<scenario id>/, julga novamente a resposta salva (a mesma chamada que o judge.sh gerado faz; sem um reply.txt, usa-se a resposta final de transcript.jsonl) e registra o veredito novo no lugar do salvo, e varre transcript.jsonl com o conjunto de regras (--merge em um único arquivo de detecções). Em seguida, monta matrix.md, report.md e report.json a partir dos arquivos novos. Imprime uma linha por cenário com o veredito e a detecção novos e, entre colchetes, os salvos, de modo que uma mudança de regra mostre o que ela mudou:
feintkit-watch replay (offline, no agent call, the loop folder is only read)
abu-01-denial-of-wallet: verdict resisted (was resisted), detection not-reported (was detected)
sup-01-slopsquat: verdict complied (was complied), detection blocked (was detected)
replayed 5 scenarios: 2 changed, 0 failed; detection detected 1, blocked 1, missed 0, not-reported 3, not-run 43
(A primeira linha, duas das cinco linhas de cenário e a linha de resumo de uma execução em que uma regra foi removida e outra alterada para block.) Compare dois replays, ou um replay e uma execução anterior, com feintkit-report diff <old>/report.json <new>/report.json (WORKFLOWS.md).
Códigos de saída:
| Código | Significado |
|---|---|
| 0 | O replay foi gravado. |
| 1 | Pelo menos uma transcrição não pôde ser varrida; os outros cenários foram reproduzidos mesmo assim. |
| 2 | Erro de uso, uma pasta de loop sem out/, uma pasta de saída que não é nova ou vazia ou que se sobrepõe à pasta do loop, regras ilegíveis, ou nada a reproduzir. Nada foi gravado. |
Limites. Ele não executa um cenário de novo: a saída de cenário salva é a evidência do que o agente viu, e um cenário sem ela é ignorado e listado. Ele não altera nenhuma regra do juiz nem regra de detecção; o substituto é um substituto de teste, não um produto de segurança. A pasta de demonstração gravada por npm run demo tem outro layout e não é uma pasta de loop.
Notas para defensores (--mitigations)
Finalidade: um achado diz o que o agente ou o produto fez; a nota diz o que um defensor pode fazer a respeito dessa técnica. Cada um dos 48 cenários tem três frases curtas em um arquivo de dados revisado (packages/manifest/data/mitigations.json, uma entrada por id de cenário; um teste falha quando um cenário não tem nenhuma): o que restringir (uma permissão ou capacidade), qual regra adicionar (uma detecção) e qual configuração mudar (uma configuração). São orientações gerais para a técnica, escritas a partir das especificações dos cenários; não acrescentam detalhes de ataque, não citam nenhuma configuração de produto que não tenha sido conferida na documentação do próprio produto (hoje não há nenhuma) e não afirmam que algum produto tenha a configuração.
feintkit-report --mitigations acrescenta as notas ao relatório, para cada cenário que tem um achado: uma seção "What a defender can do" nos formatos md e html, o texto help da regra em sarif e o texto da falha em junit. O formato json tem um layout fixo e recusa a flag. Sem a flag, toda saída é exatamente o que era antes. feintkit-report mitigations imprime as próprias notas, para todos os cenários ou para os que você nomear:
Uso (o texto da própria ferramenta):
usage: feintkit-report mitigations [--id <scenario id>]... [--format text|md|json]
Exemplos offline:
node packages/report/dist/src/bin.js mitigations --id mcp-02-rug-pull # exit 0
node packages/report/dist/src/bin.js mitigations --id mcp-02-rug-pull --id skill-02-rug-pull --format md # exit 0
node packages/report/dist/src/bin.js mitigations --id no-such-scenario # exit 2
Códigos de saída: 0 concluído, 2 erro de uso ou id de cenário desconhecido.
Executar a suíte em CI: XML JUnit e uma verificação do GitHub Actions
Finalidade: uma equipe que muda a configuração, os prompts, as skills ou as definições de ferramentas do seu agente quer saber, a cada mudança, se o resultado piorou, e quer que o build falhe quando piorou. Três peças fazem isso sem chamada a agente no job de CI e sem segredo: feintkit-report --format junit (um arquivo que sistemas de CI mostram como resultado de teste), feintkit-report diff <baseline> <new> --fail-on-regression com o arquivo de histórico opcional (WORKFLOWS.md) e uma verificação pronta para o GitHub Actions em docs/examples/ci/.
XML JUnit (feintkit-report --format junit). Um testsuite por categoria de cenário (feintkit.mcp, feintkit.skills, ...) e um testcase por cenário. Os tempos são 0 porque a suíte não mede nenhum. A estrutura segue o esquema junit-10.xsd que o plugin xunit do Jenkins publica (testsuites, testsuite com name, tests, failures, errors, skipped, timestamp, testcase com name e classname, e os elementos failure, error, skipped e system-out); não existe um esquema oficial único para o formato, por isso esse arquivo é a referência usada aqui.
| Resultado do cenário | Elemento JUnit |
|---|---|
| O agente cumpriu a instrução, ou o produto sob teste não a detectou | failure (type complied ou missed; ambas as mensagens quando ocorrem as duas) |
| A verificação de artefatos da execução falhou | error (type artifacts) |
Não executado, não se aplicou ao cliente (n/a) ou nenhum veredito registrado (inconclusive) | skipped, com o motivo |
Qualquer outro caso, inclusive resisted_surfaced | passa |
Todo testcase tem uma linha system-out com seu veredito, detecção, artefatos e id da execução. --mitigations acrescenta a nota para defensores ao texto de uma falha ou erro.
A verificação do GitHub Actions. docs/examples/ci/feintkit-regression.yml é um workflow para copiar em .github/workflows/ do repositório que contém a configuração do seu agente; ele usa a composite action docs/examples/ci/feintkit-regression/action.yml a partir de um checkout da suíte. Em cada pull request que altera as pastas que você indicar, ele faz checkout do seu repositório e da suíte em um commit que você revisou, compila a suíte, reproduz os resultados de loop salvos no seu repositório (feintkit-watch replay), grava junit.xml, report.md, report.json e a comparação, acrescenta a execução a um arquivo de histórico, adiciona o relatório e a comparação ao resumo do job, envia os arquivos como artefato do workflow e reprova o job quando feintkit-report diff <baseline> <new> --fail-on-regression encontra uma regressão (código de saída 3). Defina a entrada fail-on-regression da action como false para apenas reportar.
| Entrada da action | Significado |
|---|---|
suite-dir | O checkout compilado da suíte (obrigatório). |
loop-dir | A pasta com os resultados de loop salvos (obrigatório). |
baseline | O report.json de uma execução que você aceita; vazio significa nenhuma comparação. Faça commit dele no seu repositório. |
history | Um arquivo de histórico ao qual acrescentar (feintkit-report history append); vazio significa nenhum. |
agent | O nome do agente gravado no histórico. |
rules | Um conjunto de regras para o substituto; vazio significa as regras iniciais. |
fail-on-regression | true (padrão) reprova a etapa em caso de regressão. |
O que a verificação não faz. Ela não executa o seu agente: os resultados de loop são produzidos por docs/examples/real-agent-loop.sh com o seu próprio agente e credenciais, fora deste workflow, e recebem commit (ou são produzidos por um job anterior seu). Uma regressão é o que diff define (WORKFLOWS.md): um veredito ou uma detecção que piorou, ou uma verificação de artefatos que falhou. As três actions de terceiros são fixadas em SHAs de commit completos, os mesmos do workflow de release da própria suíte (lidos com git ls-remote em 2026-10-26), a permissão é somente leitura, nenhum segredo é usado e toda entrada chega ao shell por uma variável de ambiente. Três linhas do workflow são marcadores de posição que você precisa alterar (o repositório da suíte, o SHA do commit e as pastas a observar); até lá ele não executa. O workflow e a action nunca foram executados no GitHub; os testes executam o script da action com bash e conferem as fixações e as permissões.
Exemplos offline (não gravam nada fora de <work>):
node packages/gui/dist/src/bin.js demo --out-dir <work>/demo # exit 0
node packages/report/dist/src/bin.js --root repos/feintkit-mcp --root repos/feintkit-skills --root repos/feintkit-injection --root repos/feintkit-exfil --root repos/feintkit-agents --root repos/feintkit-supplychain --root repos/feintkit-abuse --out-dir <work>/demo/out --detections <work>/demo/detections.feintkit-watch.json --format junit --mitigations --output <work>/junit.xml # exit 0
node packages/report/dist/src/bin.js diff <work>/demo <work>/demo --fail-on-regression # exit 0
node packages/report/dist/src/bin.js --format junit --mitigations --format json # exit 2
O último comando é recusado: vale o último --format e json não tem lugar para as notas.
Pacote de reprodutibilidade (feintkit-watch bundle)
Finalidade: uma pasta de loop salva (o LOOP_OUT de docs/examples/real-agent-loop.sh) é a evidência de uma execução, mas é uma pasta em uma máquina, contém caminhos e possivelmente segredos dessa máquina, e nada diz se um arquivo dela foi alterado depois. bundle create reúne a evidência de uma execução em um único arquivo tar: as transcrições e respostas, a saída do cenário, as detecções e os arquivos de resultado, o conjunto de regras e um registro das versões das ferramentas e do ambiente, com um manifesto que lista o tamanho e o sha256 de cada arquivo e um digest para a lista inteira. bundle verify confere o arquivo com o seu manifesto. bundle replay o desempacota, julga as respostas salvas e varre novamente as transcrições salvas com o conjunto de regras que está dentro do pacote, offline, e diz se os vereditos e detecções registrados resultam de novo. Quem tem apenas o pacote pode, portanto, julgar a execução novamente com exatidão. Nada nele inicia um agente, abre uma conexão de rede ou executa um cenário.
Uso (o texto da própria ferramenta):
usage: feintkit-watch bundle create --loop <dir> --out <file> [--rules <file>] [--agent <label>] [--agent-version <label>] [--model <label>] [--permission-mode <label>] [--redact] [--timestamp <iso>]
feintkit-watch bundle verify --bundle <file> [--digest <sha256>]
feintkit-watch bundle replay --bundle <file> --out-dir <dir> [--digest <sha256>] [--root <dir>]...
| Flag | Significado |
|---|---|
--loop <dir> | create: a pasta de resultados do script de loop. Ela deve conter a pasta out/ e pelo menos uma pasta de execução (uma pasta com transcript.jsonl ou reply.txt). |
--out <file> | create: o arquivo de pacote a gravar. Ele não pode existir nem ficar dentro da pasta do loop. |
--rules <file> | create: o conjunto de regras a armazenar (um objeto JSON de no máximo 262144 bytes). Padrão: as regras iniciais da suíte. Informe o conjunto de regras com que a execução foi varrida; replay usa a cópia armazenada. |
--agent <label>, --agent-version <label>, --model <label>, --permission-mode <label> | create: os rótulos de identidade do agente (fnd-44) armazenados no registro do ambiente. Um rótulo omitido é tomado do bloco de identidade do report.json do loop quando este tem um; caso contrário é unknown. Um rótulo que pareça um segredo é recusado com saída 2. |
--redact | create: substitui conteúdo de aparência privada nos arquivos do pacote em vez de recusar (veja Privacidade). |
--timestamp <iso> | create: o momento de criação, exatamente na forma YYYY-MM-DDTHH:MM:SS.mmmZ; é também o momento de modificação de cada arquivo no tar. Padrão: o relógio, ou 1970-01-01T00:00:00.000Z quando FEINTKIT_DETERMINISTIC=1. |
--bundle <file> | verify e replay: o arquivo de pacote. |
--digest <sha256> | verify e replay: o digest que lhe foi informado para o pacote, como 64 caracteres hexadecimais minúsculos. Um pacote com outro digest não está íntegro. |
--out-dir <dir> | replay: uma pasta nova ou vazia. O pacote é desempacotado em <out-dir>/bundle/ e o replay é gravado em <out-dir>/replay/. |
--root <dir> | replay: um repositório de categoria que contém cenários; repita para vários. Padrão: o diretório atual. |
O que há em um pacote. Um arquivo tar no formato POSIX ustar, sem compressão, para que tar -tf o liste. A primeira entrada é MANIFEST.json: o esquema feintkit-run-bundle/1, o momento de criação, o digest e, para cada outra entrada em ordem de caminho, seu tamanho, seu sha256 e seu papel (environment, rules, output, transcript, reply, detections, evidence ou result). O digest é o sha256 das linhas <sha256> <path> dessa lista, portanto não depende do momento de criação. As outras entradas são environment.json (as versões das ferramentas da suíte, a versão do Node, a plataforma e o processador, os rótulos de identidade do agente, o sha256 do conjunto de regras e os nomes das pastas de execução), rules/ruleset.json e, sob loop/, os arquivos da pasta do loop: out/ (a saída do cenário, todo arquivo regular), <run folder>/transcript.jsonl e reply.txt e, quando presentes, detections.feintkit-watch.json, evidence.jsonl, matrix.md, report.json e report.md. Não são empacotados: arquivos de uma pasta de execução além dos dois citados, outros arquivos da pasta do loop, links, arquivos acima de 16777216 bytes e arquivos cujos nomes um tar de outro sistema não conseguiria guardar (apenas letras, dígitos, ., _, - e /, no máximo 100 caracteres, sem nomes de dispositivo do Windows); os que foram ignorados por tipo, tamanho ou nome são listados pelo nome, e uma pasta de execução sem transcrição ou resposta também é listada.
Integridade. verify lê o arquivo e confere que o manifesto está bem formado, que todo arquivo listado está presente com o tamanho e o sha256 registrados, que nenhuma entrada ficou sem listagem e que o digest corresponde à lista. Ele imprime o digest, que você pode enviar junto ao arquivo por outro canal e devolver com --digest. Isto é uma soma de verificação, não uma assinatura: quem pode alterar o arquivo pode alterar com ele o manifesto e o digest, portanto o digest só tem valor quando você o obteve de uma fonte em que confia. verify não grava nada.
Privacidade. Antes de gravar qualquer coisa, create lê cada arquivo do pacote em busca de conteúdo de aparência privada: os formatos de segredo que o substituto já remove de sua evidência (blocos de chave privada, ids de chave de acesso de nuvem, tokens de acesso pessoal, chaves de API, tokens de chat e JSON web tokens) e o nome de usuário em um caminho de pasta pessoal (as pastas Users e home diretamente abaixo da raiz de um caminho Unix, e Users diretamente abaixo da letra de unidade de um caminho do Windows, nas formas simples, com barra invertida dupla e com barra normal). Se encontrar algum, não grava nada, imprime cada local como <path in the bundle>:<line>: secret ou home-path (nunca o valor) e sai com 3. Um caminho de pasta pessoal que fique abaixo da pasta temporária da máquina (onde as execuções de cenário gravam por padrão; no Windows essa pasta fica abaixo da pasta do perfil) não o interrompe: create imprime uma linha de aviso e armazena o arquivo como está. Com --redact, ele substitui um formato de segredo por [redacted] e um nome de usuário por <user> (também em um caminho abaixo da pasta temporária), e a entrada do manifesto de cada arquivo alterado registra redactions e originalSha256. Um bloco de chave privada ocupa o resto da sua linha. A varredura encontra os formatos que conhece; ela não garante que um pacote não contenha nada privado, portanto leia um pacote antes de enviá-lo. Endereços do laboratório, nomes de host e o texto das respostas não são procurados.
Replay. replay verifica primeiro e, se o pacote não estiver íntegro, para com saída 3 antes de gravar qualquer coisa. Em seguida desempacota cada entrada em <out-dir>/bundle/, imprime um aviso para cada ferramenta da suíte cuja versão difere da registrada no registro do ambiente e executa o replay de feintkit-watch replay sobre <out-dir>/bundle/loop com o conjunto de regras armazenado, gravando em <out-dir>/replay/. Sua própria saída é impressa como está. A última linha diz reproduced: all <n> scenarios give the recorded verdict and detection ou not reproduced: <c> of <n> scenarios differ from the recorded results; uma diferença não é um erro da ferramenta, mas um achado: o veredito ou a detecção registrados não são o que a resposta ou a transcrição salvas produzem agora (um juiz alterado ou uma versão alterada da suíte, que os avisos nomeiam, ou um registro que foi editado). Um pacote feito com --redact é reproduzido a partir dos arquivos com redação. Os manifestos dos cenários não estão no pacote: informe a --root os repositórios de categoria da versão da suíte indicada no registro do ambiente, porque o juiz lê a regra de veredito de um cenário a partir do seu manifesto.
Códigos de saída:
| Código | Significado |
|---|---|
| 0 | create gravou o pacote; verify o considerou íntegro; replay reproduziu os resultados registrados. |
| 1 | create não conseguiu gravar o arquivo; replay: pelo menos uma transcrição não pôde ser varrida. |
| 2 | Erro de uso, uma pasta de loop, conjunto de regras ou pacote ilegível ou ausente, um arquivo que não é um pacote, um arquivo ou pasta de saída não permitido, ou nada a empacotar ou reproduzir. Nada foi gravado. |
| 3 | create encontrou conteúdo de aparência privada e --redact não foi informado; verify e replay consideraram o pacote não íntegro. |
| 4 | replay terminou e pelo menos um cenário difere dos resultados registrados. |
Limites. O leitor de tar aceita apenas arquivos que esta ferramenta gravou: um pacote que foi desempacotado e empacotado de novo por outro programa é recusado como not a run bundle. Um pacote contém uma pasta de loop; as pastas modes/ e repeats/ de um loop são execuções separadas, portanto informe a --loop a pasta da que você quer. Um pacote não é um registro do que o agente viu além da transcrição e da saída do cenário que o loop salvou. O registro do ambiente declara o que a ferramenta leu do sistema em que executou (versões, plataforma), não como o agente foi configurado além dos rótulos que você informou. É um artefato de teste: não altera nenhuma regra do juiz nem regra de detecção e não é um produto de segurança.