Skip to content
Back to skills

Ci Bootstrap

ASecurity

Give a project its first real CI gate, built only from commands the repo already declares, and ratcheted so it goes green on day one. Use when a repo has no CI, has CI that has never passed, or has CI nobody trusts.

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 19, 2026
businessrustgonodedebugginggit

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned October 19, 2026

npx -y skills add xkazm04/ai-registry --skill ci-bootstrap --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ci Bootstrap?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ci Bootstrap
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/xkazm04-ci-bootstrap/badge)](https://www.skillsdirectory.com/skills/xkazm04-ci-bootstrap)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ci-bootstrap
description: "Give a project its first real CI gate, built only from commands the repo already declares, and ratcheted so it goes green on day one. Use when a repo has no CI, has CI that has never passed, or has CI nobody trusts."
category: ci-cd
memory: project
version: 0.4.1
tags: bootstrap, gate, ratchet, workflow, first-ci
argument-hint: "[project-root]"
---

# CI bootstrap

Most projects get CI at the wrong moment and in the wrong shape. Too early, it is a
copied template running commands the repo does not have. Too late, it is added in one
push, fails on forty pre-existing problems, and is switched off within a week.

This skill installs a gate that is **true on the day it lands**: it runs only commands
this repository actually declares, it blocks only on stages that pass right now, and
everything else is reported until someone fixes it. A gate that is green on day one is a
gate that stays.

## When to use

- The repo has no CI at all.
- The repo has CI that has never passed, or whose failures nobody reads.
- An agent is about to start making changes at volume and there is nothing catching them.

## Step 1: measure before you gate

Do this first and do not skip it. You cannot ratchet what you have not measured.

Discover the real commands, in this order of authority. **Never invent a command.**

1. `.ai/manifest.yaml` -> `capabilities` (`lint`, `typecheck`, `test`, `build`)
2. The project's own task definitions: `package.json` scripts, `Makefile` targets,
   `justfile` recipes, `pyproject.toml` tool config, `Cargo.toml`
3. Any existing CI config - whatever it runs IS the current gate, and it wins ties

Then run each one locally and record the result. Report the table before writing anything:

```
format     ok        0.8s   npm run format:check
lint       FAIL     4.1s   npm run lint            37 problems
typecheck  ok        9.2s   npx tsc --noEmit
test       ok       22.0s   npm test                104 passed
build      -         -      not configured
```

`not configured` is a real outcome and is reported as itself. A stage with no command in
this repo does not get one made up for it.

## Step 2: place each stage on a rung

Three rungs, and the assignment is decided by the measurement, not by preference.

| rung | goes here when | behaviour |
| --- | --- | --- |
| blocking | the stage passes today | fails the build |
| reporting | the stage fails today | runs, prints, exits 0 |
| absent | no command exists | not in the workflow at all |

The reporting rung is the ratchet. It exists so a pre-existing problem does not block an
unrelated change - which is how gates get deleted - while still being visible on every
run. Each reporting stage gets a one-line comment in the workflow naming what is wrong
and roughly how much: `# 37 lint problems as of <date>; promote to blocking when 0`.

Never put a stage on the reporting rung because it is slow or annoying. Reporting is for
"currently failing", nothing else.

## Step 3: write one workflow, with these five properties

1. **One job per stage, named for the stage.** Not one job running five commands in a
   chain - a chain aborts at the first failure and hides every stage after it, so a
   single early breakage blinds the whole gate.
2. **Path filters that include the workflow itself** and the dependency lockfile. A gate
   that can be edited without running is not a gate. If in doubt, filter coarsely: over-
   triggering costs seconds, under-triggering costs a whole class of unchecked change.
3. **A schedule trigger as well as the change trigger.** A change-only trigger means a
   repo that goes quiet never re-reports, and the last green result stays on the page
   while everything underneath it drifts. Weekly is enough. The scheduled run reports and
   does not block.
4. **No install step the gate does not need.** Keep the gate dependency-light so it is
   fast and so it can be run by anyone debugging it.
5. **Fail on a stage that did not run.** If a command is missing or a glob matched
   nothing, that is a failure of the gate, not a pass. Zero files checked is never green.

## Step 4: wire the same commands locally

The gate's commands and the local pre-push commands are the same commands. Add them to
whatever hook system the repo already has - `lefthook`, `husky`, `pre-commit`. **Never
add a second hook system.** If there is no hook system, do not install one; point the
author at `ci-gate-check` instead, which reads the same declarations.

## Step 5: report

```
CI bootstrap complete.

blocking   format, typecheck, test
reporting  lint (37 problems, 2026-08-21)
absent     build (no command declared)

triggers   push+PR on <paths>, weekly schedule
local      3 stages wired into existing lefthook pre-push
next       fix lint to 0, then promote it to blocking
```

## Rules

- Never invent a command. `not configured` is an honest result; a fabricated passing
  command is a false green with a plausible name on it.
- Never land a gate that is red on the day it lands. Ratchet instead.
- Never chain stages into one job.
- Never let a stage be silently skipped. Not-run, not-configured and passed are three
  different outcomes and must render as three.
- Do not add a second hook system, a second lint config, or a second version of any tool
  the repo already has. One authority per rule.
- Do not raise thresholds or add exemptions to make a stage pass. That is a change to
  what the gate means, and it needs its own commit and a reason.

## Related

- `ci-gate-check` - runs this same gate locally before a push.
- `ci-triage` - what to do when the gate this skill installed goes red.
- Knowledge: `quality-gates` (gate-laddering, ratchet-design, gate-liveness),
  `pipeline-authoring` (change-scoped-work-selection),
  `machine-paced-delivery` (pre-authorship-verification).

---

<!-- clause: skill-reflection v6 - stamped by scripts/apply-skill-clauses.mjs from docs/skill-clauses/skill-reflection.md; edit the template, then re-stamp -->
## Skill Reflection

After the work, record only useful observations supported by this run. No lesson is
a valid result. Reflection inherits the task's authorization; it grants no additional
permission to edit another repository, send data, commit, or publish.

**Run log.** Unlike a lesson, this is written on every run that started work - failed and
aborted runs included; skip read-only info modes and runs cancelled before any work. Append
ONE line to `.ai/skill-runs.local.jsonl` at the root of the task's MAIN checkout: local,
gitignored run output inside the task's own repository, never a write into the registry.
A run that worked in a linked worktree logs in the main checkout that worktree belongs to
(`git rev-parse --git-common-dir`, minus `/.git`) - a disposable worktree takes the line
with it when it is removed. `log-run.mjs` resolves this on its own.
The registry pulls it later (`/librarian skills` on the same machine). When a registry
checkout is reachable (`registry.local` in `.ai/manifest.yaml`), prefer its writer, which
stamps project, device and version for you:

```sh
node <registry>/scripts/log-run.mjs --skill ci-bootstrap --outcome <o> --difficulty <1-5> \
  --provider <claude|openai|xai|qwen|google|other> --model <your model id> [--effort <level>] \
  [--tokens-est <n>] --result "<one sentence>" --comment "<self-reflection>"
```

Otherwise write the line yourself: `{"ts":"<ISO, UTC Z>","skill":"ci-bootstrap","outcome":…,
"difficulty":…,"provider":…,"model":…,"effort":…|null,"tokensEst":…|null,"result":…,"comment":…}`.

- `outcome`: `shipped` (the goal landed) / `partial` / `no-op` (ran correctly, nothing to
  do) / `parked` (designed or staged, deliberately not landed) / `failed` / `aborted`.
- `difficulty` rates the task as this run met it: 1 trivial - mechanical; 2 routine - the
  method as written; 3 demanding - real judgment calls or one detour; 4 hard - dead ends,
  rework or an operator course-correction; 5 at the edge - partial or failed on the merits.
- `model`/`effort` as your harness states them (`null` effort when you cannot see it).
  `tokensEst` is the drop in the harness's remaining-token counter since this skill was
  invoked, or `null` (with `log-run.mjs`, omit `--tokens-est`); exact figures are measured
  later from transcripts - never guess one.
- `result` is one line (max 240 chars). `comment` (max 2000) is the self-reflection a
  reviewer reads: what worked, what the method made harder, where its instructions were
  wrong, missing or ignored. No filesystem paths or email addresses.
- Never read run logs during a run. They are evidence ABOUT this skill for its reviewer;
  an executor that reads its own diagnosis contaminates the next measurement.

**Project learning.** Only when this run produced an observation that would change how a
future run behaves. A run that went as the method describes writes nothing: an entry that
restates the procedure, records "no issues", or repeats the task is a defect, not a
deliverable. When there is such an observation and local edits are within scope, put one
dated line in the overlay this skill's `## Project overlay` section names, under
`## Skill improvement log`. **Write only into an overlay that already exists.** If the
project has none, put the observation in the response instead - creating a new tracked
file for a reflection is scope the task did not ask for, and a reader who never asked for
the skill has to review it. If the overlay is a structured config (YAML, TOML, JSON),
record the note as comments so the file keeps parsing, or use the response.
Use a supplied memory contract only when its destination and writes are authorized.
Keep project details out of the shared method.

**Method learning.** Identify the installation before editing anything. A local
`.ai/registry-installation.local.json` receipt can identify development versus release,
the registry revision, and selected skill versions. Verify any link's actual target;
do not assume a skill directory is a writable registry link.

- For a pinned release, marketplace cache, ordinary copy, or unknown installation,
  keep a proposal in the project overlay or response. Do not edit the installed method
  or silently relink it. Adoption and rollback are explicit installation operations.
- For a development link, edit the registry only when that checkout is already within
  the accepted task scope. Otherwise report a proposal. Authorized changes belong in
  the source checkout, followed by its gates; commit only when the task authorizes it.
- Record an actual lesson in `LESSONS.md` against the version **used**:
  `## <version-used> - <YYYY-MM-DD> - <project-name>` and concise bullets. A proposal
  must be labeled as such; structural checks are not evidence of field effectiveness.
- Applied skill changes require a version bump: patch for wording, minor for a step
  refinement, major for method redesign. A lesson alone needs no bump. Shared stamped
  clauses are edited in the registry's `docs/skill-clauses/` and regenerated with
  `scripts/apply-skill-clauses.mjs`, never patched in individual installed skills.

**Domain learning.** Follow `## Knowledge sync` when present, within the same scope
and privacy boundaries. A method lesson and a domain knowledge lead are different
artifacts; do not fabricate either to fill a reflection quota.
<!-- /clause: skill-reflection -->

Files in this skill

  • LESSONS.md318 B
  • SKILL.md11.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.