Create a PR or MR from the current branch to a destination branch asked to the user, on any git repo with a configured remote.
Source = current branch, without exception. There are two valid modes, which the skill infers from the source→destination pair (see Modes: implementation and promotion):
- Implementation PR — from a working branch (
feature/,fix/,chore/,refactor/,test/,hotfix/…) to its integration or deployment branch. This is the default case.- Promotion PR — from an integration branch to a deployment branch (
develop → master,develop → release/x,release/x → main). It does not bring new code: it consolidates work that already passed its gates when it was integrated.The mode is decided by a single decision table, evaluated in Step 3 with the destination already known; see Modes: implementation and promotion. It also defines when it stops and when it asks.
A dirty working tree does not stop the flow, but it is not committed in the pre-flight: the gates of Step 4 verify commit + working tree, so pending changes are inventoried here and committed only once, before the push (Step 5), automatically invoking the flow of the skill
git-commit(without asking the user whether they want to commit — the decision to invoke it is automatic). Note:git-commithas no silent mode — a single commit runs it without confirming, but it may pause to confirm its split proposal when the diff is spread across several commits (withcommitConfirmation = always) and it may stop entirely in the face of a protected branch or a failed hook; that behavior is not suppressed when invoking it from here.Platform is auto-detected from the remote
origin. Do not ask.Mandatory and blocking quality gates: in an implementation PR, always
quality-check,code-reviewandcoverage-verifyare run; in a promotionone, onlyquality-check. In both modes, if the Definition of Done (docs/policies/definition-of-done.md) exists, it is verified. All applicable ones must be passed; if any is not, the PR is not created. There is no "create as draft" or "ignore and continue" flow, nor any way to skip a gate that applies.Does not include: modifying code on one's own initiative, merges, rebases, resolving conflicts, assigning reviewers/labels/milestones, editing existing PRs. (Corrections are only applied if the user explicitly authorizes them — see Handling failures at the gates.)
Modes: implementation and promotion
The normal cycle has two hops, not one: the work is implemented on a branch, integrated into an integration branch (develop), and from there several work items are promoted together to a deployment branch (master, main, release/*). This skill covers both.
| Implementation PR | Promotion PR | |
|---|---|---|
| Source | Work branch: prefix feature/, fix/, chore/, refactor/, test/, hotfix/, or the repo's equivalent |
Integration or deployment branch: develop, release/*, main, master, trunk |
| Target | Its integration branch | Another integration/deployment branch, downstream |
| What it contributes | New code, not yet reviewed | Nothing new: it consolidates already integrated work items |
| Gates | quality-check + code-review + coverage-verify (+ DoD) |
quality-check (+ DoD). See Gates in a promotion PR |
| Description | Commits in the range + ticket | Work items being promoted (US-XXX/WI-XXX) + commit delta |
Decision table. It is the only classification rule of the skill; it is evaluated in Step 3, with the target already known. Step 1 does not classify or stop: it only detects whether the source has an implementation prefix.
| # | Source | Target | Result |
|---|---|---|---|
| 1 | Implementation prefix (feature/, fix/, chore/, refactor/, test/, hotfix/, or the repo's equivalent) |
Integration/deployment branch | Implementation PR. Default path, without confirmation. |
| 2 | Integration/deployment branch | Another, downstream | Promotion PR, after confirmation (see below). |
| 3 | Integration/deployment branch | Up stream, or the same one | Stop. It is not a promotion. |
| 4 | Any | Implementation branch | Stop. This skill does not open PRs toward a work branch. |
| 5 | No recognizable prefix and it is not an integration branch | Any | Ask which category the branch belongs to (hotfix-cache, PROJ-1234...). If the user places it, apply the corresponding row; if not, stop. Do not classify it as a promotion by elimination. |
| 6 | Prefix spike/ (spike/WI-XXX-…, the branch of a WI of type spike) |
Any | Stop, always. Spikes are not integrated nor is a PR opened for them: their deliverable is the spike-report.md in the WI folder, and the definitive development is formalized with /work-define or /work-plan (see work-implement/references/work-items.md → spike variant). Say it for that reason; do not offer an alternative within this skill. |
The confirmation in row 2 is never omitted. Being stopped on develop is also what happens when someone forgot to switch branches —the typical case right after work-integrate, which leaves HEAD at the base—, and there the correct PR is a different one. It is the only defense against that mistake.
What counts as an integration or deployment branch. By default
main,master,develop,trunkandrelease/*. If the repo uses other names (staging,uat,qa,produccion) and the user indicates one as the target, treat it as such: the target rules. Do not invent your own hierarchy or require the repo to follow git-flow.
What «downstream» is. The canonical order of the cycle is:
rama de implementación → develop → release/* → main | master
The target is downstream if it appears to the right of the source in that order. develop → master is; master → develop is not, and that is why row 3 cuts it off. Do not use «the branch it is born from» as the criterion: in git-flow develop is born from master, so that reading would classify the canonical promotion as a step backward and disable the entire mode. If the repo uses other names, the order is set by the user when indicating the target; when in doubt about the direction, ask instead of assuming.
Synchronizing a branch backward (bringing master to develop after a hotfix) is a merge or a rebase, not a PR of this skill.
Platform detection
Heuristic by host of git remote get-url origin:
| Host | Platform | CLI |
|---|---|---|
github.com or GitHub Enterprise |
GitHub | gh |
gitlab.com or self-managed GitLab host |
GitLab | glab |
bitbucket.org |
Bitbucket Cloud | REST + curl (or installed CLI) |
Host with segment /scm/ or Bitbucket Server |
Bitbucket Server | REST + curl |
dev.azure.com or *.visualstudio.com |
Azure Repos | az repos |
| Gitea/Forgejo markers | Gitea | tea |
| Any other | — | Try a known installed CLI; if nothing fits, stop and warn |
Verify that the chosen CLI is installed (<cli> --version); if it is missing, stop and warn. Credentials are the responsibility of the user's environment (environment variables, ~/.netrc, prior CLI config).
Paths of the shared references
${PLUGIN_ROOT} is the root of the installed plugin (the folder that contains skills/, agents/ and references/), and every shared reference of this skill is written as ${PLUGIN_ROOT}/references/<archivo>.md. To resolve it: the root is the folder from which this file was loaded, two levels up (<raíz>/skills/<nombre>/SKILL.md) — the client announces that location when invoking the skill (e.g. «Base directory for this skill: …»). If that location is not available, locate the installation by searching for the plugin manifest: PLUGIN_ROOT="$(dirname "$(grep -rl '\"name\": *\"sdd-devkit\"' "$HOME/.claude/plugins" --include=plugin.json 2>/dev/null | head -1)")". In both cases, verify before using it that $PLUGIN_ROOT/references/language.md exists. The destination of each markdown link (../../references/…) exists only to navigate the repository on GitHub or in an editor: do not resolve it from the working directory. Never look for references/ in the project: a <proyecto>/references/language.md that does not exist is not a missing file, it is a misresolved path — fix the root and read again, without asking the user or skipping the read.
Language resolution
Before executing this skill, you MUST read ${PLUGIN_ROOT}/references/language.md.
The rules of language.md are mandatory and take priority for determining the language of all artifacts, documents and messages generated by this skill.
Do not continue until you have read and applied language.md.
Deliberate exception: a title or description explicitly provided by the user are respected literally, in the language in which they were written. When the resolved language requires translating the title, the ticket prefix ([US-042], [TK-007]) is kept intact; the subjects of commits cited in the description are not translated: they go in literally to preserve traceability. If language.md reaches its asking step, offer as the default option the predominant language of the commits in the range origin/<destino>..HEAD — but still ask, do not decide it on your own.
Links to project files: you MUST read and apply ${PLUGIN_ROOT}/references/linking.md — every existing file or folder of the project that this skill mentions in an artifact, document or message (identifiers such as US-XXX or WF-XXX, paths, indexes) is written as a Markdown link that opens it.
Flow
Step 1 — Pre-flight (mandatory before any action)
git rev-parse --is-inside-work-tree— confirm git repo.git rev-parse --abbrev-ref HEAD— get current branch.- Characterize the current branch — without classifying the mode or stopping: that belongs to Step 3, which already knows the destination. Simply note which of the three categories it falls into:
- implementation (prefix
feature/,fix/,chore/,refactor/,test/,hotfix/, or the repo's equivalent), - integration or deployment (
develop,release/*,main,master,trunk, or whatever the repo uses), - neither of the two (loose branch such as
hotfix-cacheorPROJ-1234) → it will be resolved by asking the user in Step 3, not by stopping here.
- implementation (prefix
git status --porcelain— if it is not empty, note what is pending and continue without committing. The gates of Step 4 verify commit + working tree (quality-checkfingerprints both;code-reviewchecks the diff against the base including what is uncommitted), so committing here and again after the gates duplicated the invocation ofgit-commitwithout adding any guarantee. The only commit in the flow is made in Step 5, before the push.
Step 2 — Detect platform and CLI
Apply the detection table. (The "PR already exists" check needs the destination, so it is done at the end of Step 3, not here.)
Step 3 — Ask for the destination and close the mode
- Destination branch (single question): validate that it exists in
origin(git ls-remote --heads origin <destino>) and that it does not match the current branch. - Verify that there is something to integrate:
git rev-list --count origin/<destino>..HEAD. If it is0, stop and warn — the PR would come out empty. Applies to both modes. - Extract the jobs from the range (see Step 6 for the degradation order). It is needed here, not only in Step 6: the confirmation message in point 5 lists them.
- Classify the mode by applying the decision table from Modes: implementation and promotion to the source→destination pair. If the current branch did not fit any category (row 5), ask the user now which one it belongs to.
- If the result is promotion, confirm the intention before continuing: «You are going to create a promotion PR from
<origen>to<destino>: N commits, jobs X, Y, Z. Is this what you want, or did you forget to switch to your work branch?». Without confirmation it does not continue. - PR already existing: with source and destination resolved, check whether there is an open PR for
<rama-actual> → <destino>; if there is, capture its URL and return it to the user without creating a new one.
The gates that apply to the mode are not asked about: they are mandatory (see Step 4) and there is no option to skip them. That in a promotion code-review and coverage-verify not do not run is an exception granted to the user: it is that their unit of analysis does not exist in that mode.
Step 4 — Quality gates (mandatory, blocking)
Before any push or PR creation, the gates that apply to the modeare run, in this order. A gate that applies and does not end up in approved stops the flow: no push is made nor is the PR created. See Handling failures in the gates for what to do in the event of a failure.
| Gate | Implementation PR | Promotion PR |
|---|---|---|
4.1 quality-check |
Mandatory | Mandatory |
4.2 code-review |
Mandatory | Does not apply |
4.3 coverage-verify |
Mandatory | Does not apply |
| 4.4 Definition of Done | If the file exists | If the file exists |
4.1 — quality-check (always). Invoke the flow of quality-check (automated verifications: typing, linter, architecture validations, unit, coverage, build, e2e, sonar, plus the suites declared by the testing standard) on the branch.
- Approved =
verdict=APPROVEDin the footer mark → continue (even if there are warnings or informational results). - Rejected =
verdict=REJECTEDorverdict=INCOMPLETE→ stop.
How a verdict is read. The gate reports are written in the resolved language of the repo, so neither the word nor the symbol in the header are comparable. What is read is the hidden footer mark of the report:
<!-- <skill>:verdict=<VALOR> … -->.APPROVEDlets it pass;REJECTEDandINCOMPLETEblock;APPROVED_WITH_NOTES(onlycoverage-verify) not blocks: the observations are shown and it continues. Full contract in${PLUGIN_ROOT}/references/verdicts.md.
This is the closing point where
quality-checkruns the full battery and persistsquality-check-run.json. Order matters:4.1before4.3allowscoverage-verifyto reuse that run without re-executing the tests. The same cache keeps fresh the entryarchitecture, whicharch-auditreuses if it is audited later without touching the code.
4.2 — code-review (only in implementation PR). Invoke the code-review flow (qualitative review: intent, architecture and design) with base origin/<destino>, its default scope (everything the branch differs from that base, including the corrections that 4.1 may have left uncommitted). It issues a verdict of its own and independent from that of 4.1; neither replaces the other. If the existing docs/audits/code-review.md was already fresh and approved (same fingerprint, same base and same mode, and 4.1 applied no corrections), it returns it without reviewing again — do not force revalidate from here. A previous report in ❌/⚠️ is never served from cache: code-review reviews it again on its own.
- Approved =
verdict=APPROVEDin the footer mark → continue. - Rejected =
verdict=REJECTEDorverdict=INCOMPLETE→ stop.
4.3 — coverage-verify (only in implementation PR). Resolve the work to validate (US-XXX or WI-XXX) from the branch pattern, the commit prefix, or the work path. coverage-verify traces the acceptance criteria AC-XXX of the work (same format in US and WI). If the work cannot be determined, ask the user which one to validate; if they do not provide it, the gate cannot be approved → stop. Invoke coverage-verify on that work. Reuse the quality-check-run.json produced by 4.1 (same branch, no changes) and, if the criteria-coverage.md was already fresh, it returns it without regenerating it.
- Approved =
verdict=APPROVEDin the footer mark → continue. The⚠️of this gate isAPPROVED_WITH_NOTESand also is considered approved, but the observations are shown to the user before continuing. - Rejected =
verdict=REJECTED→ stop.
4.4 — Definition of Done (only if the file exists). Check whether docs/policies/definition-of-done.md exists at the repo root (test -f docs/policies/definition-of-done.md).
No plugin skill generates that file: it is written and maintained by the team. It is deliberate —a Definition of Done is a team agreement, not a derivable artifact— and that is why the gate is conditional: in a repo that does not have one, it simply does not apply. If the user asks how to have one, tell them it is enough to create that file with a checklist of verifiable closure conditions; do not offer to generate it for them.
- If it does not exist → skip this gate (it does not affect the result).
- If it exists → read it and verify the code/change against each policy/item of that Definition of Done, over the range
origin/<destino>against the current state of the tree, so that it includes the corrections that the previous gates may have left uncommitted (the same scope as4.2in an implementation PR; in a promotion, where4.2does not run, the range is still that one). Expected format ofdocs/policies/definition-of-done.md: a policy document with verifiable items/checklist (each item a concrete closure condition). The skill only automatically evaluates the items checkable from the repo or the diff; for the rest, it asks.- Items checkable from the repo/diff → evaluate them directly: met / not met.
- Items not automatically checkable → present them to the user and ask whether they are met (do not invent their fulfillment). If the user confirms that they are met → they count as met. If they do not confirm them or marks them as not met → they count as not met.
- Approved = all applicable items are met (the checkable ones verified + the non-checkable ones confirmed by the user) → continue.
- Rejected = at least one item not met, or some non-checkable item that the user does not confirm → the gate is not approved → stop, listing which DoD item(s) are not met or remain unconfirmed.
Only if all applicable gates remain approved does it move on to Step 5 (push).
Gates in a promotion PR
A promotion does not introduce new code: each piece of work that travels in it already passed the three gates when it was integrated into the integration branch. Repeating them here discovers nothing and is expensive. What does remain to be demonstrated —and nobody verified feature by feature— is that the consolidated branch is green: that is exactly quality-check.
| Gate | Why it does not apply |
|---|---|
code-review |
Its unit is an unreviewed diff. In a promotion, the entire diff origin/<destino>..HEAD was already reviewed and approved PR by PR; passing it again would mean reviewing ten already-closed diffs and would produce findings about code that was already justified at the time. |
coverage-verify |
It validates a single artifact against its acceptance criteria. A promotion covers several pieces of work, so there is no single artifact to validate; and each one already brings its criteria-coverage.md approved. |
Rules when reporting:
- In the summary to the user and in the PR description, those two gates are listed as
N/A(—) with the reason "Promotion PR". They are not silently omitted or marked as approved: whoever reads the PR must see that they did not run and why. - The Definition of Done does apply, if the file exists: its items are usually deployment conditions (changelog, version, reviewed migrations) that this is precisely where they should be checked. Its scope is the same range
origin/<destino>..HEAD. - If the user expressly requests an additional review,
code-revieworcoverage-verifycan be invoked manually; it is not part of the flow nor does it condition the creation of the PR.
Archived: outside this skill
This skill does not archive the work folder nor does it offer to: there is always a human review between the PR and archiving, and that moment is decided by the team. When they want to do it, the user asks the skill that produced the artifact — /work-define US-XXX archive or /work-plan WI-XXX archive —, which shows the real state of the work and asks for confirmation (see ${PLUGIN_ROOT}/references/archive.md). If the work folder is already under <archivedPath>, it is read from there (Rule 1 of the contract) and reported; it is not an error.
Step 5 — Push of the current branch
Before the push, commit everything pending — the only invocation of git-commit in the flow. The tree contains the work that was pending in the pre-flight, the corrections that the gates of Step 4 have left (applied by quality-check or delegated to work-implement), their versioned reports, and the archiving rename that this same step leaves staged if the user confirmed it. Run git status --porcelain and, if there is output, automatically invoke the flow of the skill git-commit (without asking the user whether they want to commit): delegate to it all its operational criteria (grouping by logical change, inference of type/scope/message, staging, confirmation of the split proposal) — pr-create it does not decide a message or what to stage on its own. The code that is pushed must be exactly the one the gates verified; archiving is the only exception, and it is deliberate: it moves documentation under docs/specs/, it does not touch code or test sources, so it does not invalidate the verdicts of quality-check or code-review. It does shift the SPEC_FINGERPRINT of coverage-verify, whose criteria-coverage.md will be regenerated once in the next validation.
- If
git-commitis not available (skill not installed or not locatable in the environment): stop and warn, showing the pending files and suggesting the user commit manually before retrying — do not rungit add/git commitdirectly as a substitute. - If
git-commitleaves the working tree partially clean due to a scope decision of its own (e.g. it grouped and committed some files but deliberately left others out, or the user excluded some from a proposed commit): it is not an error ofpr-create. Re-checkgit status --porcelain; if there are still changes, invokegit-commitagain on the remainder (same criterion, without asking) until it is clean orgit-commitstops for a real reason. - If it stops without committing (e.g. because it requires a user decision that
git-commititself cannot resolve alone), stop and notify with the reason reported bygit-commit.
In promotion mode, delete before docs/audits/quality-check.md from the tree and, if develop had it tracked, remove it from the index — see the following note. Only then re-check the state and invoke git-commit.
.sdd-devkit/quality-check-run.jsonis never committed, in either of the two modes: it is in the.gitignorebecause it is a local and disposable cache, and a test result produced on another machine is not evidence here. Nothing that follows shifts the freshness fingerprint:.sdd-devkit/falls under the exclusion of hidden folders anddocs/under its own.In an implementation PR, the reports travel in the PR. The gates write
docs/audits/quality-check.md,docs/audits/code-review.mdand thecriteria-coverage.mdof the work; that commit includes them on purpose, so that the reviewer sees the three verdicts alongside the change. But the two fromdocs/audits/are snapshots of this branch and must not remain in the target one: their header carries the branch and the commit on which the gates were run, indevelopthey would assert a verdict that no one executed there, and since they live in a fixed path, every branch that is integrated would overwrite them.work-integrateremoves them within the merge itself, but here the merge is done by the platform and this skill does not control it. Hence two things:
- State it in the PR body. The description composed by Step 6 closes with this line: «
docs/audits/quality-check.mdanddocs/audits/code-review.mdare artifacts of this branch — delete them when integrating.»- When reporting to the user, remember that after the merge on the platform it is advisable to delete them in the target branch (
git rm docs/audits/quality-check.md docs/audits/code-review.md), or integrate withwork-integrate, which already does it on its own. Only those two: thearch-audit-*.md, the copies ofsave-reportand thecriteria-coverage.mdof the work do belong to the base branch.In a promotion PR, the report does not reach disk. Here the source branch is already an integration branch: committing
docs/audits/quality-check.mdwould leave it planted indevelopand from there it would travel tomasterwith the promotion — the previous problem, but with no one who can clean it up afterward. The handling, in the exact order in which it occurs:
- After reading the verdict of
4.1, delete the report from the working tree withrm -f docs/audits/quality-check.md(rm, nogit rm: in most repos it isn't even tracked).- If
developwas already tracked —the usual case if implementation PRs that did commit it were previously merged—, also remove it from the index:git rm -q -f --ignore-unmatch ':(top,glob)**/docs/audits/quality-check.md' ':(top,glob)**/docs/audits/code-review.md'. Paths are anchored to the root (:(top)) and with**/: in a monorepoquality-checkaudits the chosen module and writes topackages/<mod>/docs/audits/, which a literal pathspec wouldn't reach. That deletion is committed: it cleans the integration branch of reports that should never have gotten there.- The verdict and the summary go in the PR description, which is where the reviewer of a promotion needs them and which dies with the PR.
Why delete and not "leave it uncommitted". This skill cannot exclude a file from the commit: it delegates to
git-commit, which cannot be forced a scope from outside (its own scope is decided by it), and the flow itself mandates reinvoking it until the tree is clean — the leftover would be exactly that report, so it either loops or commits what was meant to be avoided. Deleting it leaves the tree clean, which is the precondition assumed by both this flow's push and any subsequent branch change — a modified uncommitted file would make agit checkout.If the user wants an on-disk record of that run,
save-reportleaves a timestamped copy that they can commit by hand.
If the branch doesn't exist in origin or has unpublished commits (git rev-list origin/<rama>..HEAD not empty): run git push -u origin <rama-actual>. Never --force or --force-with-lease. If the push fails due to divergence: stop and warn — the user decides how to resolve it.
In promotion mode, the push is to a protected branch: confirm it. The current branch is
develop, which after one or morework-integrateaccumulates local merges that nobody has published — andwork-integrateexplicitly leaves that push as the user's decision, outside its scope. Before pushing, list the commits that will be published and ask for confirmation. It is the only operation in the entire flow that writes to a protected branch on the remote; in implementation mode it doesn't apply, because there the working branch is pushed.
Step 6 — Generate title and description
Without asking for confirmation (unless explicitly overridden by the user):
In an implementation PR:
- Title: a single commit in the range → its subject (
git log -1 --pretty=%s). Multiple commits → subject of the oldest one. If the branch follows the pattern<prefix>/<TICKET>-<desc>orUS-XXX-..., prepend[<TICKET>]. Translate into the resolved language keeping the ticket prefix intact. - Description: list of commits (
git log origin/<destino>..HEAD --pretty="- %s"), summary of changes (git diff --stat origin/<destino>..HEAD) and reference to the issue/ticket if the branch name contains it (patternUS-XXX,TK-XXX,JIRA-XXX,#NNN).
In a promotion PR, the range is merge commits from several work items and a flat list of subjects says nothing useful:
-
How work items are extracted (also used by the Step 3 confirmation). Try in this order and keep the first one that yields a result:
- Merge commits:
git log origin/<destino>..HEAD --merges --pretty="- %s", searching forUS-XXX/WI-XXX. - Identifiers in the subjects of all the commits in the range — necessary when the platform integrated with squash merge, which leaves no merge commits.
- Branch names present in the range.
If none of them yields anything, do not invent: the title goes without a list and the Step 3 confirmation is phrased by delta ("N commits") instead of enumerating work items.
- Merge commits:
-
Title:
Promoción <origen> → <destino>, plus the identifiers if they were obtained (e.g.Promoción develop → master (US-042, US-047, WI-007)) or(N commits)if not. No ticket prefix: there is not a single one. -
Description: the work items being promoted, the delta (
git rev-list --count origin/<destino>..HEADcommits) and the change summary (git diff --stat origin/<destino>..HEAD). If any commit in the range does not map to any work item, list it separately as "loose commits": that is information a promotion reviewer wants to see. -
Gate verdicts: the one for
quality-checkwith its summary —here goes the content, not a link: the report is not committed in this mode— and the other two asN/A(—) with the reason "Promotion PR", with the reason on one line.
Implementation only, if the gates commit included reports in docs/audits/, add as the last line: "docs/audits/quality-check.md and docs/audits/code-review.md are artifacts of this branch — delete them when integrating." See the note in Step 5.
Step 7 — Create PR/MR
| Platform | Command |
|---|---|
| GitHub | gh pr create --base <destino> --head <rama> --title "<título>" --body "<desc>" |
| GitLab | glab mr create --target-branch <destino> --source-branch <rama> --title "<título>" --description "<desc>" --yes |
| Bitbucket Cloud | POST https://api.bitbucket.org/2.0/repositories/<workspace>/<repo>/pullrequests with JSON payload |
| Bitbucket Server | POST /rest/api/1.0/projects/<key>/repos/<slug>/pull-requests with equivalent payload |
| Azure Repos | az repos pr create --source-branch <rama> --target-branch <destino> --title "<título>" --description "<desc>" |
| Gitea/Forgejo | tea pr create --base <destino> --head <rama> --title "<título>" --description "<desc>" |
If the CLI indicates that a PR already exists: capture and return the existing URL.
Step 8 — Report
✓ PR creado en <plataforma> Origen: <rama-actual> Destino: <rama-destino> Título: <título-generado> URL: <url>
In an implementation PR, add below a line reminding that the artifact is still in its active path and that, after the PR review, it can be archived with /work-define US-XXX archive or /work-plan WI-XXX archive. In a promotion it does not appear.
Blocked by a quality gate:
✗ PR NO creado: la puerta <quality-check | code-review | coverage-verify | definition-of-done> no quedó enAPPROVED. (En un PR de promoción solo pueden aparecer aquí quality-check y definition-of-done.) Veredicto: <REJECTED(quality-check) |INCOMPLETE(quality-check) |REJECTED(code-review) |INCOMPLETE(code-review) |REJECTED` (coverage-verify) | DoD not met>
<literal report of the skill, or list of unmet DoD items>
Actions to retry: ` If the fix is within this skill's scope, offer to apply it before requesting manual action (see Handling failures at the gates).
Handling failures at the quality gates
When one of the Step 4 gates is not approved, stop the flow (no push and no PR) and, in this order:
- Inform the user which gate failed, with its verdict/reason and the skill's literal report (or the list of unmet DoD items).
- State the specific actions they must take to get the gate to approved and be able to retry creating the PR (e.g. "fix the failing tests in
X", "cover criterionAC-003with a test", "satisfy the \"changelog updated\" item of the DoD"). - If the fix is within this skill's scope, do not apply it automatically: ask the user whether they want it applied. Only with their explicit authorization, apply the minimal fix and retry the gate that failed; if that gate is approved again, continue with the rest of the flow (re-running the corresponding subsequent gates). If the user does not authorize it, finish by leaving the stated actions.
Notes:
- Fixes within
quality-check,code-reviewandcoverage-verifyare governed by each skill's own flow (which also requires user authorization). Do not re-implement that logic here. - After any authorized fix, re-run the affected gate before moving on; do not assume it was approved.
Examples
Example 1 — Happy path (GitLab self-managed)
User: "Create the PR for this branch."
Skill: pre-flight OK (branch feature/US-042-auth-refresh-token). Detects GitLab (ns.bayteq.com:3311). Asks for destination → develop. Gates: quality-check → APPROVED; code-review with base origin/develop → APPROVED; resolves US-042, coverage-verify → APPROVED; docs/policies/definition-of-done.md exists → all items satisfied. the user confirms the archiving and the single invocation of git-commit in the flow collects the renaming along with the gate reports. Push. Auto-generates title [US-042] feat(auth): refresh token con expiración 15min. Runs glab mr create. Returns URL.
Example 2 — quality-check blocks
quality-check returns REJECTED (failing tests + eslint errors). The skill does not create the PR, does not push, shows the report, lists the actions to retry and —since it is within its scope— asks whether to apply the fix. If the user does not authorize it, it finishes.
Example 3 — coverage-verify blocks
quality-check and code-review → APPROVED, but coverage-verify of US-042 returns REJECTED (criterion AC-003 without a test). The skill does not create the PR; it reports that AC-003 is missing coverage and asks whether to attempt the fix (delegating to the corresponding flow). Without authorization, it finishes with the stated actions.
Example 4 — Definition of Done unmet
The first three gates approved, but docs/policies/definition-of-done.md requires "CHANGELOG.md updated" and the diff does not touch it. The skill stops creation, lists that item as unmet and indicates the action; if the user authorizes it and the fix is within its reach, it applies it and retries the gate.
Example 5 — No Definition of Done
There is no docs/policies/definition-of-done.md. That gate is skipped; the PR is created if the mode's gates ended up approved — all three in implementation, only quality-check in promotion.
Example 6 — Azure Repos
origin points to https://dev.azure.com/<org>/<proyecto>/_git/<repo>. Detects Azure Repos, checks az repos, asks for the destination, runs the gates, push, creates the PR with az repos pr create.
Example 7 — Promotion PR
User in develop: "create a PR to master." Step 1 does not block: develop is an integration branch, so the mode stays open. Step 3 sees that the destination is a deployment branch and confirms: "You are about to create a promotion PR from develop to master: 23 commits, work US-042, US-047 and WI-007. Is that what you want, or did you forget to switch to your work branch?". Once confirmed, it runs quality-check (+ DoD if it exists), marks code-review and coverage-verify as N/A (—) with the reason "promotion PR", and creates the PR titled Promoción develop → master (US-042, US-047, WI-007).
Example 7b — Backward promotion
User in master: "create a PR to develop." Row 3 of the decision table: develop is upstream of master in the cycle order, so it is not a promotion. Stop: "Bringing master to develop is syncing, not promoting: do it with a merge — not with this skill."
Example 7c — Branch with no recognized prefix or role
User in hotfix-cache (it does not follow any recognized prefix and is not an integration branch): "create a PR to develop." Row 5: ask which category it belongs to. If the user answers that it is a work branch, it is treated as an implementation PR (row 1); if they do not clarify, stop by stating the expected convention. Not classified as a promotion by elimination.
Example 7d — Forgetting to switch branches
User has just run work-integrate (which leaves HEAD at develop) and asks "create the PR for my feature." Step 3 asks for the destination and detects the pair develop → develop: stop and warn that the work is already integrated locally and that, if they want the feature PR, they must return to their branch; if they want to promote develop, indicate a deployment branch as the destination.
Example 8 — Dirty working tree
git status --porcelain returns two modified uncommitted files. The skill notes them and continues the pre-flight uncommitted; the gates check them along with what is already committed and, before the push, it automatically invokes the flow of git-commit on everything pending (without asking whether it should be invoked) — git-commit would only pause if it proposed splitting into several commits; a single commit it executes without confirming.
Example 9 — PR already exists
The branch already has an open PR/MR toward develop. Return the existing URL with the note "A PR already exists for this combination". Do not create a new one.
Anti-patterns
- Narrating the internal flow: announcing that the language or policy is being resolved, that
settings.jsonis being read, that a reference is being loaded, or enumerating the steps out loud. The user is told the result, the questions the flow requires, and what remains pending — not the machinery. - Asking for the source branch (it is always the current one) or assuming the target.
- Asking for the platform (it is detected from the remote).
- Asking whether to run a gate that applies to the mode, or offering to skip it: the ones that apply are mandatory.
- Treating every protected branch as a pre-flight error. Being on
developwith targetmasteris a legitimate promotion, not an oversight; what resolves the ambiguity is the confirmation in Step 3, not a block. - Classifying the mode in Step 1, before knowing the target: the mode depends on the pair source→target, and deciding it halfway produces rules that contradict each other.
- Using "the branch the source was born from" to detect a backward promotion: in git-flow
developis born frommaster, so that criterion would classifydevelop → masteras a rollback and disable the mode. The direction is set by the downstream order. - Classifying a branch that does not fit anywhere as a promotion (
hotfix-cache,PROJ-1234) by elimination, instead of asking (row 5). - Conversely: assuming it is a promotion without confirming it. The same state occurs when someone forgot to switch branches —typically right after
work-integrate, which leaves HEAD on the base—, and there the correct PR is a different one. - Marking
code-revieworcoverage-verifyas approved in a promotion, or silently omitting them: they are reported asN/A(—) with the reason "Promotion PR", with the reason visible in the PR. - Skipping
code-revieworcoverage-verifyin a PR of implementation on the grounds that "it was already reviewed": there they do apply, without exception. - Considering a gate met based on the verdict of another (e.g. assuming
code-reviewapproved becausequality-checkis): they are independent skills with their own verdicts. - Asking for confirmation of title or description (non-interactive flow).
- Creating the PR with
quality-checkorcode-reviewinREJECTED/INCOMPLETE, withcoverage-verifyinREJECTED, or with the Definition of Done unmet. - In an implementation PR, skipping
coverage-verifybecause the work (US/WI) cannot be found instead of asking the user — or declaring it a "promotion" to dodge the gate. - Archiving or offering to archive the artifact from this skill: archiving is not part of the PR; the user requests it from the skill that produced the artifact.
- Commit
docs/audits/quality-check.mdin a promotion PR: the source is already an integration branch and that report would end up in the deployment branch with nobody to clean it up. It is deleted from the tree before the commit; if the branch already had it tracked, it is removed from the index and that deletion is indeed committed. - Trying to "exclude a file" from the commit by delegating to
git-commit: its scope is decided by it, not imposed from outside. Either it is deleted beforehand, or it goes in. - Push
developtooriginin promotion mode without confirming it: these are local merges that the user had not yet published. - Assuming that the range brings merge commits with
US-XXX: with squash merge there are none. Fall back to the subjects and branch names, and if nothing comes up, do not invent the list. - Treating the absence of
docs/policies/definition-of-done.mdas a failure: if it does not exist, that gate is simply skipped. - Inventing the fulfillment of a DoD item that cannot be determined from the repo or the diff.
- Applying a correction without explicit authorization from the user, or not re-running the gate after correcting.
- Running
git add/git commitdirectly (outside the flow ofgit-commit), stopping to ask the user whether they want to commit the pending changes, or invokinggit-commitin the pre-flight and again before the push: when faced with a dirty working tree, the flow ofgit-commitis automatically invoked a single time, before the push (even thoughgit-commitmay in turn pause to confirm a split proposal, or stop before a protected branch or a failed hook), withoutpr-createrequesting prior permission to invoke it. - Creating the PR from a branch that is neither an implementation branch (recognized prefix) nor an integration/deployment branch.
- Using
git push --forceor--force-with-lease. - Assigning reviewers, labels or milestones on one's own initiative.
- Re-implementing the logic of
quality-check,code-revieworcoverage-verifyinstead of invoking the existing flow. - Creating a second PR when one already exists for
<rama-actual> → <destino>.