docs(skills): move uat→main merge-gate policy from coding-standards to sdlc

Reviewer feedback (COrtHvtYnuZx6DmhztGD50uGnKVJajPf): the merge-gate
policy is a process / SDLC rule, not a code-quality / coding-standard
rule, so it belongs in the sdlc skill.

  - skills/sdlc/SKILL.md: add new '## uat→main merge-gate policy'
    section after Phase 5 with the full policy, the three categories,
    the engineer workflow, and the 'when uncertain' escalation path.
    Update frontmatter description and intro paragraph to point at
    the new local section. Re-point the branch-strategy table row
    and Phase 4 step 3 at the local section.
  - skills/coding-standards/SKILL.md: remove the duplicate
    'uat→main merge-gate policy' section (it now lives in sdlc) and
    replace it with a one-paragraph pointer to sdlc. Update the
    frontmatter description to remove the policy bullet and add a
    'lives in sdlc, not here' line.

No behavior change: the policy content is identical, only its home
file moved. The PR is now an sdlc PR with a small coding-standards
follow-on, which matches the reviewer's point.

Refs: GRO-2377
Triggers: GRO-2358, GRO-2359
Source rule: GRO-2348 (merge-whitelist fix)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-06-12 01:39:27 +00:00
parent 152c52f47c
commit 8930a8d5f1
2 changed files with 42 additions and 23 deletions
+4 -17
View File
@@ -3,9 +3,9 @@ name: coding-standards
description: >
Engineering quality bar for GroomBook code: priority ordering of correctness
vs. clarity vs. maintainability vs. performance vs. elegance, PR and test
requirements, no-hardcoded-values rules, branch discipline, the no-self-
merge contract, and the uat→main merge-gate policy (CTO Gitea Approve
reserved for novel auth, infra/prod-affecting, and risk-flagged merges).
requirements, no-hardcoded-values rules, branch discipline, and the
no-self-merge contract. The uat→main merge-gate policy lives in the `sdlc`
skill, not here.
---
# Coding Standards
@@ -60,20 +60,7 @@ Push to `git.farh.net` only. Never Docker Hub for first-party images.
## uat→main merge-gate policy
The **CTO Gitea Approve click is not the default gate** on `uat → main` PRs. Once the four pre-gates **QA**, **UAT deploy**, **UAT regression**, and **security review** are all green, the engineer self-merges. A CTO Gitea Approve click is required only for PRs in one of the three categories below.
### Categories that require CTO Gitea Approve
1. **Novel auth / session paths** — login, OIDC, OOBE, session middleware, token issuance, password reset, MFA, or any new auth provider integration. Routine changes to auth-gated UI (button styling, error messages, form layout, copy edits) are **not** in this category.
2. **Infra / prod-affecting merges** — deploys, infra manifests, secrets, GitOps overlays, CI/CD pipelines, `main` branch protection, production routing/ingress, or any change that mutates prod state. **All Phase 5 infra overlay PRs (`groombook/infra`) require CTO Gitea Approve** without exception.
3. **Risk-flagged merges** — any PR that carries the `risk:cto-approve` label, or where the CTO or CEO has explicitly requested CTO sign-off in the PR or issue thread.
The engineer who opened the PR classifies it against the three categories above (escalating to the CTO via comment if the call is unclear), then:
* **In a category** → request a CTO Gitea Approve click. The engineer merges once the CTO has approved.
* **Outside all three categories** → no CTO click needed. The engineer merges once the four pre-gates are green.
The pre-gates (QA, UAT deploy, UAT regression, security) do **not** change. This rule only removes the CTO Gitea Approve click from the default `uat → main` path for routine PRs that already pass every pre-gate.
The uat→main merge-gate policy lives in the `sdlc` skill, not here. The one-line summary: the engineer self-merges a uat→main PR once the four pre-gates (QA, UAT deploy, UAT regression, security) are green and the CEO code review is APPROVED on the Paperclip issue. A CTO Gitea Approve click is reserved for three categories: novel auth / session paths, infra / prod-affecting merges, and risk-flagged merges. See the `sdlc` skill — "uat→main merge-gate policy" — for the full rule, the category list, and the "when uncertain" escalation path.
## When uncertain
+38 -6
View File
@@ -3,14 +3,17 @@ name: sdlc
description: >
Software development lifecycle for GroomBook application repos. Covers
Gitea authentication, the 3-branch dev/uat/main strategy, the SDLC
pipeline phases 1-5, the Stage 1 CI image build, the authentication
framework, and application-tool policy. For infrastructure
(groombook/infra), see the devops skill.
pipeline phases 1-5, the uat→main merge-gate policy (engineer
self-merge when pre-gates are green; CTO Gitea Approve only for
novel auth, infra/prod-affecting, and risk-flagged merges),
the Stage 1 CI image build, the authentication framework, and
application-tool policy. For infrastructure (groombook/infra), see
the devops skill.
---
# Software Development Lifecycle
This skill governs **application code repos**. For infrastructure (`groombook/infra`), see the `devops` skill. For PR/test discipline and the `cc @cpfarhood` visibility rule, see `coding-standards`. For non-negotiable safety rules, see `safety`.
This skill governs **application code repos**. For infrastructure (`groombook/infra`), see the `devops` skill. For PR/test discipline and the `cc @cpfarhood` visibility rule, see `coding-standards`. For non-negotiable safety rules, see `safety`. The **uat→main merge-gate policy** (which uat→main PRs need a CTO Gitea Approve click vs. engineer self-merge) is defined in this skill — see "uat→main merge-gate policy" below.
## Gitea authentication
@@ -26,7 +29,7 @@ Three long-lived branches map to the three deployment environments:
|--------|-------------|-----------|-----------|
| `dev` | Dev | Engineer | CI passes |
| `uat` | UAT | Engineer | QA code review approval |
| `main` | Production | Engineer | UAT validation, security review, and the `coding-standards` uat→main merge-gate policy |
| `main` | Production | Engineer | UAT validation, security review, and the uat→main merge-gate policy (below) |
**Engineers always target `dev` first** — never `uat` or `main` directly.
- Feature branches: `<agent-name>/<short-description>`.
@@ -70,7 +73,7 @@ tea pr create --base dev --title "..." --body "... cc @cpfarhood"
1. **Engineer** opens a PR from `uat` to `main`.
2. **CI** fail → back to **Engineer** (return to Phase 1).
3. **CI** pass → **Engineer** classifies the PR against the `coding-standards` **uat→main merge-gate policy**:
3. **CI** pass → **Engineer** classifies the PR against the **uat→main merge-gate policy** (below):
* **In a category that requires CTO Gitea Approve** (novel auth / session paths, infra / prod-affecting merges, `risk:cto-approve` label or explicit CTO/CEO sign-off request) → Engineer pings the CTO for a Gitea Approve click.
* **CTO** rejected → back to **Engineer** (return to Phase 1).
* **CTO** approved → continue to step 4.
@@ -83,6 +86,35 @@ tea pr create --base dev --title "..." --body "... cc @cpfarhood"
The **Engineer** opens a PR against `groombook/infra` to update the relevant Kustomize overlay with the new image tag. From this point the work follows the **`devops` skill pipeline** end-to-end — review, merge, and Flux reconciliation are all owned there. On merge, Flux rolls out the updated pods to production (`https://demo.groombook.dev`).
## uat→main merge-gate policy
This is the process policy that governs which `uat → main` PRs need a CTO Gitea Approve click vs. engineer self-merge. It exists because the Gitea `required_approvals` branch-protection gate is satisfied only by a Gitea Approve click — the Paperclip issue-thread QA/UAT-deploy/UAT-regression/security approvals do **not** clear it. The engineer **MUST** classify every `uat → main` PR against this policy before merging.
### The four pre-gates are unchanged
A `uat → main` PR is mergeable only when all of these are green on the linked Paperclip issue: QA code review, UAT deploy, UAT regression, and security review. The CTO Gitea Approve click is **in addition to** those four when the PR falls in one of the categories below; it does not replace any of them.
### Categories that require CTO Gitea Approve
A CTO Gitea Approve click is required only for PRs in one of the following three categories:
1. **Novel auth / session paths.** Login, OIDC, OOBE, session middleware, token issuance, password reset, MFA, or any new auth provider integration. Routine changes to auth-gated UI (button styling, error messages, form layout, copy edits) are **not** in this category.
2. **Infra / prod-affecting merges.** Deploys, infra manifests, secrets, GitOps overlays, CI/CD, `main` branch protection, prod-affecting routing/ingress, or any change that mutates prod state. **All Phase 5 infra overlay PRs in `groombook/infra` require CTO Gitea Approve without exception.**
3. **Risk-flagged merges.** The PR carries the `risk:cto-approve` label, **or** the PR or its linked Paperclip issue thread contains an explicit CTO/CEO sign-off request.
### Engineer workflow
The engineer who opened the PR classifies it against the three categories above (escalating to the CTO via comment if the call is unclear), then:
* **In a category** → request a CTO Gitea Approve click. Engineer merges once the CTO has approved.
* **Outside all three categories** → no CTO click needed. Engineer merges once the four pre-gates are green.
**Board/CEO approval is via SDLC code review (judgment) on the Paperclip issue, not via a Gitea Approve click.** The CEO's role at Phase 4 is to perform the code review on the Paperclip issue thread; that approval satisfies the "CEO approved" pre-condition and is recorded in Paperclip, not in Gitea.
### When uncertain
If a `uat → main` PR does not obviously belong to a category, comment on the PR with `@<the-dogfather>` (or escalate to the CEO if the CTO is unavailable) and pause the merge. Do not guess the category — a routine PR is a routine PR, but a borderline PR is cheaper to escalate than to misclassify.
## Stage 1 CI — Image build
Triggered automatically on every merge to `main` in an application repo: