Pre merge
End-to-end engineering harness for Claude Code — go from planning to building to reviewing in one workflow. 8 agents with multiple modes. In-built GUI to visualise your PRDs and todos. Ship with AI confidently. MIT.
npx -y skills add ndisisnd/msg --skill pre-mergeAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
The CI gate. Takes a feature branch from "eng says done" to "PR open against staging with green checks and a human-approved preview". Runs the project's preflight-resolved pipeline from devkit/policy.json components[]: sync → parallel correctness + security waves → coverage → regression tail → security/migration → PRD-consistency → preview deploy (human gate) → open PR. Emits a severity-graded verdict JSON. Absorbs the old /review and /test. Activates on /pre-merge after eng --build.
SKILL.md
18.5 KB, as published. Nobody here has run it
pre-merge
The CI gate. Runs after eng --build says a feature branch is done, and takes
it to a PR open against staging with green checks and a human-approved preview.
Absorbs the retired /review and /test. Each run is independent.
eng --build → /pre-merge → (fail → eng --build report=…, repeat) → PR feature→staging → post-merge --staging
Usage
/pre-merge— gate the current feature branch againststaging/pre-merge --init— run the one-time setup: detect tooling (incl. the.github/workflows/CI pipeline that runs the gate on PRs, unlesspolicies.github_actions.enabledisfalse— then the missing workflow is a settled opt-out, not a gap, and no scaffold is offered) → interview → gated install/scaffold → writedevkit/policy.json(no gate run); seerefs/protocol-init.md/pre-merge --doctor— deprecated alias for one release: runs--initand prints a deprecation note naming--init/--update
/pre-merge --update— reconcile the manifest with codebase reality (re-run preflight checks → diffcomponents[]→ approve the delta → applypresent/active_when/new-component changes only; never re-grades user-set criticality or re-prompts settled opt-outs); seerefs/protocol-init.md/pre-merge --prd <path>— load a PRD; enables theprd-group components (prd-consistency,manual-test-plan) and feeds theregressioncomponent (repeatable)/pre-merge --prior-issues <path>— load a prior verdict JSON to mark regressions/pre-merge --full-secret-scan— thesecuritycomponent scans the full tree (default: diff-only)/pre-merge --flaky <N>— retry failing e2e / unit-int tests up toNtimes before counting a hard failure (refs/_common.md)/pre-merge --changed-only— skip platform components whose surface the diff doesn't touch (refs/_common.md)/pre-merge --minified— force test selection on for this run even whenpolicies.test_selectionis off (a trial); nothing is written (refs/executor.md§3c)/pre-merge --full— force the full suites for this run — the kill switch. Flag beats policy:--full>--minified>policies.test_selection/pre-merge --update-criticality— the criticality reconcile: inventory untagged tests → LLM proposals with cited evidence → one human gate → write the approved critical markers as one commit + restampcriticality_review; seerefs/protocol-update-criticality.md
Natural language: "run pre-merge", "gate this before merge", "open the PR against staging", "run the CI gate".
Hard refusals (refs/refusal-patterns.md):
- Does NOT modify source code. Its ONLY direct write is the SYNC (D7)-bounded sync-merge commit; regression tests are written by a spawned eng subagent (the
regressioncomponent), never by pre-merge. - Does NOT
git push,gh pr merge,git mergeintomain, or deploy production. It opens exactly one PR (feature→staging, or feature→mainwhen nostagingbranch exists) and never merges it. - Does NOT run without a non-empty diff against base. A missing
stagingbranch is NOT a blocker — pre-merge falls back tomainas the sync + PR target, no warning, no refusal. - Does NOT grade a finding as blocker without quoted tool evidence.
Inputs / Outputs
| Name | Source / Destination | |
|---|---|---|
| In | base | resolved via release_flow per ../shared/refs/policy-schema.md §1 — staged → staging_branch (falls back to main when the branch is absent), direct → prod_branch; no policy → default staging, else main; diff resolved by scripts/resolve-diff.sh / a fresh verify-prelude |
| In | prd_paths | --prd (repeatable) — feeds Steps 4 + 7 |
| In | prior_issues | --prior-issues JSON, optional |
| Out | verdict_json | single JSON per refs/output-schema.md — final stdout emission |
| Out | run_report | report-prd-<N>-<K>.md per ../shared/refs/report-schema.md (first --prd's reports/, else features/reports/ as report-<K>.md) |
| Out | issues_file | the run report's paired .json (same stem + reports/ folder as run_report) on a non-clean verdict — consumed by eng --build report= |
| Out | run_artifacts | raw stage logs → .pre-merge/<timestamp>/<stage>.log |
| Out | pr | PR feature→staging (Step 9), verdict JSON + report linked in the body |
Schema: refs/output-schema.md · finding shape: refs/finding-schema.md (canonical
../shared/refs/finding-schema.md) · severity: refs/severity-rubric.md.
Persona
Release engineer on a small product team. Owns the gate: what ships, what blocks, what gets logged as accepted risk. Repeatable evidence over assertion; severity matched to reachability. Never modifies source (bar the sync-merge), never merges, never grades a blocker without quoted evidence. Compact and structured — tables over prose, severity counts before the issue list, JSON-first.
Pre-flight — manifest gate (Fork C, BREAKING)
The gate is a preflight-driven executor (refs/executor.md) — it runs the resolved
components[] pipeline from devkit/policy.json, not a fixed step list. Load + validate
the policy once per run (../shared/refs/policy-schema.md read-contract), then gate on
the manifest:
| state | behavior |
|---|---|
components[] present, non-empty | run the executor (refs/executor.md) |
file absent / malformed / version ≠ 1 | REFUSE no_manifest — name /pre-merge --init, run zero components (refs/refusal-patterns.md) |
pre-v3 policy.json (init/release_flow, no components[]) | REFUSE no_manifest + upgrade nudge — name /pre-merge --init |
This is the breaking cutover (Fork C, AC-PF13/PF14): the old "file absent → run on
built-in defaults" fallback is retired (AC-LC6/AC-ST5 retired). There is no
defaults path and no inline auto---init — a run without a components[] manifest does
nothing but tell the user to run /pre-merge --init, which detects the pipeline and
writes the manifest. The old per-step policy self-consult (the retired steps entries)
is superseded by component presence (an absent component simply isn't in the
pipeline). The loaded policy still drives base resolution (below).
Manifest staleness nudge (Fork E, read-only). With a valid manifest, the executor
recomputes source_signature cheaply (the sha256 over the sorted
id:present:run:tooling.chosen lines, per ../shared/refs/policy-schema.md) and, on
mismatch, prints one line — "pipeline may be stale — run /pre-merge --update" — then
proceeds on the current manifest. The gate never writes policy.json or mutates
components[]; only --init/--update do (AC-UP5/UP6).
The pipeline executor (replaces the old fixed gate sequence)
The full algorithm — manifest read → prune → runtime topo-sort → parallel waves →
fail-fast → per-check result reports → aggregate — lives in refs/executor.md;
this file stays the spine. In outline:
- Prelude — diff + base. Resolve base (
staging, elsemain) and the diff: consume a fresh../shared/refs/verify-prelude.mdif present, else runscripts/resolve-diff.sh <base>; empty diff → refuseno_diff(refs/refusal-patterns.md). Best-effort write the prelude. Tooling is already resolved into each component'sruncommand in the manifest (by--init/--updatevia thepreflight-check-*.shfamily) — the gate does not re-detect tooling. - SYNC (D7) — the un-prunable DAG root. Fetch + merge the sync target
(
staging, elsemain); trivial conflicts auto-resolve, semantic same-hunk pause; the sync-merge commit is the sole direct write; nostaging→ fall back tomain(no refusal). Every component implicitly depends on SYNC — the tree is synced before anything runs (refs/sync.md). - Resolve the pipeline from
components[]— includepresent/mandatorycomponents whoseactive_whengate is met; apply--changed-only/--prd/--flakypruning. An absent component produces no step and no note (AC-PF6).security+migrationare always in (Fork D). - Topo-sort + run in waves. Order = topological sort on
depends_on, ties broken bycriticalitythencost(AC-PF7). Independent components in a wave run as parallel subagents; dependents never run concurrently (AC-PF8/9). For universal+prd this is{mechanical·security·unit·prd-consistency}‖ → the env wave{integration·e2e·a11y·perf·load·mobile}inside the C23 test-sandbox (one ephemeral isolated env, provisioned only-on-green after the static waves, promoted to serve as the preview, torn down after —refs/executor.md§3b) →{coverage}→{regression}(C5, AC-SEQ1). Static (needs_env:false) components never enter the sandbox;preview/smokeare the only-on-green tail. Each protocol loads its ref on demand (refs/universal/*,refs/platform/*,refs/prd/*). - Fail-fast by
criticality(refs/severity-rubric.md):criticalaborts the remaining pipeline (mechanical/security/migration short-circuit);blockingfails the verdict, marks downstream dependentsblocked, lets independent branches finish;advisory/config-drivennever aborts (AC-PF11). - Every component writes a result report to
.pre-merge/<ts>/<check>.json— pass, fail, or skip, on every run (C6, AC-RR1) — theresultsection of../shared/refs/check-report-schema.md.unitemits the same shape as every check. - OPEN-PR / issues-loop — the un-prunable terminal. On clean → open the PR; on non-clean → the Issues-file loop (below). The gate never dead-ends.
Test selection (opt-IN, off by default). When policies.test_selection
resolves enabled (--full > --minified > policy), the three selection-capable
components — unit, integration, regression — run run_minified
(affected(diff) ∪ the critical floor) instead of their full suites, at the size
tier computed from the diff's blast radius. The rule, the tier rubric, and the
recording contract live in refs/executor.md §3c; the key's schema in
../shared/refs/policy-schema.md § policies.test_selection. Absent/disabled ⇒
byte-identical to today: no selection artifact is read and none is emitted
(AC-TS1). Every resolution failure fails open to the full suite;
mechanical/security/migration and this PRD's newly authored regression tests
are never selected away (AC-TS4/TS5).
Aggregate + emit (from the per-check result reports)
The per-check result reports (§6) are the executor's single uniform aggregation
input (AC-RR6/UR6) — the verdict and universal report are derived, never
authored separately. Full detail in refs/executor.md; in outline:
- Collect every result report's
findings[]; filter nulls. - Dedup by
(category, file, line, rule)— keep highest severity, concatenatesource(refs/finding-schema.md). - Triage with
refs/severity-rubric.md(in-diff weighting, dev-only / unreachable downgrades, profile coverage floor). - Mark regressions from
--prior-issueson(category, file, rule). - Verdict:
fail(any blocker/high) ·pass_with_warnings(only medium/low) ·pass(zero) ·refused/skipped(early-termination paths). - Run report — write
report-prd-<N>-<K>.mdper../shared/refs/report-schema.md(skill: pre-merge;## Test results= one line per check for pass AND fail, sourced from the result reports'checks[];tests_passed/tests_failedsummed from theirtotals;## How to verifylists the resolved, ordered pipeline + what flags pruned — AC-RR3/PF15; on a minified run each selection-capable check's line also carriesselected/total+ tier, and the paired.jsoncarries thetest_selectionblock verbatim — AC-TS6/TS9). Best-effort; skip onrefused/skipped. - Terminal issue summary — on every report write, all verdicts, print the
Issue summaryblock to the terminal (exact format owned by../shared/refs/report-schema.md); counts derive from the run's canonicalfindings[](category/severity). A clean run prints exactlyIssue summary — 0 issues. - Print the JSON per
refs/output-schema.mdas the final emission — shape unchanged (AC-PF16); the optional additivepipelinefield carries the resolved ordered pipeline for observability, and — only when selection ran — the additivetest_selectionblock (AC-TS6). - Closing message — end the run (every verdict, including
refused/skipped) with the closing message per../shared/refs/closing-message.mdas the last chat output; the step-8 JSON stays the final machine emission, byte-identical.
Issues-file loop (non-clean verdict)
On fail, write the issues file — the run report's paired .json (same stem,
same reports/ folder, sharing its N and K) — the universal report (C7). It
carries the same canonical-finding issues[] + context + summary + followUp
the prior verdict artifact carried, now plus an additive checks[] block (the
per-check run picture, sourced from the result reports — AC-UR2). The
followUp.status contract is kept — camelCase, the key eng --build writes
back and the --gui board reads (AC-UR4). checks[] is additive to the existing
shape, not a rename (AC-PF16). It is consumed by
eng --build report=<that .json path>, which fixes issues[] using checks[] for
context and the branch comes back through the gate. followUp.suggested_command =
eng --build report=<that .json path> — kept as the deep-link fallback
fix-loop.md resumes from if the user declines.
Once the issues file and the run report are written, hand off to
../shared/refs/fix-loop.md — it runs Offer #1 (plan the fixes with eng --plan)
→ Offer #2 (orchestrated eng --build) off this same issues file. Do not
re-spell the offer wording here; fix-loop.md owns it. The gate does not dead-end on
the issues file — the loop walks the user from "issues found" to "fixes planned + built".
OPEN-PR — the terminal (clean verdict only)
On pass / pass_with_warnings and an approved preview (when the gate fired):
gh pr create --base <target> --head <feature-branch> (where <target> is the
SYNC target — staging, else main) with the verdict JSON + report
path linked in the body. Record pr_url. Never gh pr merge — post-merge
--staging merges it on green CI (Part C). On a non-clean verdict, skip OPEN-PR —
no PR opens; the Issues-file loop above runs instead (issues file → fix-loop),
so the gate never dead-ends.
References
refs/executor.md— the pipeline executor (C1/C5/C6/C7): manifest read → prune → topo-sort → parallel waves → fail-fast → per-check result reports → aggregate. The spine points here for the full algorithmrefs/platform-profiles.md— profile → per-componentcriticalityoverride layer fromdevkit/PLATFORMS.mdrefs/sync.md— SYNC (D7, the DAG root) sync-merge + conflict handlingrefs/universal/protocol-mechanical.md—mechanicallint/format/typecheck/comment/commit-cap (scripts, no LLM; critical, short-circuits)refs/universal/protocol-unit.md,refs/universal/protocol-integration.md—unit+integrationsuites (Wave 1)refs/universal/protocol-regression.md—regressionaccumulated suite + spawned eng-subagent authoring (D9/D5; tail-pinned)refs/universal/protocol-coverage.md—coverage(depends_on unit,integration; Wave 2)refs/_common.md+refs/platform/*.md— platform components +--flaky/--changed-onlyrefs/universal/protocol-security.md,refs/platform/protocol-migration.md— the mandatory safety-floor componentsrefs/prd/protocol-prd-consistency.md—prd-group spec-match pass (Wave 1,active_when --prd)refs/platform/protocol-preview.md—previewdeploy + human gate (D6/D10; only-on-green tail)refs/protocol-init.md—--init/--updatemode: detect → interview → gated install → assemblecomponents[]→ writedevkit/policy.json; also the test-selection enabling interview + its single-run disable;--doctoris a deprecated one-release alias for--init(see Usage)refs/protocol-update-criticality.md—--update-criticalitymode: inventory → evidence-cited proposals → human gate → tag commit +criticality_reviewrestamp; also the gate's read-only staleness nudge../shared/refs/policy-schema.md—devkit/policy.jsonschema + read-contract (components[]manifest, baserelease_flow,source_signature,policies.test_selection§2c + thecriticality_reviewstamp)../shared/refs/component-catalog.md— component metadata (schema, defaults,depends_onedges, grouping) the manifest + executor key offrefs/output-schema.md— final emission schema (shape unchanged, AC-PF16) ·refs/finding-schema.md— per-finding shaperefs/severity-rubric.md— grading + criticality fail-fast rules ·refs/refusal-patterns.md— refusal shapes (incl.no_manifest)../shared/refs/finding-schema.md,../shared/refs/report-schema.md,../shared/refs/verify-prelude.md../shared/refs/fix-loop.md— post-failure Offer #1 → Offer #2 sequence the issues-file loop hands off to../shared/refs/check-report-schema.md— the normalized check-report schema (detect+resultsections); the executor writes theresultsection per check and aggregates them.claude/scripts/preflight-check-*.sh— the per-check detect+normalize family (C4);--init/--updaterun + ingest them intocomponents[](refs/protocol-init.md). These + the manifest are the detector now — the monolithic pre-merge tooling detector is retired (v3 P3).claude/scripts/pre-merge-aggregate-verdict.sh— per-component verdict aggregation/merge helperscripts/resolve-diff.sh— diff-vs-base structured summary