Run this repo's CI end-to-end — the kolu-specific procedure on top of the odu runner: the odu MCP front door, banned opt-out flags, mandatory two-platform coverage, venue-pool leasing, fail-fast surfacing, e2e timing evidence, and the green-gate. Triggers on "run CI", "drive CI", "re-run the pipeline", "close the red check", "warm the pool". Runner mechanics live in the `/odu` skill.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add juspay/kolu --skill ci --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Ci?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/juspay-kolu-kolu)More formats (shields.io, HTML) on the badges page.
---
name: ci
description: Run this repo's CI end-to-end — the kolu-specific procedure on top of the odu runner: the odu MCP front door, banned opt-out flags, mandatory two-platform coverage, venue-pool leasing, fail-fast surfacing, e2e timing evidence, and the green-gate. Triggers on "run CI", "drive CI", "re-run the pipeline", "close the red check", "warm the pool". Runner mechanics live in the `/odu` skill.
---
# CI
**Drive CI through the odu MCP server — the single front door.** The runner is
**odu** (npins-pinned by `ci/flake.nix`, `nix run ./ci#odu`): `mcp__odu__run`
spawns the coordinator, `mcp__odu__wait_for_settle` blocks until settle or first
red node (its verdict is stamped `sha7#seq`; pass `expected_sha` to hard-check),
the `surface://collections/logs/{id}` resource drills into a failure,
`mcp__odu__node_rerun` closes a red check. Runner mechanics: `/odu` skill.
**Banned flags: never `--no-post`, `--no-strict`, `--no-snapshot`.** CI here is
always strict and always posts commit statuses — a run that doesn't post isn't
CI, it's a private dry-run that leaves the PR unverified.
**Push before CI** — remote lanes `git fetch` the pinned SHA from origin; an
unpushed commit can't run.
**Sync master before CI, every run, whoever is driving.** Fetch and merge
`origin/<default>` unless it's already an ancestor
(`git merge-base --is-ancestor`). The changelog is `merge=union` and never
conflicts; a real conflict is yours to resolve now. Never merge while a
gauntlet round is mid-commit — it races the index.
**Every run covers both platforms.** Pin them explicitly —
`platforms=["x86_64-linux", "aarch64-darwin"]` — never trust a machine-local
default: a platform you don't name **silently drops**; a named platform with no
pool entry is **refused loudly** (juspay/odu#46). Before reporting green,
confirm the settled run actually carried both — a single-platform green is a
false green.
**Darwin hosts: read `hosts.json`, never this skill.** The darwin fleet is
volatile (this file hard-named the live box three times and was stale each
time) — `~/.config/odu/hosts.json` (`nix run ./ci#odu -- hosts`) is the only
source of truth; copy entries verbatim when pinning (user@ and tailnet suffixes
differ). Durable rules: under a coordinator, ask it before every darwin
dispatch (single-tenant); treat fs-watch-class reds on darwin as suspect box
environment and report before chasing; a dead pool entry silently stalls the
whole darwin lane — report it for removal rather than waiting it out.
**A companion repo's darwin lane uses `--host aarch64-darwin=<box>`, never
inline `$ODU_HOSTS`** — odu reads `$ODU_HOSTS` as a *file path*, so inline JSON
is silently ignored and burns a run on a dead host.
**Linux lane: odu leases natively** from the warm Incus pool
(`kolu-ci-1..8` in `hosts.json`) — picks a free box, holds it for the run,
releases on settle. No manual leasing. Saturated pool waits in line
(`no_wait: true` to fail fast instead); `nix run ./ci#odu -- hosts` shows
free/busy. To keep the *same* hot box across fix→rerun cycles, take an
agent-held lease with `mcp__odu__lease` first and `mcp__odu__release` when
done. Pool upkeep: `just ci::pool-ensure` / `just ci::pool-status`; warm idle
slots by running the linux lane against master with a `hosts=` pin (strict and
posting, like every run).
**Fail fast on the MCP; don't drain the pipeline.** `wait_for_settle` returns
on the first red node with `{failed[], errored[]}` — read the red node's log
(the log resource, or `.ci/<sha7>/<platform>/<recipe>.log`) and start the
fix → fmt → commit → retry loop immediately. **Waiting IS `wait_for_settle`
re-invoked**: an unsettled return at timeout means call it again — never park
the wait on a background shell watcher over `.ci/<sha7>/runs/` or a
`gh pr checks` poll. A hand-guessed ledger predicate hangs silently, and a
watcher that only detects settle forfeits first-red. `errored` (vs `failed`)
means infrastructure death — `node_rerun` it rather than hunting a test bug.
**`pu` misbehaves → log it on
[juspay/kolu#1204](https://github.com/juspay/kolu/issues/1204)** via
`.apm/skills/ci/pu/diagnose.sh <stage> <host>` (best-effort, never blocks the
run). Capture the stage's stderr:
`pu create "$host" 2> >(tee /tmp/pu-$host.err >&2)`.
**After a green two-platform settle, post e2e metrics to the PR.** Source of
truth: the run ledger `.ci/<sha7>/runs/<seq>.json` for each `ci::e2e@<platform>`
node's recipe-wall `durationMs` and host (never Cucumber's internal timer), and
the LAST `^e2e: workers=` line in `.ci/<sha7>/<platform>/ci::e2e.log` for
resolved parallelism. Maintain **one** comment keyed by the
`<!-- kolu-ci-e2e-metrics -->` marker (edit if present, create if absent) with
the run identity `<sha7>#<seq>` and a table of
`platform · host · workers · cores · cap · e2e duration`. Fail loud rather than
comment if any ingredient is missing. Post only after the full run settles
green, before reporting the gate.
**The green-gate: every required status check green on the PR's current
`HEAD`.** Source the required list from `just ci::protect --dry-run` **with
both explicit `--platform` flags** — without them odu derives platforms from
the machine-local `hosts.json` and can emit a single-platform subset, a false
green. Verify with `gh pr checks` (a green from a retry counts).
**Code-scanning alerts block merge too, and `gh pr checks` doesn't show them.**
Query **by PR number, never by branch ref** — code scanning here is GitHub's
default setup, which analyses only the default branch and `refs/pull/<n>/*`, so
a `ref=refs/heads/<branch>` query answers "no alerts" about a ref nobody
scanned (measured on #2017: branch ref → 0, `pr=2017` → an open HIGH):
```
gh api "repos/{owner}/{repo}/code-scanning/alerts?state=open&pr=<n>" \
--jq '.[] | "\(.rule.security_severity_level) \(.rule.id) \(.most_recent_instance.location.path):\(.most_recent_instance.location.start_line)"'
```
Fix every alert on code this PR introduced; name (don't silently ignore) any
pre-existing alert on untouched code.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!