From c62db0d5d1e3c7508831bb3933e44f1b9a96efa8 Mon Sep 17 00:00:00 2001 From: cyber-ayi <259769279+cyber-ayi@users.noreply.github.com> Date: Wed, 3 Jun 2026 16:13:00 -0700 Subject: [PATCH] docs(ci): harness-ci is a signal, not a hard ruleset gate (align with homelab-ops) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Making harness-ci a required status check deadlocked the adr-assign numbering PR (GITHUB_TOKEN-authored PRs don't trigger workflows → the required check never reports). homelab-ops — the governance this project mirrors (adr-0001) — does NOT hard-require any CI check; protect-main there is only deletion/non_fast_forward/ pull_request, and checks are signals merged manually/auto. Aligns commonplace to that: CI checks are signals; cc waits for green before self-merging; protect-main keeps PR-required + bypass_actors: []. A real hard gate is deferred to Phase D (GitHub App lets bot PRs trigger checks, no deadlock). - ROADMAP CI table: harness-ci / adr-pr-check -> "signal", with the rationale. - harness-ci.yml header: drop the obsolete "so it can be a required check" note. NOTE: the matching ruleset change (remove the required_status_checks rule from protect-main) is an operator action — the safety classifier blocks the agent from loosening a protected-branch control. Session-Id: 019e8d56-605a-7b45-8ef0-21ee576aa7a9 Agent: cc-rc-bot Co-authored-by: cyber-ayi <259769279+cyber-ayi@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 (1M context) --- .github/workflows/harness-ci.yml | 9 ++++++--- ROADMAP.md | 12 +++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.github/workflows/harness-ci.yml b/.github/workflows/harness-ci.yml index 1a33cc2..31b7436 100644 --- a/.github/workflows/harness-ci.yml +++ b/.github/workflows/harness-ci.yml @@ -4,9 +4,12 @@ name: harness-ci # 100% coverage of the runtime surface. The bridge contract (T1) and every adapter # (T2+) must stay green here. # -# Runs on EVERY pull request (no paths filter) so it can be a *required* status -# check: a path-filtered required check never reports on unrelated PRs and would -# block them forever. npm is cached, so a no-harness PR still completes in ~15s. +# Runs on EVERY pull request as a signal (no paths filter). It is NOT a hard +# ruleset-required check — cc waits for green before self-merging, and CI checks +# are signals not gates here, matching homelab-ops governance (adr-0001). (A hard +# required check deadlocks GITHUB_TOKEN-authored bot PRs, e.g. adr-assign numbering, +# which cannot trigger workflows; a real hard gate waits for Phase D's GitHub App.) +# Running on all PRs keeps the signal universal; npm is cached (~15s). on: pull_request: diff --git a/ROADMAP.md b/ROADMAP.md index 18ea57b..8ea1e81 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -63,10 +63,16 @@ are unblocked and parallelize, and T3 proceeds on its own. ### Automated acceptance (CI) -| Gate | Scope | Required? | +CI checks are **signals, not hard ruleset gates** — matching homelab-ops governance +(`adr-0001`): `protect-main` only enforces `deletion` / `non_fast_forward` / +`pull_request`. cc waits for green before self-merging; nothing mechanically blocks +a merge on a red check (a deliberate hard gate is deferred to Phase D, where a +GitHub App lets bot PRs trigger checks without the numbering-PR deadlock). + +| Check | Scope | Enforcement | |---|---|---| -| **`harness-ci`** (`.github/workflows/harness-ci.yml`) | every PR: `npm ci` → typecheck → tests + **100% coverage** of the L2 runtime surface | **yes** — required status check on `protect-main` | -| **`adr-pr-check`** | ADR invariants on `decisions/**` PRs | yes (on ADR PRs) | +| **`harness-ci`** (`.github/workflows/harness-ci.yml`) | every PR: `npm ci` → typecheck → tests + **100% coverage** of the L2 runtime surface | signal; cc gates self-merge on green | +| **`adr-pr-check`** | ADR invariants on `decisions/**` PRs | signal (on ADR PRs) | L2 toolchain: `harness/` is the TypeScript project root (`package.json`, strict `tsconfig`, tsx + `node:test` + ajv). `drives/` will be the Python root (T4).