Verificação contínua — do GitHub para a rede de ontologias¶
Como uma execução do GitHub Actions vira conceito, e por que o estado da verificação mora em três lugares diferentes.
Esta página é escrita à mão. As tabelas de mapeamento em mappings.md são geradas da base — aqui está o porquê que a tabela não carrega.
Os dois eixos, e por que separá-los¶
Um painel de CI responde "passou ou quebrou". Isso não precisa de ontologia. A pergunta que precisa é o que passou ou quebrou — porque teste vermelho tem resposta diferente de inspeção vermelha: um é código, o outro é convenção.
Por isso a modelagem tem dois eixos independentes, e um terceiro que é de outra API:
| Eixo | Pergunta | Vem de |
|---|---|---|
| tipo | que processo esta execução materializa | os jobs, derivado |
| fase | como esse processo terminou | status + conclusion da execução |
| gatilho | o que a disparou | event da execução |
Cruzá-los é o que produz medida. Colapsá-los produz um número que parece confiável e não é.
Eixo 1 — o tipo é derivado dos jobs, nunca afirmado pela execução¶
A versão 1 do mapeamento afirmava que toda execução de workflow é uma ocorrência de
processo de integração contínua. O dado desmentiu. Das 1.051 execuções coletadas em
2026-08-18, 399 não são nem verificação nem implantação: Sync to GitLab,
Sprint Rollover, Card de promoção.
A regra que decide está em
priv/knowledge_base/rules/github_ci_job_routing.yaml,
com confidence: low declarada, e a razão da confiança baixa está escrita nela: o
GitHub não declara qual processo componente um job executa, e o nome é convenção de quem
escreveu o workflow.
| nome ou etapa casa | conceito | ontologia |
|---|---|---|
build compile assets docker image |
ciro.continuous_build_process |
CIRO |
test spec coverage e2e pytest jest |
ciro.continuous_test_process |
CIRO |
lint credo sobelow dialyzer gates sast |
ciro.continuous_inspection_process |
CIRO |
deploy rollout helm kubectl argocd |
cdro.deployment_activity |
CDRO |
release publish delivery |
cdro.delivery_activity |
CDRO |
Três decisões nessa tabela, e nenhuma é detalhe.
Devolve todos os que casam, não o primeiro¶
Job que testa e inspeciona materializa dois componentes. Escolher um e descartar os outros faria a plataforma afirmar que o job só testa quando ele também inspeciona.
Quando mais de um casa, o job é reportado como ci.ap01.monolithic_job — e o
agrupamento é fato sobre o script, não sobre a execução. Por isso a tela nomeia o
arquivo, não o nome do job: dois repositórios com um job chamado build não são a mesma
linha. O antipadrão mais frequente na instalação é o deste próprio projeto —
.github/workflows/ci.yml, job quality-gates, 352 execuções.
O custo do agrupamento é exatamente a pergunta desta página não ter resposta: a plataforma não sabe o que quebrou.
Deploy sai da CIRO¶
deploy não é componente de integração contínua. É CDRO. Manter os dois na mesma
ontologia faria a medida de integração incluir implantação, e implantação tem outro
ciclo, outro responsável e outro risco.
Sem componente reconhecido, a execução fica sem tipo¶
A rede não tem conceito para automação de quadro. Forçar Card de promoção num conceito
de verificação produziria medida errada; deixá-la sem tipo é ausência nomeada, e a
tela nunca escreve as duas situações com a mesma frase.
Os padrões são estreitos de propósito¶
artifact casava com Upload Pages artifact e produziu 238 entregas falsas.
package casava com Install npm packages. Os dois foram removidos.
A assimetria é a razão: o padrão não reconhecido alguém corrige — aparece na tela como lacuna e vira issue. O padrão reconhecido errado vira medida, e ninguém procura o erro num número que já parece resposta.
Eixo 2 — a fase vem de status mais conclusion¶
Implementada em
classification.ex.
| GitHub | conceito CIRO |
|---|---|
status em queued in_progress waiting pending |
em andamento — sem fase |
conclusion: success |
ciro.successful_continuous_integration_process |
conclusion: failure |
ciro.unsuccessful_continuous_integration_process |
conclusion: cancelled |
ciro.interrupted_continuous_integration_process |
conclusion: skipped |
ciro.unperformed_continuous_integration_process |
conclusion: timed_out |
ciro.expired_continuous_integration_process |
cancelled e skipped não são insucesso. A versão 1 do mapeamento dizia que eram, e
as cinco fases distintas foram o conserto. Uma execução cancelada não diz nada sobre o
código; contá-la como falha faz a taxa de insucesso medir a interrupção humana.
O modelo foi validado em escala, e a escala mudou o que ele mostra: no primeiro
repositório havia 55 falhas e 54 cancelamentos, e unperformed era zero. Nas 15.375
execuções são 2.633 falhas, 248 cancelamentos — e unperformed só existe no volume.
Execução em andamento não recebe fase, e não recebe sucesso. Ausência de erro não é resultado.
Eixo 3 — o estado de quem entrou vem de outra API¶
workflow_run cobre uma camada de verificação. O GitHub tem três:
| camada | API | quem publica |
|---|---|---|
workflow_run |
Actions | o próprio Actions, por execução de workflow |
check_run |
Checks | o Actions por job, e apps de terceiros |
status |
Statuses (antiga) | serviço externo |
Coletar só a primeira deixa duas invisíveis. E a pergunta que a máxima ci.ap03 faz —
quem integrou código com verificação vermelha — é sobre a ponta no momento do merge,
não sobre uma execução qualquer do ramo.
Por que o casamento por head_sha não serve¶
O head_sha de uma execução é a ponta do ramo naquele instante. Isso produz erro nas
duas direções, e a direção que importa não é a que parece.
Ele deixa passar: ramo que recebeu mais commits depois tem execuções apontando para SHAs que já não são a ponta, e o casamento não acha execução para a ponta.
E ele superconta, que é o pior. Qualquer execução vermelha em qualquer commit do PR faz o casamento marcar a solicitação como integrada vermelha — inclusive a vermelha que foi consertada antes do merge, que é o processo funcionando.
statusCheckRollup é campo do commit, e agrega as três camadas¶
A consulta pede commits(last: 1) do pull request — a ponta no merge. É ela que
interessa, porque a máxima ci.ap03 fala de integrado com vermelho, e o que foi
integrado é a ponta.
Medido em 2026-08-20 sobre as 4.878 solicitações integradas, todas medidas — nenhuma pendente, o que importa porque a versão anterior desta página comparava com 763 ainda por medir:
| vermelhas | |
|---|---|
casamento por head_sha |
323 |
statusCheckRollup da ponta |
261 |
| nos dois | 115 |
| união | 469 |
A sobreposição de 115 em 469 é o número que diz tudo: não são duas medidas do mesmo fenômeno com precisões diferentes — são dois fenômenos.
Das 208 que só o casamento acha, 198 estão verdes na ponta. Conferido no #13: 33
commits, três execuções vermelhas no meio, ponta verde com 2 contextos. O casamento
chamava isso de integração vermelha.
Outras 10 dessas 208 não tiveram check nenhum na ponta. O casamento achava vermelho no meio e a ponta entrou sem verificação — as duas coisas são verdade, e só a segunda descreve o que foi integrado.
Das 146 que só o rollup acha, a causa é a camada: check_run e status não aparecem em
workflow_run.
Duas colunas, porque nulo não é desconhecimento¶
Declaradas em
20260819070000_add_merged_check_state.exs:
merged_check_state = nil E merged_check_contexts = 0 → nenhum check rodou
merged_check_contexts = nil → não medimos ainda
Com uma coluna só, "não coletamos" e "não havia o que coletar" ficariam com o mesmo nulo — que é exatamente a confusão que esta casa mais combate.
E a distinção não é acadêmica: 2.024 das 4.878 solicitações integradas entraram sem check nenhum — 41%. Pelo caminho antigo apareciam como "não dá para saber". São a coisa oposta — achado sobre o processo, não lacuna nossa. A organização apareceria medida onde não é verificada, que é pior do que não ter o número, porque ninguém procuraria o problema.
Os valores ficam crus: SUCCESS, FAILURE, PENDING, ERROR, EXPECTED. A
tradução para fase da CIRO acontece na leitura, nunca no lugar do que a origem disse.
O que a tela faz com isso¶
| Tela | O que responde |
|---|---|
/work/verifications |
fases, componentes, cobertura pela ponta, jobs monolíticos por arquivo |
/work/verifications/:id |
uma execução, seus jobs e os conceitos de cada um |
/work/verifications/people |
quem propôs e quem integrou vermelho, por participação |
Vermelho no ramo de proposta não conta¶
É o processo funcionando: a verificação pegou o problema antes de integrar, que é para isso que ela existe. Contá-lo produziria a medida ao contrário — quem empurra cedo e usa o CI como rede acumularia vermelhos, e quem desenvolve local e empurra uma vez apareceria impecável.
As duas participações não se somam¶
Submeter (cmpo.stakeholder_submitted_change_request) e integrar
(cmpo.stakeholder_performed_checkin) são atos distintos, e a tela obriga a escolher um.
Quem propôs pode ter aberto a solicitação vermelha de propósito, para pedir ajuda. Quem
integrou decidiu que entrava assim — e a definição de cmpo.change_request já dizia que
o PR "não é o merge, nem a decisão de aprovação".
Base pequena não recebe taxa¶
Abaixo de dez solicitações verificáveis a tela mostra a contagem e não a porcentagem. Três de quatro é 75% e não significa nada — e o corte vai declarado na tela, porque corte escondido faz quem lê achar que é propriedade do dado.
Limitações abertas¶
- A confiança do tipo é baixa, e permanece baixa. Depende do nome que alguém deu ao job. Não há como elevá-la sem o GitHub declarar o processo — e declarar confiança alta onde ela não existe seria pior que a lacuna.
- CIRO não declara relação entre
ciro.continuous_integration_processecmpo.source_repository. A execução aponta para o repositório e nada materializa o vínculo na rede. updated_ataproxima o término, mas não é o instante exato de fim.- Implantação real ainda não é observada.
cdro.deployment_activityé derivado do nome do job, e o processo de implantação vive no ArgoCD — que não é coletado (issue #442). - Coautoria não tem atribuição única. 1.203 de 16.416 commits têm mais de um autor
pelo trailer
Co-Authored-By, e a rede declara uma participação para cada.
Números conferidos na instalação de três organizações em 2026-08-19.