Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ on:
branches: [main, develop]
workflow_dispatch:

# Scorecard Token-Permissions: the default GITHUB_TOKEN is read-only for every job;
# a job that has to write declares exactly what it writes on itself.
permissions:
contents: read

jobs:
test:
name: Test
Expand Down Expand Up @@ -525,6 +530,10 @@ jobs:
governance-guards:
name: Governance guards (GT-578)
runs-on: ubuntu-latest
# Guard 50 lists the open pull requests and reads each one's diff.
permissions:
contents: read
pull-requests: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Node.js
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/docker-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ on:
tags:
- "v*"

# Scorecard Token-Permissions: read-only by default; the build job below is the
# one that pushes to GHCR and declares `packages: write` itself.
permissions:
contents: read
packages: write

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/docs-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ on:
- 'release/docs-*'
- 'hotfix/docs-*'

# Scorecard Token-Permissions: the default GITHUB_TOKEN is read-only for every job;
# a job that has to write declares exactly what it writes on itself.
permissions:
contents: read

jobs:
release-trigger-check:
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
Expand Down Expand Up @@ -59,6 +64,9 @@ jobs:
needs: release-trigger-check
if: needs.release-trigger-check.outputs.version != ''
runs-on: ubuntu-latest
# Commits the version log back to main.
permissions:
contents: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand Down Expand Up @@ -93,6 +101,9 @@ jobs:
needs: [release-trigger-check, update-version-log]
if: needs.release-trigger-check.outputs.version != ''
runs-on: ubuntu-latest
# Pushes the tag and creates the GitHub Release.
permissions:
contents: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/enforce-root-cleanliness.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ on:
branches:
- main

# Scorecard Token-Permissions: the default GITHUB_TOKEN is read-only for every job;
# a job that has to write declares exactly what it writes on itself.
permissions:
contents: read

jobs:
validate-root:
runs-on: ubuntu-latest
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/reliability.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ defaults:
run:
shell: bash

# Scorecard Token-Permissions: the default GITHUB_TOKEN is read-only for every job;
# a job that has to write declares exactly what it writes on itself.
permissions:
contents: read

jobs:
k6-load:
name: k6 load profile (thresholds + published metrics)
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/sdk-cli-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ env:
# Bumping it is a reviewed change; guard 60 re-derives nothing from it.
GITLEAKS_VERSION: '8.30.1'

# Scorecard Token-Permissions: the default GITHUB_TOKEN is read-only for every job;
# a job that has to write declares exactly what it writes on itself.
permissions:
contents: read

jobs:
# ============================================
# JOB 1: Evolith Core Validation
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/sdk-cli-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ env:
NODE_VERSION: '20'
CLI_DIR: 'src/sdk/cli'

# Scorecard Token-Permissions: the default GITHUB_TOKEN is read-only for every job;
# a job that has to write declares exactly what it writes on itself.
permissions:
contents: read

jobs:
# ============================================
# GATE 0: Evolith Core Validation
Expand Down Expand Up @@ -629,6 +634,9 @@ jobs:
# a GitHub Release must not be cut when the npm publish failed.
if: ${{ needs.release-gate.outputs.release_created }}
runs-on: ubuntu-latest
# Creates the GitHub Release and uploads the binaries to it.
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down
2 changes: 2 additions & 0 deletions README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Evolith es un linter de arquitectura para CI. Lee tu repositorio —estructura,

Lo que lo distingue de otros linters: **también cuenta las reglas que no pudo evaluar.** Una regla bloqueante que no llegó a ejecutarse hace fallar el PR igual que una que falló. Cobertura y cumplimiento nunca se pintan del mismo verde.

Y no es solo un linter: **las reglas van atadas a la fase SDLC del producto.** Evolith sabe en qué fase está un producto (Discovery → Design → Construction → QA → Delivery), evalúa los controles de esa fase (`evolith gate evaluate --phase`) y bloquea el paso a la siguiente hasta que se cumplen (`evolith phase advance`), dejando evidencia legible por máquina de cada transición. Las decisiones de arquitectura viven en el mismo ciclo: `evolith adr create` las redacta y muchas reglas se derivan de ellas.

Es para equipos que quieren sus decisiones de arquitectura aplicadas en CI y no revisadas a mano, para plataformas que bloquean artefactos no conformes antes de producción, y para agentes de IA que necesitan validar su propia salida contra las mismas reglas.

[Pruébalo](#pruébalo-en-dos-minutos) · [Cuatro términos](#cuatro-términos-que-necesitas) · [En CI](#en-ci) · [Qué hay dentro](#qué-hay-dentro) · [Qué no es](#qué-no-es) · [Documentación](#documentación) · [Atlas interactivo](https://beyondnetcode.github.io/evolith_arch32/)
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Evolith is an architecture linter for CI. It reads your repository — structure

What sets it apart from other linters: **it also counts the rules it could not evaluate.** A blocking rule that never ran fails the PR exactly as one that failed. Coverage and compliance are never painted the same green.

And it is not only a linter: **the rules are tied to the product's SDLC phase.** Evolith knows where a product is (Discovery → Design → Construction → QA → Delivery), evaluates the gates of that phase (`evolith gate evaluate --phase`) and blocks the move to the next one until they pass (`evolith phase advance`), leaving machine-readable evidence of every transition. Architecture decisions live in the same loop: `evolith adr create` drafts them and many rules are derived from them.

It is for engineering teams that want their architecture decisions enforced in CI rather than reviewed by hand, for platform teams blocking non-conformant artifacts before production, and for AI agents that need to validate their own output against the same rules.

[Try it](#try-it-in-two-minutes) · [Four terms](#four-terms-you-need) · [In CI](#in-ci) · [What is inside](#what-is-inside) · [What it is not](#what-it-is-not) · [Documentation](#documentation) · [Interactive atlas](https://beyondnetcode.github.io/evolith_arch32/)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,33 @@
"id": "cli-baseline",
"status": "PASS",
"observedAt": "2026-09-19",
"commit": "99b53259",
"source": "https://github.com/beyondnetcode/evolith_arch32/actions/runs/35435224907",
"summary": "Re-observed 2026-09-19 on main (99b53259, the merge of #719) and GREEN. Run 35435224907 of the CLI CI pipeline shows all THIRTEEN jobs succeeding, CI Gate included: Lint and Type Check, Package Integrity, Unit Tests, E2E Tests, Architecture Validation, Evolith Core Validation, Security Audit, Secret Detection (gitleaks), Trivy Container Scan, CodeQL SAST, DAST OWASP ZAP, Winston Agentic Review and CI Gate. Why now: the four entries were taken together on 2026-08-18 and all four crossed the 0..30 day window on 2026-09-18, turning `Validate documentation` red on two Dependabot PRs whose content had nothing to do with it. Same rule as last time: aged-out evidence is re-taken against a fresh green run, not date-bumped."
"commit": "4d655745",
"source": "https://github.com/beyondnetcode/evolith_arch32/actions/runs/34998373252",
"summary": "Re-observed 2026-09-19 against the head of develop (4d655745, pushed 2026-09-15) and GREEN. Run 34998373252 shows all THIRTEEN jobs of the CLI CI pipeline succeeding, CI Gate included: Lint and Type Check, Package Integrity, Unit Tests, E2E Tests, Architecture Validation, Evolith Core Validation, Security Audit, Secret Detection (gitleaks), Trivy Container Scan, CodeQL SAST, DAST OWASP ZAP, Winston Agentic Review and CI Gate. WHY THIS RE-OBSERVATION HAPPENED, stated plainly: the previous four entries were taken on 2026-08-18 and crossed the 30-day window on 2026-09-17, so `09-reconcile-maturity.mjs` turned `Validate documentation` red on a README-only PR (#724) whose content had nothing to do with it. Same pattern as the 2026-08-18 re-observation: the window is the point, evidence that ages out is re-taken, not extended."
},
{
"id": "coverage",
"status": "PASS",
"observedAt": "2026-09-19",
"commit": "99b53259",
"source": "https://github.com/beyondnetcode/evolith_arch32/actions/runs/35435224907",
"summary": "Re-observed 2026-09-19 on main (99b53259) and GREEN. The Unit Tests job of run 35435224907 succeeds with 107 suites and 1492 tests, 0 failures, and both coverage gates clear: the jest global thresholds (statements 80 / lines 80 / functions 75 / branches 75) with Statements 87.22% (5450/6248), Lines 87.54% (5116/5844), Functions 84.79% (853/1006) and Branches 75.73% (2382/3145), plus the workflow statement gate at 80%. Suite count, test count and branch total all grew since the previous observation (106 suites / 1486 tests, 2376/3139 branches), so the margin over the branch threshold is still being held while the corpus grows, not by shrinking what is measured."
"commit": "4d655745",
"source": "https://github.com/beyondnetcode/evolith_arch32/actions/runs/34998373252",
"summary": "Re-observed 2026-09-19 against the head of develop (4d655745, pushed 2026-09-15) and GREEN. The Unit Tests job of run 34998373252 succeeds with 107 suites and 1492 tests, 0 failures, and the blocking coverage gate clears: Branches 75.73% (2382/3145) against the unchanged 75% global threshold. Since the previous observation (106 suites / 1486 tests, 2376/3139 branches) the corpus grew by one suite, six tests and six branches, and the margin over the threshold moved from 75.69% to 75.73%: held while the corpus grows, not by shrinking what is measured."
},
{
"id": "documentation",
"status": "PASS",
"observedAt": "2026-09-16",
"commit": "3d0662c7",
"source": "https://github.com/beyondnetcode/evolith_arch32/actions/runs/35125943994",
"summary": "Observed 2026-09-16 on 3d0662c7 (the head of #719, whose tree became main as 99b53259 with no other change) and GREEN. Run 35125943994 of Documentation Validation has both jobs succeeding -- `Validate documentation` and `Validate semantic tracking (guard)` -- so the reconciler, bilingual parity, the bilingual sync guard, the gap-board tracking guard and the derived-artifact order guard all pass on the same tree. This entry cites a run three days older than its siblings ON PURPOSE: once the window closes, every later run of this workflow is red at the `Reconcile maturity evidence` step because of the window itself (see run 35435224859 on 99b53259: the evidence and ISO rules pass, then the reconciler rejects the four aged entries), so the last green run BEFORE the window closed is the only honest observation of this claim available until this very refresh lands."
"observedAt": "2026-09-19",
"commit": "4d655745",
"source": "https://github.com/beyondnetcode/evolith_arch32/actions/runs/34998373244",
"summary": "Re-observed 2026-09-19 against the head of develop (4d655745, pushed 2026-09-15) and GREEN. Run 34998373244 of Documentation Validation has both of its jobs succeeding -- 'Validate documentation' and 'Validate semantic tracking (guard)' -- so the reconciler, the bilingual parity suite and the gap-board tracking guard all pass on the same tree. That run passed at 28 days of evidence age; the same check went red four days later on PR #724 purely by the calendar, which is the 0..30 day window working as designed. All four entries are re-taken together, as on 2026-08-18."
},
{
"id": "release",
"status": "PASS",
"observedAt": "2026-09-19",
"commit": "99b53259",
"source": "https://github.com/beyondnetcode/evolith_arch32/actions/runs/35435224976",
"summary": "Re-observed 2026-09-19 on main (99b53259) and GREEN through the binary jobs. Run 35435224976 of the Evolith SDK CLI Release Pipeline succeeds across release-gate, build-and-test, Evolith Core Validation, package-binaries on all three platforms (linux-x64, macos-x64, win-x64), smoke-test on all three platforms and smoke-test-functional. publish-npm, upload-assets and failure-notification are `skipped` because this run is a push to main, not a `cli-v*` tag. Second consecutive observation with the packaged binaries passing `--help` on every platform, which until GT-707 had never happened."
"summary": "Re-observed 2026-09-19 on the head of main (99b53259, push of 2026-09-19) and GREEN THROUGH THE BINARY JOBS AGAIN. Run 35435224976 of the Evolith SDK CLI Release Pipeline succeeds across release-gate, build-and-test, Evolith Core Validation, package-binaries on all three platforms, smoke-test on all three platforms and smoke-test-functional. This is the second consecutive observation in which the packaged binaries answer `--help` (the ERR_REQUIRE_ESM regression closed by GT-707 has not returned). publish-npm, upload-assets and failure-notification are `skipped` because this run is a push to main, not a `cli-v*` tag (PR #708 moved the CLI release trigger to `cli-v*` tags)."
}
]
}
Loading
Loading