Skip to content

ci: the single pipeline run by the Claude bot (bootstrap, ADR-1115) - #781

Merged
cdeust merged 1 commit into
mainfrom
ci/single-pipeline
Oct 22, 2026
Merged

cdeust merged 1 commit into
mainfrom
ci/single-pipeline

Conversation

@cdeust

@cdeust cdeust commented Oct 22, 2026

Copy link
Copy Markdown
Owner

The single CI pipeline (bootstrap, ADR-1115)

Adds .github/workflows/pipeline.yml ("Pipeline"), ci.json and ADR-1115 (wiki/adr/cortex/1115-...md, written with the Cortex wiki_adr tool). Deletes .github/workflows/claude-review.yml (the pipeline's review job replaces it; claude.yml, the @claude mention, stays). ci.yml and every other workflow are untouched. Branched from origin/main; PR #780 (fix/claude-ci-runtime, a centralised CI by another session) is not touched. Design: zetetic-team-subagents docs/superpowers/specs/2026-10-22-single-ci-design.md, decisions 1 to 9 binding; plan Phase 2.

Pipeline

contract (validates ci.json) -> unit (reads Cobertura coverage.xml, fails under 90 % of lines) -> regression -> e2e -> environment (ubuntu, macOS, Windows; bare runner plus @anthropic-ai/[email protected]) -> install (same matrix, fresh HOME and CLAUDE_CONFIG_DIR) -> review (the bot: documented /code-review:code-review --comment, then a fix step whose prompt carries the failed-job URLs; skipped when the head commit is the bot's, the PR is a draft or a fork, the actor is Dependabot, or the diff touches pipeline.yml) -> merge -> tag on push to main (this repository's own release-gate block, ADR-0802: canonical_version from pyproject.toml, check_version_surfaces.py, tag pushed over RELEASE_TAG_SSH_KEY). Actions pinned by SHA; actionlint 1.7.12 passes. # source: ADR-1115 cited in pipeline.yml.

merge runs on every same-repo, non-draft pull request and its first step fails explicitly, naming the job, when unit, regression, e2e, environment or install is not a success or review failed; only then does it arm gh pr merge --auto --squash (no checkout). Measured on claude-mods #38 and session-optimizer #73: a merge job whose if: is not met is skipped, and GitHub treats a skipped required check as satisfied. The bot cannot edit .github/workflows files (its App token lacks the workflows scope), so a workflow change is never a bot commit.

ci.json

step command
unit pipx install uv==0.11.3 when absent, uv sync --locked --extra dev --extra sqlite --extra codebase, CORTEX_MEMORY_STORE_BACKEND=sqlite CORTEX_RERANKER_OFFLINE=1 uv run --locked pytest --tb=short -q -p no:randomly --cov=mcp_server --cov-report=xml
regression same setup, uv run --locked pytest ... tests_py/integration
e2e bash scripts/docker_smoke.sh (the image is built in the job: a bare runner has none to skip)
environment python3 -m venv "$CI_WORK/venv", pip install ., python -c "from mcp_server.doctor import run; raise SystemExit(run())" (cortex-doctor after install)
install python3 scripts/install_e2e/run.py --marketplace "$PWD" --work "$CI_WORK/install-e2e" --settle-seconds 1500 on the three OS
version_file pyproject.toml

No mutation run is referenced (owner rule 2026-10-22: mutation testing is scoped to the PR's files, never a whole-tree pass; scripts/mutation_check.sh stays out of the pipeline).

Red cells on day one

  • unit: line coverage is 82 % (ci.yml enforces --cov-fail-under=82), under the 90 % floor.
  • install on Windows: the leg is new; scripts/install_e2e was measured on linux and macOS only (ADR-1104).
  • environment on a bare runner installs the project's full dependency set with pip; the three legs have not run locally.
  • This PR touches pipeline.yml, so it gets no bot review (decision 2); it merges on green tests.

Three pillars

Research pillar, done. Baseline reproduced locally on macOS arm64, 2026-10-22: uv sync --locked with the dev, sqlite and codebase extras (uv 0.11.3, CPython 3.12 arm64, uv.lock unchanged); tests_py/integration on SQLite: 29 passed, 4 skipped (PostgreSQL), 57.68 s. The full unit suite, the docker smoke (no docker on this host) and the install legs are left to this PR's own run.

SSDLC pillar, done. Threat model: the review and fix jobs run only on same-repo, non-draft, non-Dependabot PRs; the fix step's tools are an explicit allowlist; tag uses the write-enabled deploy key; actions pinned by commit SHA; the contract step refuses an empty or unknown key; merge fails closed. SAST: actionlint. Cortex declares no local gate.

Operations pillar, not applicable: no data is processed; the only secrets are the existing CLAUDE_CODE_OAUTH_TOKEN and RELEASE_TAG_SSH_KEY, read by the jobs that need them and no other.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BxsVCVscNG2Vb7fafCgqYR

Adds .github/workflows/pipeline.yml, the one pipeline every pull request
goes through: contract (validates ci.json), unit (the SQLite-backed pytest
suite under uv, Cobertura coverage.xml, 90 % of lines), regression
(tests_py/integration), e2e (scripts/docker_smoke.sh, image built in the
job), environment (cortex-doctor after `pip install .` into a fresh venv on
ubuntu, macOS and Windows, bare runner plus the pinned Claude Code CLI
2.1.296), install (scripts/install_e2e/run.py on the three OS, the Windows
leg new), the bot's review (code-review plugin) and fix steps, the squash
auto-merge, and the release tag on push to main, which keeps ADR-0802's
gate: canonical_version from pyproject.toml and check_version_surfaces.
The commands live in ci.json (version_file: pyproject.toml). No mutation
run is part of the pipeline (owner rule 2026-10-22: scoped to a PR's
files, never a whole tree).

merge runs on every same-repo, non-draft pull request and its first step
fails, naming the job, when a test job is not a success or review failed;
only then is the squash auto-merge armed, with no checkout (measured on
claude-mods #38 and session-optimizer #73: a skipped required check
counts as satisfied). claude-review.yml is deleted, replaced by the
pipeline's review job; claude.yml stays. ci.yml and the other workflows
are untouched.

Red cells on day one: line coverage 82 % (ci.yml --cov-fail-under=82)
under the 90 % floor; the Windows install leg. Measured 2026-10-22 on this
checkout: uv sync --locked and tests_py/integration on SQLite (see the
pull request for the figures); actionlint 1.7.12 passes.

source: ADR-1115

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01BxsVCVscNG2Vb7fafCgqYR
@cdeust
cdeust merged commit 93cfe11 into main Oct 22, 2026
35 of 36 checks passed
@cdeust
cdeust deleted the ci/single-pipeline branch October 22, 2026 08:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant