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
61 changes: 61 additions & 0 deletions .github/ci-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# CI tier policy — fast PR tier, full main tier

Design: developing-today/code#1779 (ci-fast-pr-full-main). Phases:
#1780 (cancel-in-progress), #1781 (this policy), #1782 (main-breakage
chain, .github/workflows/main-broken.yml). Tracker: #1599.

Every workflow touched by the tier redesign carries the header
comment . Tuning the tiers
means editing THIS table by PR — never ad-hoc pipeline changes.

## Change classes (§3.3 of the design)

| class | trigger paths (examples) | PR tier |
|---|---|---|
| 0 — prose | , docs/, comments-only changes | nothing, or markdown lint only |
| 1 — config/data | non-build, (non-workflow) | syntax parse + lint of changed files |
| 2 — package source (default) | one package's src + tests | lint/format + typecheck/syntax of affected packages + affected unit tests |
| 3 — elevated | lockfiles, / roots, /, build definitions (), , shared/core libraries | class 2 + compile check of affected packages |
| 4 — nix expressions | | class 1 + parse/eval of the changed files only (never full flake check on a PR) |

Default when a change spans classes: the highest class wins. The
policy ships conservative (more class 3) and loosens as the
main-breakage rate (issues labelled ) proves out.

## Tier assignment in this repo (after #1781)

| workflow | PR tier | main tier | nightly |
|---|---|---|---|
| nix ci | treefmt/format gate only | treefmt + full flake-check | schedule in nix-ci.yml |
| id | guard + affected-crate matrix () | + full job | schedule in id-check.yml + id-e2e-nightly.yml (full flake check) |
| mcpx conformance | spec-parity leg only (measured 28s exec, run 40801660942, 2026-10-29 — under the 5m fast-leg limit) | all conformance legs + records + spec-parity | — (main covers it) |
| id bench | — (removed) | yes | — |
| go modules build / identity build / map build / mcpx nix build | class-3 paths only (see each workflow) | always (push to main, no path filter) | — |
| mcpx, lab-ops-hub, mod-tidy, research-workflow | unchanged path-gated PR checks (already PR-tier weight) | push to main | — |

## Coverage rule

Nothing removed from PRs may vanish: the union of main-tier +
nightly jobs must cover the old PR matrix. For pkgs/id the full
flake check runs on main (id-check full-flake-check job) and
nightly twice over (id-check schedule, id-e2e-nightly). For nix ci
the flake-check job runs on main and on the nix-ci nightly
schedule. mcpx conformance legs run on every mcpx-touching merge
to main.

## Dedup rule

A commit must not run the same suite twice via push +
pull_request. Standard shape: for PRs,
restricted to (plus tags where already
applicable, e.g. goreleaser).

## Concurrency rule (#1780)

Standard block (design §4): group keyed by for
push-to-main, by otherwise,
— PR/branch runs cancel on supersede; main runs are never
cancelled. Exceptions: (load-bearing cip=false, #304)
and scheduled singleton/deploy workflows (cip=false) are NOT
touched. Issue-event workflows (auto-assign) use a per-issue group
so cancel-in-progress can only supersede a run for the same issue.
5 changes: 4 additions & 1 deletion .github/workflows/auto-assign.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ concurrency:
# events github.ref is always the default/base branch, so a ref-keyed group
# is one repo-wide group and a burst of opened events silently replaces the
# pending run (queue: single is the default), dropping its assignment (#302).
# The group below is per-target, so cancel-in-progress only ever supersedes
# a stale run for the SAME issue/PR; the assignment is idempotent and the
# newest event wins (Phase 1, #1780). CI tier policy: see .github/ci-policy.md
group: ${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number }}
cancel-in-progress: false
cancel-in-progress: true

jobs:
run:
Expand Down
41 changes: 26 additions & 15 deletions .github/workflows/go-modules-build.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: go modules build

# CI tier policy: see .github/ci-policy.md

# Build verification for the small pkgs/{chat,database,graph,import,
# launcher,tea} Go modules (#342).
#
Expand Down Expand Up @@ -28,24 +30,33 @@ name: go modules build

on:
pull_request:
# PR tier (Phase 2, #1781): builds fire on PRs only for class-3
# changes (lockfiles, module roots, flake files, build definitions,
# workflow files, shared libs); on push to main they always run.
paths:
- "pkgs/chat/**"
- "pkgs/database/**"
- "pkgs/graph/**"
- "pkgs/import/**"
- "pkgs/launcher/**"
- "pkgs/tea/**"
- ".github/workflows/go-modules-build.yml"
- "pkgs/chat/go.mod"
- "pkgs/chat/go.sum"
- "pkgs/database/go.mod"
- "pkgs/database/go.sum"
- "pkgs/graph/go.mod"
- "pkgs/graph/go.sum"
- "pkgs/import/go.mod"
- "pkgs/import/go.sum"
- "pkgs/launcher/go.mod"
- "pkgs/launcher/go.sum"
- "pkgs/tea/go.mod"
- "pkgs/tea/go.sum"
- "pkgs/chat/package.nix"
- "pkgs/database/package.nix"
- "pkgs/graph/package.nix"
- "pkgs/import/package.nix"
- "pkgs/launcher/package.nix"
- "pkgs/tea/package.nix"
- "flake.nix"
- "flake.lock"
- ".github/workflows/**"
push:
branches: [main]
paths:
- "pkgs/chat/**"
- "pkgs/database/**"
- "pkgs/graph/**"
- "pkgs/import/**"
- "pkgs/launcher/**"
- "pkgs/tea/**"
- ".github/workflows/go-modules-build.yml"

permissions:
contents: read
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ on:
permissions:
contents: write

# CI tier policy: see .github/ci-policy.md
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && github.run_id || github.ref }}
cancel-in-progress: true

jobs:
dump_contexts_to_log:
runs-on: ubuntu-latest
Expand Down
9 changes: 4 additions & 5 deletions .github/workflows/id-bench.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# using .github/scripts/id-bench-compare.sh. The report lands in the job
# summary and as a run artifact.
#
# Main tier only (Phase 2, #1781): benchmarks no longer run on PRs.
#
# NON-BLOCKING BY DESIGN: this workflow is separate from the required
# "nix flake check" gate in id-check.yml, the bench step is
# continue-on-error, and the compare script always exits 0. A regression
Expand All @@ -15,18 +17,15 @@

name: id bench

# CI tier policy: see .github/ci-policy.md

on:
push:
branches: [main]
paths:
- "pkgs/id/**"
- ".github/workflows/id-bench.yml"
- ".github/scripts/id-bench-compare.sh"
pull_request:
paths:
- "pkgs/id/**"
- ".github/workflows/id-bench.yml"
- ".github/scripts/id-bench-compare.sh"
workflow_dispatch:

permissions:
Expand Down
33 changes: 33 additions & 0 deletions .github/workflows/id-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@

name: id

# CI tier policy: see .github/ci-policy.md

on:
push:
branches: [main]
Expand All @@ -55,6 +57,10 @@ on:
- ".github/scripts/id-pr-checks.txt"
- ".github/scripts/check-id-pr-checks.sh"
- ".github/scripts/check-crash-gate-coverage.sh"
schedule:
# Nightly backstop for the full flake check (main tier, #1781).
- cron: "41 8 * * *"
workflow_dispatch:

permissions:
contents: read
Expand Down Expand Up @@ -166,3 +172,30 @@ jobs:
echo "::error::one or more PR check jobs did not succeed (result: $result) — see the per-check jobs above."
exit 1
fi

# Main tier (Phase 2, #1781): the FULL flake check for pkgs/id. The PR
# tier above keeps guard + the affected-crate matrix from
# id-pr-checks.txt; the full check (including the heavy checks the PR
# list excludes) runs once per merge on main, plus the nightly
# schedule above -- and nightly in id-e2e-nightly.yml as a second
# backstop. Nothing from the old PR matrix is lost: the union of this
# job, id-e2e-nightly, and the PR matrix covers it.
full-flake-check:
name: nix flake check (full, main tier)
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 180
steps:
- uses: actions/checkout@v7
- uses: DeterminateSystems/nix-installer-action@3138316df39ed29be04236d7ffc686fa525866aa # v23
with:
extra-conf: |
accept-flake-config = true
- uses: DeterminateSystems/magic-nix-cache-action@84c0677f58dcedf3b91f8223ce36a9ea5b3c84b7 # v15
- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: Run full nix flake check
run: nix flake check ./pkgs/id/ -L --keep-going
Comment on lines +200 to +201

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve disk reclamation before the new full check

On ubuntu-latest runs that need to build the heavy derivations rather than restore them from cache, this new job reintroduces a known disk-exhaustion failure. The existing equivalent job in .github/workflows/id-e2e-nightly.yml explicitly documents intermittent No space left on device failures and reclaims roughly 20–30 GB before running the same full check (lines 52–73). This job uses the same runner but omits that preparation, so main-tier and scheduled checks can fail from runner capacity rather than code regressions. Carry over the disk-reclamation step before invoking the full check.

Useful? React with 👍 / 👎.

16 changes: 11 additions & 5 deletions .github/workflows/identity-build.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: identity build

# CI tier policy: see .github/ci-policy.md

# Build verification for the pkgs/identity Go module (#340).
#
# pkgs/identity builds only with a build tag: its charm fork keeps the
Expand All @@ -11,14 +13,18 @@ name: identity build

on:
pull_request:
# PR tier (Phase 2, #1781): builds fire on PRs only for class-3
# changes (lockfiles, module roots, flake files, build definitions,
# workflow files, shared libs); on push to main they always run.
paths:
- "pkgs/identity/**"
- ".github/workflows/identity-build.yml"
- "pkgs/identity/go.mod"
- "pkgs/identity/go.sum"
- "pkgs/identity/package.nix"
- "flake.nix"
- "flake.lock"
- ".github/workflows/**"
push:
branches: [main]
paths:
- "pkgs/identity/**"
- ".github/workflows/identity-build.yml"

permissions:
contents: read
Expand Down
16 changes: 11 additions & 5 deletions .github/workflows/map-build.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: map build

# CI tier policy: see .github/ci-policy.md

# Build verification for the small pkgs/map Go module (#338).
#
# Nothing built pkgs/map in CI at all, so it rotted silently: its
Expand All @@ -11,14 +13,18 @@ name: map build

on:
pull_request:
# PR tier (Phase 2, #1781): builds fire on PRs only for class-3
# changes (lockfiles, module roots, flake files, build definitions,
# workflow files, shared libs); on push to main they always run.
paths:
- "pkgs/map/**"
- ".github/workflows/map-build.yml"
- "pkgs/map/go.mod"
- "pkgs/map/go.sum"
- "pkgs/map/package.nix"
- "flake.nix"
- "flake.lock"
- ".github/workflows/**"
push:
branches: [main]
paths:
- "pkgs/map/**"
- ".github/workflows/map-build.yml"

permissions:
contents: read
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/mcpx-conformance.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: mcpx conformance

# CI tier policy: see .github/ci-policy.md

# The official MCP conformance suite (github.com/modelcontextprotocol/conformance) against mcpx,
# one job per leg. A leg is one side of the protocol (mcpx as a server, or as a client) checked
# against one spec revision. The suite has frozen requirement sets for 2025-11-25 and 2026-07-28;
Expand Down Expand Up @@ -54,6 +56,10 @@ env:
jobs:
leg:
name: ${{ matrix.leg }}
# Main tier only (Phase 2, #1781): the conformance legs move off PRs.
# The spec-parity job below stays on PRs: measured exec 28s on run
# 40801660942 (2026-10-29), well under the 5m fast-leg limit.
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
Expand Down Expand Up @@ -343,7 +349,7 @@ jobs:
records:
name: compare with the records
needs: leg
if: always()
if: always() && github.event_name != 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
Expand Down
14 changes: 8 additions & 6 deletions .github/workflows/mcpx-nixbuild.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: mcpx nix build

# CI tier policy: see .github/ci-policy.md

# Narrow package-build verification (#297).
#
# The mcpx workflow's PR gate is a direct-Go test job — it no longer builds
Expand All @@ -17,18 +19,18 @@ name: mcpx nix build

on:
pull_request:
# PR tier (Phase 2, #1781): builds fire on PRs only for class-3
# changes (lockfiles, module roots, flake files, build definitions,
# workflow files, shared libs); on push to main they always run.
paths:
- "pkgs/mcpx/go.mod"
- "pkgs/mcpx/go.sum"
- "pkgs/mcpx/package.nix"
- ".github/workflows/mcpx-nixbuild.yml"
- "flake.nix"
- "flake.lock"
- ".github/workflows/**"
push:
branches: [main]
paths:
- "pkgs/mcpx/go.mod"
- "pkgs/mcpx/go.sum"
- "pkgs/mcpx/package.nix"
- ".github/workflows/mcpx-nixbuild.yml"

permissions:
contents: read
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/nix-ci.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
name: nix ci

# CI tier policy: see .github/ci-policy.md
on:
push:
branches: [main]
pull_request:
schedule:
# Nightly backstop: the full flake check runs on main + nightly, not PRs.
- cron: "17 8 * * *"
workflow_dispatch:

permissions:
contents: read
Expand Down Expand Up @@ -58,6 +63,8 @@ jobs:

flake-check:
name: Nix flake evaluation
# Main tier only (Phase 2, #1781): PRs keep the treefmt/format gate above.
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
Expand Down
Loading