Files
familysync/.planning/milestones/v1.1-phases/15-ci-skip-api-harness-jobs-for-doc-only-prs/15-03-PLAN.md
T
2026-06-18 22:21:38 -04:00

9.8 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
15-ci-skip-api-harness-jobs-for-doc-only-prs 03 execute 3
15-02
.gitea/workflows/publish.yml
false
truths artifacts key_links
Branch protection on main requires CI / fast-checks + CI / gate
Branch protection on main no longer requires CI / api or CI / harness directly
A doc-only PR (which skips api/harness) is mergeable — no missing-required-check deadlock
publish.yml's safety-gate comment names the new required checks (fast-checks + gate)
path provides contains
.gitea/workflows/publish.yml Updated safety-gate comment naming the new required checks CI / gate
from to via pattern
Gitea branch-protection (main) ci.yml gate job required status check 'CI / gate' (always-running aggregate) CI / gate
Finalize the gating surface: update Gitea branch protection on `main` to require `CI / fast-checks` + `CI / gate` and DROP the now-skippable `CI / api` and `CI / harness` direct requirements, and update the `publish.yml` safety-gate comment to name the new required checks.

This delivers Success Criterion 3 — the only step that makes doc-only PRs actually mergeable without a missing-required-check deadlock.

Purpose: With the heavy jobs conditionally skipped (Plan 02), a doc-only PR no longer emits CI / api / CI / harness statuses; leaving them required would deadlock the merge. The always-running CI / gate is the correct gating surface. Output: A Gitea branch-protection change (operator checkpoint — not automatable in YAML) + a one-comment edit to publish.yml.

ORDERING HAZARD (read before executing): This plan MUST run only AFTER Plan 02's ci.yml change has merged to main and Gitea has emitted at least one CI / gate commit-status. Dropping CI / api + CI / harness before CI / gate exists would leave main with no valid heavy-job gate, and adding CI / gate as required before it has ever reported can itself block PRs. Confirm CI / gate has appeared on a recent run before changing branch protection.

<execution_context> @$HOME/.claude/gsd-core/workflows/execute-plan.md @$HOME/.claude/gsd-core/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/15-ci-skip-api-harness-jobs-for-doc-only-prs/15-RESEARCH.md @.planning/phases/15-ci-skip-api-harness-jobs-for-doc-only-prs/15-PATTERNS.md Task 1: Update the publish.yml safety-gate comment to name the new required checks - .gitea/workflows/publish.yml (lines 13-17 — the "Safety gate" comment block currently naming "the three required checks (CI / fast-checks, CI / api, CI / harness)") - .planning/phases/15-ci-skip-api-harness-jobs-for-doc-only-prs/15-PATTERNS.md ("publish.yml Comment Update (advisory)" section — exact current text and the required-check change) Edit ONLY the safety-gate comment in publish.yml (lines ~14-17). Change the clause that names "the three required checks (CI / fast-checks, CI / api, CI / harness)" to name the new required checks: `CI / fast-checks` and `CI / gate`. Reflect that `api`/`harness` are now conditionally skipped and gated via the always-running `CI / gate` aggregate rather than being required directly. Do not change any publish.yml job, step, env, or trigger — comment text only. This is the documentation half; the actual protection change is Task 2 (operator). grep -q 'CI / gate' .gitea/workflows/publish.yml && grep -q 'CI / fast-checks' .gitea/workflows/publish.yml && ! grep -qE 'three required checks \(CI / fast-checks, CI / api, CI / harness\)' .gitea/workflows/publish.yml && command -v yq >/dev/null 2>&1 && yq -e '.jobs.publish' .gitea/workflows/publish.yml >/dev/null && echo OK - publish.yml safety-gate comment names `CI / fast-checks` and `CI / gate` as the required checks - publish.yml safety-gate comment no longer asserts `CI / api` and `CI / harness` are required (the old "three required checks" line is replaced) - no publish.yml job/step/env/trigger changed (only comment text); publish.yml still parses as valid YAML publish.yml's safety-gate rationale matches the new branch-protection reality. Task 2: Operator — update Gitea branch protection on main (drop api/harness, require gate) - .planning/phases/15-ci-skip-api-harness-jobs-for-doc-only-prs/15-RESEARCH.md (Gitea-Specific Notes #4 — branch-protection required-check update is a MANUAL Gitea admin step; Pitfall 1 — required-check deadlock from skipped jobs) Plan 02 added an always-running `CI / gate` aggregate job to ci.yml and made `CI / api` / `CI / harness` conditionally skipped on doc-only PRs. Once Plan 02 merged, Gitea emits a `CI / gate` commit-status on every PR run. Branch protection still requires the old `CI / api` + `CI / harness` contexts, which a doc-only PR will never emit — so until you make this change, doc-only PRs deadlock on "missing required checks". This change is a Gitea admin action that cannot be done in a workflow file. PRECONDITION — confirm first: open the most recent PR run in Gitea Actions for this repo and verify a `CI / gate` job ran and reported a status. Do NOT proceed until `CI / gate` has appeared at least once (Plan 02 must already be merged to main). If it has not appeared, stop — the protection change is premature.
Then update branch protection:
1. Gitea → this repo → Settings → Branches → edit the protection rule for `main`.
2. Under "Status Check Patterns" / required status checks, set the required contexts to EXACTLY these two:
   - `CI / fast-checks`
   - `CI / gate`
3. REMOVE these two from the required list (they are now conditionally skipped and gated via `CI / gate`):
   - `CI / api`
   - `CI / harness`
4. Save the protection rule.
(Alternative: the `tea` CLI / Gitea API can set branch-protection `status_check_contexts` to `["CI / fast-checks", "CI / gate"]` — login Bergerhouse — if you prefer not to use the UI.)

VERIFY the change end-to-end:
- Open a throwaway DOC-ONLY PR (edit only a `*.md` under docs/ or the repo root). Expect: `fast-checks` runs, `api`/`harness` show skipped, `CI / gate` passes, and the PR is MERGEABLE (no "missing required checks"). This proves SC-1 + SC-3.
- Open a throwaway CODE PR (touch a `*.ts` file). Expect: `fast-checks`, `api`, `harness`, and `CI / gate` all run; the PR is mergeable only when all are green. This proves SC-2.
- Close both throwaway PRs without merging.
Type "approved" once branch protection requires exactly `CI / fast-checks` + `CI / gate`, `CI / api` and `CI / harness` are no longer required, and the doc-only + code throwaway PRs behaved as described. Or describe what differed.

<artifacts_produced> This phase introduces the following new configuration state (Plan 03 portion). The plan-review source-grounding pass must treat these as newly-created, not drift:

  • Branch-protection required checks on main changed to CI / fast-checks + CI / gate (Gitea admin state, not a repo file)
  • publish.yml safety-gate comment updated to name the new required checks </artifacts_produced>

<threat_model>

Trust Boundaries

Boundary Description
operator → Gitea branch-protection config the required-check set decides whether unreviewed/failing code can merge to main
skipped heavy job → branch-protection check list a skipped job may emit no commit-status; a still-required skipped context would deadlock

STRIDE Threat Register

Threat ID Category Component Disposition Mitigation Plan
T-15-08 Denial of Service (deadlock) leaving CI / api/CI / harness required after the skip logic ships mitigate This plan explicitly drops both from required checks and requires the always-running CI / gate instead (RESEARCH Pitfall 1 / Gitea-Specific Note #4).
T-15-09 Elevation of Privilege (bypass window) dropping the heavy-job requirements BEFORE CI / gate exists leaves main ungated for code mitigate Ordering hazard called out: this plan is wave 3, depends_on: [15-02]; the checkpoint's PRECONDITION requires confirming CI / gate has reported at least once before any required-check edit.
T-15-10 Tampering (false sense of gating) publish.yml comment still claims api/harness are required, misleading a future maintainer mitigate Task 1 updates the comment to name CI / fast-checks + CI / gate.
</threat_model>
- Gitea branch protection for `main` requires exactly `CI / fast-checks` + `CI / gate`; `CI / api` and `CI / harness` are not required. - Throwaway doc-only PR is mergeable with api/harness skipped (SC-1/SC-3). - Throwaway code PR runs and gates on all jobs (SC-2). - publish.yml safety-gate comment names the new required checks.

<success_criteria> Maps to Phase 15 Success Criterion 3: branch protection requires CI / fast-checks + an always-running CI / gate aggregate; the direct api/harness requirements are dropped so a skipped heavy job never deadlocks the merge. (SC-1 doc-only mergeability and SC-2 code-PR gating are confirmed end-to-end here against the live protection rule.) </success_criteria>

Create `.planning/phases/15-ci-skip-api-harness-jobs-for-doc-only-prs/15-03-SUMMARY.md` when done.