loopdive/js2/.claude/skills/dev-self-merge/SKILL.md
dev-self-merge
Merge self-check for a green PR. Reads the PR's required-check status from the checks API (the committed ci-status feed is RETIRED), outputs MERGE (mark task completed, stand down — server-side auto-enqueue enqueues,
- Source repository stars
- 59
- Declared platforms
- 0
- Static risk flags
- 1
- Last source update
- 2026-08-28
- Source checked
- 2026-08-28
Decision brief
What it does: where it fits
Devs DO NOT enqueue. On a passing self-check, mark the task completed and stand down — the server-side auto-enqueue.yml workflow enqueues (2786). This skill's outcomes are MERGE (regression self-check passes → mark the task completed and stand down; you do NOT touch the merge qu…
Not for
- Tasks that require unconfirmed production actions or broad system permissions.
- Environments where the pinned source and install steps cannot be inspected.
Compatibility matrix
Platform support, with evidence labels
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
Inspect first. Install second.
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/loopdive/js2 --skill ".claude/skills/dev-self-merge"Inspect the Agent Skill "dev-self-merge" from https://github.com/loopdive/js2/blob/f727d529abb40cdb63803a802b1502f91e4e9016/.claude/skills/dev-self-merge/SKILL.md at commit f727d529abb40cdb63803a802b1502f91e4e9016. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
What the source asks the agent to do
- 01
Step 0 — the merge gate (checks API; the committed CI feed is RETIRED)
The per-PR CI feed .claude/ci-status/pr-.json is RETIRED. The writer workflows (ci-status-feed.yml, ci-status-basic.yml, ci-status-pending.yml) are workflowdispatch-only stubs; the newest feed file on main is from the PR-471 era. A current PR will NEVER get one — do not fetch it…
pending non-empty → CI still running. Keep the background watcher on it.failed non-empty → diagnose with full PR context (you KNOW what youAll required checks green (per docs/ci-policy.md §7) + mergeStateStatus == - 02
Legacy Step 1 — read the feed
If test262skipped: true in the JSON, this was a test-only / docs-only PR (no src/ changes). Skip Steps 3–4 entirely:
conclusion == "success" → MERGE (go to Step 5, stand down — workflow enqueues)conclusion != "success" → ESCALATE — basic CI failed on a non-src PR.If test262skipped: true in the JSON, this was a test-only / docs-only PR (no src/ changes). Skip Steps 3–4 entirely: - 03
Legacy Step 1a — baseline staleness short-circuit (1391)
If baselinestale: true is set on the feed, the regression count is contaminated by drift on main (tests that flipped between when the baseline was last refreshed and the PR's CI run). Continuing through the criteria below would falsely block PRs whose actual same-run-main diff i…
If baselinestale: true is set on the feed, the regression count is contaminated by drift on main (tests that flipped between when the baseline was last refreshed and the PR's CI run). Continuing through the criteria bel…Output (when triggered):ESCALATE — baseline is stale (N commits behind main HEAD). The CI feed's regression counts are inflated by drift, not by this PR. Tech lead should sanity-check by diffing branch-merged vs main-merged artifacts from the… - 04
Legacy Step 1b — compiletimeout flake filter
A pass → compiletimeout transition is runner-load noise unless the underlying compilation takes meaningfully long. Verified during the 2026-05-21 post-wave investigation: 23 of 27 "regressions" turned out to be timeouts on tests that compile in <500ms locally. See plan/issues/sp…
A pass → compiletimeout transition is runner-load noise unless the underlying compilation takes meaningfully long. Verified during the 2026-05-21 post-wave investigation: 23 of 27 "regressions" turned out to be timeouts…If regressionswasmchange is null (older CI feed) or if the JSON has a breakdown by transition kind, the dev should subtract pass → compiletimeout transitions where baselinecompilems < 5000 from the regression count befo…The cleanest field to use is regressionswasmchange (introduced in 1222) — it already excludes compiletimeout AND byte-identical-binary flips. If the feed has it, prefer it. The filter chain stays: - 05
Legacy Step 2 — SHA check
If headsha in the JSON ≠ git rev-parse HEAD output:
If headsha in the JSON ≠ git rev-parse HEAD output:ESCALATE — SHA mismatch. CI ran on a different commit. Push again and wait for a new CI result.1943 — CI ENFORCES criteria 2 and 3 as a hard gate; the mergegroup re-run owns regression-catching. The regression-gate job (scripts/diff-test262.ts) fails the required check when the 10% ratio or 50-per-bucket limit is…
Permission review
Static risk signals and limitations
Runs scripts
The documentation asks the agent to run terminal commands or scripts.
git fetch originRuns scripts
The documentation asks the agent to run terminal commands or scripts.
git show origin/main:.claude/ci-status/pr-<N>.jsonEvidence record
Why each signal appears
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 91/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 59 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Provenance and original SKILL.md
- Repository
- loopdive/js2
- Skill path
- .claude/skills/dev-self-merge/SKILL.md
- Commit
- f727d529abb40cdb63803a802b1502f91e4e9016
- License
- Apache-2.0
- Collected
- 2026-08-28
- Default branch
- main
View the original SKILL.md
/dev-self-merge <N>
Devs DO NOT enqueue. On a passing self-check, mark the task completed and stand down — the server-side
auto-enqueue.ymlworkflow enqueues (#2786). This skill's outcomes are MERGE (regression self-check passes → mark the task completed and stand down; you do NOT touch the merge queue) or ESCALATE (to tech lead). The PR is enqueued by the server-side workflow, not by you.Why devs no longer enqueue (#2786). The old model had the dev one-shot enqueue when green, with a background CI watcher to do it after stand-down. But that watcher is a child of the dev process — it died with the agent, so a green PR whose dev had stood down stranded un-enqueued (#2225, #2247). The fix moves enqueue to the one actor that is long-lived and outside agent lifecycle: the GitHub Actions workflow. Its
workflow_run-on-completion trigger fires right after the required-check workflows finish, and its grace window is now 0 (#2786), so it enqueues every just-green PR within ~one workflow-startup — no dependence on any agent surviving. The required checks arecheap gate (main-ancestor + lint),merge shard reports, andquality.The merge queue then re-validates on the merged state.
merge_groupre-runs the required checks (the regression-gate #1943 — the hard block), andauto-park(#2547) labels any PR that fails the merge_group re-runhold. The workflow's single trailing-add enqueue never loops, so it cannot cause the re-enqueue "cancellation churn" (memoryproject_merge_queue_requeue_cancels_run) that poll-loop re-adds caused on 2026-06-20.Backstops, not the mechanism: the workflow's ~30-min cron, and the tech lead's per-loop open-PR sweep (CLAUDE.md "Tech lead discipline") — both catch the rare stray the responsive
workflow_runrun misses (e.g. a PR the queue dropped on main-advance). Neither is the primary path.SECURITY — the workflow's author-trust gate is now load-bearing. With no dev enqueue, the workflow is the single enqueuer; it only enqueues PRs whose
authorAssociationis OWNER/MEMBER/COLLABORATOR. External contributor PRs are never auto-enqueued — they require a deliberate maintainer enqueue plus a greencla-check.
Waiting for CI — background the watcher, PIPELINE the next slice (do NOT idle)
CI wall time is now ~2 min (115-shard parallel, sort-by-duration scheduling,
parallel gate+shards — see PRs #503, #505, #506), plus merge-queue time after.
The dev does NOT terminate and hand off — it keeps the PR — but it also does
not sit idle blocking on CI. Run the watch as a background task, then
immediately claim and start your NEXT slice in a fresh worktree while CI
runs. On-the-spot recovery from drift / CI-failure with full PR context is
preserved — the watcher notifies you on settle, you recover THEN (the context
lives in the diff, not your foreground attention), and return to the next
slice. Idling on a green-riding PR produces zero output and burns the budget
window; a dev whose PR is in CI should always have a new slice in flight.
A stream of idle pings "while a PR is in CI" means the dev is NOT pipelining —
it should be claiming the next task. (See .claude/agents/developer.md step 5
and the pipeline-not-idle memory.)
# Watch the run live (preferred — exits when the run finishes):
run_id=$(gh pr view <N> --json statusCheckRollup \
--jq '[.statusCheckRollup[] | select(.detailsUrl) | .detailsUrl][0]' \
| grep -oE 'runs/[0-9]+' | cut -d/ -f2)
gh run watch "$run_id" --exit-status
# Or poll every 30s with a timeout:
deadline=$(( $(date +%s) + 1200 )) # 20 min hard cap
while :; do
pending=$(gh pr checks <N> --json state \
--jq '[.[] | select(.state == "PENDING" or .state == "IN_PROGRESS")] | length')
[ "$pending" = "0" ] && break
[ "$(date +%s)" -gt "$deadline" ] && { echo "CI > 20 min — escalate"; exit 2; }
sleep 30
done
After the run exits:
| Outcome | Action |
|---|---|
All required checks green + mergeStateStatus == CLEAN | Run Step 0 (the checks-API self-check); on MERGE, mark the task completed and stand down — the server-side workflow enqueues (Step 5, #2786) |
UNSTABLE (required green, a NON-required check red) | Do NOT stand down — auto-enqueue skips UNSTABLE and the PR strands indefinitely (#3878, #3904). Re-run the failed job: gh run rerun <run-id> -R loopdive/js2wasm --failed. Never enqueue manually |
Drift (mergeable_state becomes BEHIND while waiting) | Do NOT re-enqueue. update-branch/auto-refresh-prs auto-rebases BEHIND PRs and the auto-enqueue backstop re-sweeps. A clean fast-forward (git fetch origin && git merge origin/main && git push) is optional; never re-enqueue after — the backstop owns re-adds |
CI failure (any required check FAILURE) | Diagnose with full PR context — the agent KNOWS what it changed. Fix locally, git push, loop back to wait-for-CI |
| Long wait (>10 min) | Emit a TaskUpdate noting the unusual wait but keep waiting |
| Very long wait (>20 min) | Escalate to tech lead |
Step 0 — the merge gate (checks API; the committed CI feed is RETIRED)
The per-PR CI feed
.claude/ci-status/pr-<N>.jsonis RETIRED. The writer workflows (ci-status-feed.yml,ci-status-basic.yml,ci-status-pending.yml) areworkflow_dispatch-only stubs; the newest feed file onmainis from the PR-471 era. A current PR will NEVER get one — do not fetch it, wait for it, or treat its absence as "CI still in flight". (That misread stranded two agents on 2026-07-23.) Steps 1–4 below only ever applied to that feed and are kept as historical reference — do not execute them.
The operative gate, for EVERY PR (src or not):
gh pr view <N> --json statusCheckRollup,mergeStateStatus,isDraft,labels \
--jq '{ mergeStateStatus, isDraft,
labels: [.labels[].name],
pending: [.statusCheckRollup[] | select(.status != null and .status != "COMPLETED") | .name],
failed: [.statusCheckRollup[] | select(.conclusion == "FAILURE" or .conclusion == "failure") | .name] }'
pendingnon-empty → CI still running. Keep the background watcher on it.failednon-empty → diagnose with full PR context (you KNOW what you changed), fix locally, push, loop back to wait-for-CI. ESCALATE to the tech lead only for genuine judgment calls (see "What ESCALATE means").- All required checks green (per
docs/ci-policy.md§7) +mergeStateStatus == "CLEAN"+ not a draft + noholdlabel → MERGE: mark the task completed and stand down (Step 5); the server-side workflow enqueues. - Green checks but
BEHIND/BLOCKED→ the Drift row above; never re-enqueue. - No checks at all (workflow-only / CI-config PR) → MERGE — stand down (Step 5); the workflow enqueues, or the tech lead admin-merges a CI-only change.
What a green PR-level run does and does NOT tell you. On
pull_request,merge shard reportsandcheck for test262 regressionsare DESIGNED green no-ops: the heavy test262 shard matrix is merge_group-only (#2519 slim-down; #3431 mg matrix; #3448/#3467 per-SHA baseline reuse), so both jobs green-skip withSHARDS_RAN: false— their logs literally say "shards intentionally skipped" / "no merged test262 report to diff". A green PR is NOT evidence your PR causes no test262 regressions. The real regression/trap gates (the #3467 per-SHA-merge-base diff, the catastrophic guard #1668, the standalone floor/net guards #1897/#2097) run in themerge_groupre-validation on the merged state — which is why a fully-green PR can still be auto-parked (#2547) with a botholdlabel. Handle that per "If the queue rejects your PR" below.
LEGACY — Steps 1–4 (retired ci-status feed; do NOT execute)
These steps consumed the retired .claude/ci-status/pr-<N>.json feed. The
criteria they describe (net_per_test > 0, 10% ratio, 50-per-bucket) are now
enforced by CI itself: the regression-gate job runs them as a hard required
check in the merge_group (#1943, #3467). Kept only as reference for the
field semantics.
Legacy Step 1 — read the feed
git fetch origin
git show origin/main:.claude/ci-status/pr-<N>.json
If test262_skipped: true in the JSON, this was a test-only / docs-only PR
(no src/** changes). Skip Steps 3–4 entirely:
conclusion == "success"→ MERGE (go to Step 5, stand down — workflow enqueues)conclusion != "success"→ ESCALATE — basic CI failed on a non-src PR.
Extract: head_sha, net_per_test, regressions, regressions_real,
regressions_wasm_change, wasm_identical_noise, compile_timeouts,
improvements, run_url, baseline_stale, baseline_staleness_commits.
Legacy Step 1a — baseline staleness short-circuit (#1391)
If baseline_stale: true is set on the feed, the regression count is
contaminated by drift on main (tests that flipped between when the baseline
was last refreshed and the PR's CI run). Continuing through the criteria
below would falsely block PRs whose actual same-run-main diff is clean.
stale=$(jq -r '.baseline_stale // false' .claude/ci-status/pr-<N>.json)
if [ "$stale" = "true" ]; then
drift=$(jq -r '.baseline_staleness_commits // 0' .claude/ci-status/pr-<N>.json)
echo "ESCALATE — baseline is stale ($drift commits behind main HEAD)."
exit 1
fi
Output (when triggered):
ESCALATE — baseline is stale (N commits behind main HEAD). The CI feed's regression counts are inflated by drift, not by this PR. Tech lead should sanity-check by diffing branch-merged vs main-merged artifacts from the same CI run before merging.
Skip the rest of the algorithm. Do not merge. The tech lead may override after confirming via artifact comparison; the staleness threshold (50 commits) is conservative and most PRs will not be flagged.
regressions_wasm_change (added by #1222) = regressions where the
compiled Wasm binary differs between base and PR (excluding
compile_timeout). Pass→fail flips on a byte-identical binary are
physically impossible compiler regressions — they're CI runner variance
(scheduling, memory pressure, GC timing). This is the preferred field
for the ratio check in criterion 2.
regressions_real (added by #1192) = compile_error + fail regressions
only — excludes compile_timeout transitions which are runner-load
timing noise (tests right at the 30s compile-timeout boundary flap
based on CI system load). Used as a fallback when regressions_wasm_change
is null (older CI feed).
compile_timeout transitions are NOT counted — runner timing noise.
Wasm-identical pass→fail flips are NOT counted — runner variance noise.
Field priority (use the first non-null):
regressions_wasm_change → regressions_real → regressions
Legacy Step 1b — compile_timeout flake filter
A pass → compile_timeout transition is runner-load noise unless the
underlying compilation takes meaningfully long. Verified during the 2026-05-21
post-wave investigation: 23 of 27 "regressions" turned out to be timeouts on
tests that compile in <500ms locally. See
plan/issues/sprints/53/post-wave-regression-investigation.md for the full
investigation (headline number overstated ~6×).
If regressions_wasm_change is null (older CI feed) or if the JSON has a
breakdown by transition kind, the dev should subtract pass → compile_timeout
transitions where baseline_compile_ms < 5000 from the regression count
before applying criterion 2.
The cleanest field to use is regressions_wasm_change (introduced in #1222) —
it already excludes compile_timeout AND byte-identical-binary flips. If the
feed has it, prefer it. The filter chain stays:
regressions_wasm_change → regressions_real → regressions
If the CI feed somehow surfaces a regressions count that includes
compile_timeout flakes (older format), and the feed has a compile_timeout
field, compute:
flake=$(jq -r '.compile_timeout // 0' .claude/ci-status/pr-<N>.json)
R_real=$((regressions - flake))
Use R_real for criterion 2. Document this in your ESCALATE message if
relevant ("8 of 12 regressions are compile_timeout flake; effective R=4").
Legacy Step 2 — SHA check
git rev-parse HEAD
If head_sha in the JSON ≠ git rev-parse HEAD output:
ESCALATE — SHA mismatch. CI ran on a different commit. Push again and wait for a new CI result.
Stop.
#1943 — CI ENFORCES criteria 2 and 3 as a hard gate; the
merge_groupre-run owns regression-catching. The regression-gate job (scripts/diff-test262.ts) fails the required check when the 10% ratio or 50-per-bucket limit is exceeded, not just whennet_per_test < 0. The thresholds are exported constants (REGRESSION_RATIO_LIMIT/REGRESSION_BUCKET_LIMIT/REGRESSION_BUCKET_PATH_DEPTHinscripts/diff-test262.ts) — this table is the documentation twin of those constants; they are byte-identical by construction. Because the gate runs both on the PR and again in themerge_group(against the merged state), a regression cannot slip through whether the dev runs this self-check or not. So this skill is a pre-enqueue gate: a clean result means MERGE (mark the task completed and stand down — Step 5; the server-side workflow enqueues); a failing criterion means ESCALATE to tech lead instead.
Legacy Step 3 — criteria (in order, stop at first failure)
| # | Criterion | Failure output |
|---|---|---|
| 1 | net_per_test > 0 | ESCALATE — net_per_test is not positive (value: N). PR caused more regressions than improvements. |
| 2 | R == 0 OR R / improvements < 0.10, where R = regressions_wasm_change ?? regressions_real ?? regressions | ESCALATE — regression ratio is N% (R/improvements), exceeds 10% threshold. |
| 3 | No bucket > 50 regressions (see Step 4) | ESCALATE — bucket "<path>" has N regressions, exceeds 50-test limit. |
| 4 | All above pass | MERGE — mark the task completed and stand down (Step 5); the workflow enqueues. (merge_group re-runs this same gate.) |
R (criterion 2) prefers regressions_wasm_change if the feed has it
(post-#1222 CI). This filters out byte-identical-binary pass→fail flips,
which are CI runner variance, not real regressions. Falls back to
regressions_real (post-#1192, excludes compile_timeout), then to the
headline regressions count. Excluding wasm-identical noise and
compile_timeout prevents CI variance from tipping otherwise-clean PRs
above the 10% threshold. Compute it in shell with:
R=$(jq -r '.regressions_wasm_change // .regressions_real // .regressions' .claude/ci-status/pr-<N>.json)
If regressions is null in the feed (older CI format without per-test tracking): treat criterion 2 as pass and skip criterion 3 (no data to bucket). Result is MERGE (stand down; workflow enqueues) if criterion 1 holds.
Legacy Step 4 — bucket regressions (only if regressions > 0)
Download the merged report artifact and ensure the baseline JSONL is cached
locally (#1528 — the baseline is no longer committed to the repo; it's
fetched on demand from loopdive/js2wasm-baselines):
run_id=$(jq -r '.run_url' .claude/ci-status/pr-<N>.json | grep -oE 'runs/[0-9]+' | cut -d/ -f2)
mkdir -p output/sm-<N>
gh run download "$run_id" -n test262-merged-report -D output/sm-<N>
# Fetch the baseline JSONL to .test262-cache/ if not already present.
node scripts/fetch-baseline-jsonl.mjs
Bucket by path prefix:
python3 - <<'EOF'
import json
from collections import Counter
base = {}
with open('.test262-cache/test262-current.jsonl') as f:
for line in f:
try: d = json.loads(line); base[d['file']] = d['status']
except: pass
new = {}
with open('/tmp/sm-<N>/test262-results-merged.jsonl') as f:
for line in f:
try: d = json.loads(line); new[d['file']] = d['status']
except: pass
regs = [f for f in base if base[f] == 'pass' and new.get(f, 'pass') != 'pass']
buckets = Counter('/'.join(f.split('/')[:5]) for f in regs)
print(f"Total regressions: {len(regs)}")
for path, count in buckets.most_common(10):
flag = " <- EXCEEDS 50" if count > 50 else ""
print(f" {count:4d} {path}{flag}")
EOF
Any bucket with count > 50 → ESCALATE with the bucket name and count (criterion 3 above).
Step 5 — mark task completed, then stand down (do NOT enqueue)
All criteria passed → result is MERGE. You do NOT enqueue (#2786). The
server-side auto-enqueue.yml workflow is the single enqueuer: its
workflow_run-on-completion trigger fires right after the required-check
workflows finish and (grace 0) enqueues your just-green PR within ~one
workflow-startup — without depending on you or any watcher surviving. Trying to
enqueue yourself is the old model that stranded green PRs when the dev's watcher
died on stand-down (#2225, #2247).
So on MERGE: mark your task completed and stand down. Do not touch the merge
queue at all — no enqueuePullRequest, no gh pr merge --auto, no re-enqueue.
Once the workflow enqueues, GitHub will:
- Place the PR on a temp branch (
gh-readonly-queue/main/pr-<N>-...) - Re-run the required checks (
cheap gate,merge shard reports,quality— incl. the regression-gate) against the merged state via themerge_groupevent - Fast-forward main if checks pass;
auto-refresh-prs.ymlthen mergesorigin/maininto every other open PR branch - If the
merge_groupre-run fails,auto-park(#2547) labels the PRholdso it can't re-churn the queue — fix it on the branch, remove the label, and the workflow re-enqueues
Never enqueue or re-enqueue from a dev. The single trailing-add enqueue is the workflow's job; re-enqueue loops were the sole cause of the merge-queue cancellation churn (every re-add changes queue membership → GitHub rebuilds the merge group → CANCELS the in-flight
merge_grouprun; ~3.5h on 2026-06-20, memoryproject_merge_queue_requeue_cancels_run). The workflow's single trailing-add never loops. If a green PR somehow sits un-enqueued (the rare stray the responsive run missed), the ~30-min cron and the tech lead's per-loop sweep catch it. If something looks genuinely wrong, escalate to the tech lead.
The issue file already carries status: done. Under self-merge there is no
separate post-merge observer who can commit a status flip, and once the queue
lands the PR you cannot make a follow-up commit from /workspace. So the
implementation PR itself sets status: done + completed: <date> in the
issue frontmatter when you open it (by merge time it IS done; queue rejections
are rare, and the gate already verified what the queue re-verifies). Do NOT open
the PR at in-review and plan a later flip — that is exactly what orphans issues
at in-review (see #1602/#1603/#1606).
On a passing self-check (MERGE), your job for this PR is done — STAND DOWN. Do not enqueue, do not wait for the merge, do not re-enqueue. The server-side workflow takes it from here. Proceed immediately:
- (Status already
donein the merged PR — no separate flip needed.) TaskUpdate taskId=<your-task> status=completed- Remove your worktree:
git worktree remove /workspace/.claude/worktrees/<branch> - Sync the shared checkout once the queue lands the PR:
bash scripts/sync-workspace-main.sh— fast-forwards/workspacetoorigin/mainso it never rots behind (it silently fell 135 commits behind on 2026-05-29, which made the statusline report a stale sprint). It's a no-op on a clean, current tree and refuses to touch a dirty one, so it's always safe to run. (Tech lead's auto-merge monitor also runs this; running it here too keeps the checkout fresh between monitor passes.) TaskList→ claim next unowned task (or message tech lead if empty)
If the queue rejects the PR (rare), the
status: doneyou set has not yet landed on main, so nothing is orphaned;auto-parkholds it and you re-fix it below.
If the queue rejects your PR (auto-park labels it hold)
GitHub fails the final queue checks if something flipped between your CI run and
the queue's re-run (usually main moved). auto-park (#2547) then labels the PR
hold. In that case — the backstop, not you, owns the re-add:
- The auto-refresh workflow may have already pushed a merge of main into your branch — fetch and review
- Diagnose and fix with full PR context (you KNOW what you changed), push
- Re-run this self-check against the new CI run
- If clean, remove the
holdlabel and let theauto-enqueuebackstop re-sweep it — do NOT re-enqueue manually. (Your one-shot enqueue is spent; manual re-enqueue loops are exactly what caused the cancellation churn.) Escalate to the tech lead if it won't clear.
Admin direct-merge — tech-lead only
gh pr merge <N> --merge --admin (bypassing the queue) is tech-lead-only,
used only when the change is workflow-only / CI-only (queue ruleset checks don't
apply), a hotfix bypass is explicitly authorized, or the queue itself is broken
and needs unblocking. Set GATE_BYPASS=1 if the local pre-commit hook blocks
because pr-<N>.json isn't present. Devs never use this.
What ESCALATE means
Post to tech lead via SendMessage with:
- Which criterion failed
- The exact values from the CI JSON
- The PR number
Do not merge. Do not move to the next task. Own the issue until it resolves.
What these fields mean
net_per_test=improvements - regressions— per-test transitions fromdiff-test262.ts. The merge gate.regressions_wasm_change(#1222) — regressions where the Wasm binary changed (excludingcompile_timeout). Preferred for criterion 2.wasm_identical_noise(#1222) — pass→other transitions where the Wasm binary is byte-identical on base & PR. These are CI runner variance, not real regressions, and are excluded fromregressions_wasm_change.regressions_real(#1192) —compile_error + failregressions, excludescompile_timeout. Fallback for criterion 2.snapshot_delta= bulk pass-count difference vs committed baseline. NOT a merge criterion — contaminated by baseline drift. Ignore it.
Frequently asked questions
What to verify before installation and use
What does the dev-self-merge source document cover?
Devs DO NOT enqueue. On a passing self-check, mark the task completed and stand down — the server-side auto-enqueue.yml workflow enqueues (2786). This skill's outcomes are MERGE (regression self-check passes → mark the task completed and stand down; you do NOT touch the merge qu…
How do I install dev-self-merge?
The source record exposes this install command: npx skills add https://github.com/loopdive/js2 --skill ".claude/skills/dev-self-merge". Inspect the command and pinned source before running it.
Which permission-related actions were detected?
Static rules flagged exec-script in the source; the page lists the matching lines and excerpts.
Alternatives
Compare before choosing
K-Dense-AI/scientific-agent-skills
medchem
Medicinal chemistry filters for compound triage. Apply drug-likeness rules (Lipinski, Veber, CNS), structural alert catalogs (PAINS, NIBR, ChEMBL), complexity metrics, and the medchem query language for library filtering.
vasilyu1983/AI-Agents-public
agents-swarm-orchestration
Coordinates multi-agent execution across subagents, teams, and workflows. Use when planning dependency-aware fan-out, verifier passes, runtime selection, or Loop Engineering.
objectstack-ai/objectstack
objectstack-platform
Bootstrap, configure, extend, and operate ObjectStack runtimes. Covers project setup (`defineStack`, drivers, adapters, scaffolding), plugin and service development (PluginContext, DI, kernel hooks like `kernel:ready`), and operations (CLI commands, migrations, deployment, test harnesses via LiteKernel). Use when the user is writing `objectstack.config.ts`, building a plugin or driver, wiring a framework adapter, running `os` CLI commands, or planning deployment. Do not use for data schema desig
adaptico/adaptico-os
gtm-interviews
Customer-conversation engine for /gtm interviews <target>. Two jobs in one command - generate a customer-discovery interview kit (who to talk to, where to find them, questions that surface real past behavior instead of compliments, a per-conversation capture sheet), and synthesize the founder's transcripts or notes into validated pains, verbatim customer quotes, segments, and switching triggers, written back into PROFILE.md so positioning, copy, and outreach start from real customer language. Us