Skip to content
Back to skills

Dev Uat Promotion Skill

ASecurity

Orchestrate batch dev-to-uat branch promotion across many repos — remote dedup, fast-forward vs back-merge vs uat-only classification, protected branch PR fallback, verification, and per-ticket result comments.

  • 6 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 28, 2026
devopsgobashgitapidevops

Works with

  • vscode
  • api

Security analysis

A100/100

Scanned September 28, 2026

npx -y skills add darellchua2/opencode-config-template --skill dev-uat-promotion-skill --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dev Uat Promotion Skill?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Dev Uat Promotion Skill
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/darellchua2-dev-uat-promotion-skill/badge)](https://www.skillsdirectory.com/skills/darellchua2-dev-uat-promotion-skill)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
---
name: dev-uat-promotion-skill
description: >-
  Orchestrate batch dev-to-uat branch promotion across many repos — remote
  dedup, fast-forward vs back-merge vs uat-only classification, protected
  branch PR fallback, verification, and per-ticket result comments.
license: Apache-2.0
compatibility: opencode
category: Git/Workflow
---

## What I do

I am an **orchestration skill** for promoting `dev` → `uat` across a set of
repos (one tracker task per repo — JIRA task or GitHub issue — or ad-hoc). I
do NOT execute git operations
inline. I provide the primary agent with:

1. **Inventory logic** — how to enumerate repos and dedupe remotes (sibling
   clones and renamed GitHub repos are the norm, not the exception)
2. **Classification matrix** — ff-able / divergent / uat-only / equal, from a
   FRESH fetch
3. **Execution invariants** — the back-merge-first ordering, no force-push,
   main untouched, quarantine-on-failure
4. **Conflict resolution policy** — mechanical vs decision-grade conflicts
5. **Protected-branch fallback** — the PR path when direct uat push is
   rejected
6. **Ticket hygiene contract** — result comment + transition rules (tracker
   conventions — JIRA policy per `ticketing-skill`)

Execution is plain git run by the primary agent (or delegated to
`repo-ops-specialist-subagent` with my §Delegation Spec).

## When to use me

Invoke me when asked to "promote dev to uat" for one repo or a batch, when
executing promotion tracker tasks (e.g. "Promote <repo> dev to uat"), or when
`/run-worktree-pipeline` hits promotion ops tickets (git-refs-only — no feat
branch, PLAN, or PR applies except the protected-branch fallback).

## Governance

> **Content Rule:** This skill MUST contain ZERO inline bash scripts and ZERO
> inline YAML templates. The process is described as ordered rules; any script
> written from it lives in `/tmp/opencode/` for the run only. This rule is
> auditable — inline executable script bodies are a defect.

This skill defers to:

| Aspect | Governing Skill / Agent | Section Reference |
|--------|-------------------------|-------------------|
| Branch flow & release conventions | `version-bump-standard-skill` | §Branch Flow |
| Merge strategy & tag mapping | `semantic-release-convention-skill` | §Branch-Aware Tag Mapping |
| New promotion tickets | `ticketing-skill` | full flow |
| PR on protected branches | `pr-workflow-subagent` | PR creation + gates |
| Bulk execution delegation | `repo-ops-specialist-subagent` | §Delegation Spec below |

## Inventory & Remote-Identity Dedup

Before ANY classification:

1. Enumerate candidate repo directories (e.g. `~/VSCODE/canvastekk-*`).
2. For each, read `git remote get-url origin` and normalize (strip `.git`).
3. **Resolve the canonical GitHub name**: `gh api repos/<owner/repo> --jq .full_name`.
   A configured URL may be an OLD NAME of a renamed repo — GitHub redirects
   old URLs, so two directories with different configured URLs can be ONE
   remote. Confirmed instance: `floor-flatness-assessment-demo` →
   `canvastekk-point-cloud-app`.
4. Group directories by canonical remote. **One promotion per distinct
   remote**; sibling-directory tickets for the same remote are FULFILLED
   (verified + commented), never re-executed.

## Classification (per distinct remote, fresh fetch first)

Fetch `dev` and `uat` immediately before deciding; never classify on stale
refs (a sibling promotion minutes ago can already have changed the remote).

| State | Test (`merge-base`) | Action |
|-------|--------------------|--------|
| `equal` | dev SHA == uat SHA | Nothing; report already-equal |
| `ff-able` | uat is ancestor of dev | Push dev → uat (fast-forward) |
| `uat-only` | dev is ancestor of uat | Push uat → dev (the back-merge IS the ff), then equal |
| `divergent` | both have unique commits | Back-merge uat into dev (§Back-Merge Procedure), push dev, then push dev → uat |

## Execution Invariants

- **Back-merge-first**: uat-specific commits land in dev BEFORE any uat push.
  dev → uat must always be a fast-forward.
- **No force-push anywhere.** A rejected push is a signal (remote moved, or
  branch protected) — re-fetch and re-classify, never retry blindly.
- **Main untouched.** Pushes target `refs/heads/dev` and `refs/heads/uat`
  only.
- **Fresh verification before every push**: ancestor checks against
  just-fetched refs; pushes use explicit SHAs so a concurrent remote update
  causes rejection, not corruption.
- **Never touch the user's working checkouts** beyond `git -C <repo> fetch` —
  merges happen in throwaway worktrees.
- **Worktrees**: `git worktree add --detach /tmp/opencode/prom-<KEY>
  <origin/dev SHA>`. On failure, QUARANTINE — keep the worktree for
  inspection, continue the batch, report. Before re-using a quarantined path,
  `git worktree prune` (a stale registration makes `worktree add` fail with
  exit 128).
- Back-merge commit message: `chore: back-merge uat into dev before dev-to-uat
  promotion (<KEY>)`.

## Conflict Resolution Policy

On merge conflict inside the worktree:

1. **Characterize first**: `git diff --name-only --diff-filter=U`.
2. **Mechanical** (both-append index/list files, e.g. `LEARNINGS/_index.md`):
   union-merge; then PROVE losslessness — zero lines present in the losing
   side but absent from the result (`comm -13`). Non-zero → treat as
   decision-grade.
3. **Modify/delete**: decide by lifecycle. A PLAN (or other artifact) for a
   **Done** ticket where dev deleted it as cleanup → **deletion wins**;
   preserve any unique knowledge from the surviving-but-deleted side as a
   comment on that artifact's tracker ticket. Anything else → decision-grade.
4. **Decision-grade**: quarantine the repo (keep worktree, no pushes), comment
   the ticket with the exact conflict, continue the batch, surface to the user.

## Protected Branches (push policy classification)

Some `uat` branches reject direct pushes (e.g. `canvastekk-devops`: PR-only,
merge commits forbidden, required check `check-source-branch`). The first
rejected push is the probe:

1. On a GH006 protected-branch rejection: back-merge into dev as usual (dev
   accepted the merge), then open `gh pr create --base uat --head dev`.
2. Watch required checks to green.
3. Merge with **squash** — rebase merge fails when the PR carries a back-merge
   commit ("can't be rebased").
4. Squash rewrites SHAs, so verify **content equality**
   (`git diff origin/dev origin/uat` empty) instead of SHA equality, and
   record the SHA divergence as protection-design in the ticket comment.

## Verification Gate (per remote)

- Direct-push repos: `git ls-remote` shows dev == uat.
- Squash-merged protected repos: content-diff empty.
- Re-verify via ls-remote (remote truth), not local refs.

## Ticket Hygiene

- Every ticket gets a result comment: action taken, resulting SHAs,
  verification method, and that the uat push triggers UAT deploys.
- Transition to **Done** only when the verification gate passed.
- `blocked-by:` unmet → comment the skip reason, leave open.
- Fulfilled-by-sibling tickets: comment the dedup evidence (canonical remote
  name) and transition Done.

## Deployment Warning

Pushing `uat` triggers UAT deployments (Amplify for FE apps, CI for
services). Surface this before the first push of a batch.

## Delegation Spec

Payload for `repo-ops-specialist-subagent`:

```
repos: [<abs paths>]
tickets: { <KEY>: { repo, action: ff|back-merge|uat-only, blocked-by? } }
invariants: back-merge-first; no force-push; main untouched;
            worktrees in /tmp/opencode/prom-<KEY>; quarantine-on-conflict
verification: ls-remote dev==uat (content-diff for squash-merged)
reporting: per-ticket comment + Done transition on pass
```

## Return Contract

- `complete` — every distinct remote promoted and verified; all tickets
  commented (Done or justified skip)
- `partial` — one or more quarantined or skipped; per-repo table with exact
  conflict or blocker
- `failed` — pre-execution abort (missing remotes, git unavailable)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…