From 7a2bf9e4750dae56422d179e0aedde8d971271a4 Mon Sep 17 00:00:00 2001 From: luiseiman Date: Wed, 3 Jun 2026 14:21:53 -0300 Subject: [PATCH] chore(practices): capture CI-hygiene practice + incorporate two lessons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Process the practices inbox (1 item to active). Lessons from PR #3: - _common.md Git: verify base-branch CI is green before opening a PR — a preexisting red required check blocks every PR and masks degraded workflows. - CLAUDE.md Audit System: flag that score.sh (bash CI gate) and audit_all.py (Python re-auditor) reimplement the checklist independently — any checklist change must update both engines + audit.yml + docs. practices/active/2026-06-03-verify-ci-state-before-pr.md documents both. Co-Authored-By: Claude Opus 4.8 --- .claude/rules/_common.md | 1 + CLAUDE.md | 2 +- .../2026-06-03-verify-ci-state-before-pr.md | 39 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 practices/active/2026-06-03-verify-ci-state-before-pr.md diff --git a/.claude/rules/_common.md b/.claude/rules/_common.md index 724efe4..8060f40 100644 --- a/.claude/rules/_common.md +++ b/.claude/rules/_common.md @@ -12,6 +12,7 @@ globs: "**/*.md,**/*.sh,**/*.yml,**/*.json,**/*.tmpl,**/*.py,**/*.ts,**/*.tsx,** - Branch naming: feature/, fix/, refactor/, chore/ - Customize commit/PR trailers via `attribution.commit` and `attribution.pr` in `settings.json` — supersedes the deprecated `includeCoAuthoredBy` boolean - For self-hosted GitHub/GitLab/Bitbucket, set `prUrlTemplate` to point the footer PR badge at the right host +- Before opening a PR, confirm CI is green on the base branch (`gh run list --branch main --limit 5`). A preexisting red required check blocks every PR and masks degraded workflows — fix or flag it first, don't stack new work on a blocked pipeline ## Naming - Descriptive variable/function names, no cryptic abbreviations diff --git a/CLAUDE.md b/CLAUDE.md index 019b547..37cd15b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -73,7 +73,7 @@ Seven subagent definitions in `agents/`: researcher (read-only exploration), arc ### Audit System -Two-dimension model (v4.x). **Dimension A — Native Health** (`score`, 0-10): 5 obligatory items (0-2) + 10 recommended (0-1), normalized as `obligatory*0.7 + recommended*0.3`. Security-critical items (settings.json, block-destructive hook) cap it at 6.0 if missing. Measures good use of native Claude Code (auto-memory as index, permission cascade, attribution, sandbox, deny rules). **Dimension B — dotforge Adoption** (`forge_adoption`, 0-5): behaviors/workflows/override-loop/domain-rules/sync-recency. **Informational — does NOT affect Native Health.** A native-first project scoring B=0 with A=10 is a desirable outcome (see `.claude/rules/domain/native-vs-dotforge-boundary.md`). `audit/checklist.md` + `audit/scoring.md` are the source of truth; registry in `registry/projects.yml` tracks both across managed projects. +Two-dimension model (v4.x). **Dimension A — Native Health** (`score`, 0-10): 5 obligatory items (0-2) + 10 recommended (0-1), normalized as `obligatory*0.7 + recommended*0.3`. Security-critical items (settings.json, block-destructive hook) cap it at 6.0 if missing. Measures good use of native Claude Code (auto-memory as index, permission cascade, attribution, sandbox, deny rules). **Dimension B — dotforge Adoption** (`forge_adoption`, 0-5): behaviors/workflows/override-loop/domain-rules/sync-recency. **Informational — does NOT affect Native Health.** A native-first project scoring B=0 with A=10 is a desirable outcome (see `.claude/rules/domain/native-vs-dotforge-boundary.md`). `audit/checklist.md` + `audit/scoring.md` are the source of truth; registry in `registry/projects.yml` tracks both across managed projects. **Two scoring engines reimplement the checklist independently — `audit/score.sh` (bash, CI gate) and `scripts/audit_all.py` (Python, 12-project re-auditor). Any checklist change must update BOTH plus `audit.yml` and the docs (`README.md`, `docs/usage-guide.md`, `docs/guia-uso.md`); grep all consumers before planning the edit.** ### Integrations diff --git a/practices/active/2026-06-03-verify-ci-state-before-pr.md b/practices/active/2026-06-03-verify-ci-state-before-pr.md new file mode 100644 index 0000000..e8870f9 --- /dev/null +++ b/practices/active/2026-06-03-verify-ci-state-before-pr.md @@ -0,0 +1,39 @@ +--- +id: practice-2026-06-03-verify-ci-state-before-pr +title: Verify CI state on main before opening a PR — preexisting redness blocks unrelated work +source: "feature/audit-two-dimensions (PR #3) — discovered while merging the two-dimension audit" +source_type: process +discovered: 2026-06-03 +activated: 2026-06-03 +status: active +tags: [ci, workflow, pre-pr, process, regression-hygiene, fan-out-edit] +tested_in: null +incorporated_in: [".claude/rules/_common.md", "CLAUDE.md"] +replaced_by: null +priority: medium +--- + +## Description + +Two independent, well-scoped lessons from a session that reoriented the audit to a two-dimension model and then hit a wall at merge time. + +**1. Check CI health on `main` before opening a PR.** The `validate` job (ci.yml) was red on `main` from two accumulated, unnoticed causes: `test_on_off.sh` asserted `search-first` enabled=true after it was deliberately disabled in v3.6.1, and `plugin.json` stayed at 3.0.4 after `VERSION` bumped to 4.0.0. Because `validate` runs on every PR, *every* PR in the repo was blocked by failures unrelated to its own changes. Separately, `audit.yml` could never post its score comment (missing `permissions: pull-requests/issues write` → 403), so the degraded CI was invisible — no comment, no signal. A green-looking repo can hide a CI that has silently rotted. + +**2. Grep ALL consumers before planning a fan-out edit.** Reorienting the audit `checklist.md` touched a system with many coupled consumers: two independent scoring engines (`audit/score.sh` in bash, `scripts/audit_all.py` in Python), the CI workflow (`audit.yml`), and three live docs. The initial plan listed 5 files; the real surface was 9. The consumers were discovered mid-execution, forcing a re-plan. A pre-plan `grep` for every reference to the artifact being changed would have sized the work correctly upfront. + +## Evidence + +- PR #3 went green only after 3 extra fix commits: `fix(ci)` workflow permissions, `fix` plugin.json version, `fix(test)` self-baseline test_on_off. +- Root cause of test failure: index.yaml change in v3.6.1 was deliberate (flag-consume false positives) but the test was never updated — the test was stale, not the config. +- Two scoring engines (`score.sh`, `audit_all.py`) reimplement the same checklist independently — both had to be migrated in lockstep. + +## Derived rule + +- **Before opening a PR**: run `gh run list --branch main --limit 5` (or `gh pr checks` on a recent PR) to confirm CI is green on `main`. If red, fix or flag the preexisting failure first — don't stack new work on a blocked pipeline. +- **Before planning any edit to a shared artifact** (checklist, schema, settings partial, template marker): `grep -rl ""` across the repo to enumerate every consumer, and include them all in the plan. Treat duplicate engines (bash + python implementing the same logic) as a smell worth flagging. + +## How to apply + +Candidate homes if validated: +- A pre-PR checklist note in `.claude/rules/_common.md` (Git section) or a `domain/` rule on CI hygiene. +- A planning-discipline line in the audit-related skills that edit `checklist.md`/`scoring.md`, pointing at the dual-engine coupling (`score.sh` + `audit_all.py` must stay in sync).