Use when reviewing UI for accessibility — WCAG 2.2 AA, keyboard nav, focus, ARIA, contrast, screen-reader semantics — even on 'is this a11y-OK?' or 'mach das barrierefrei'.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when working with Git — branch naming, commit messages, PR creation, rebasing, or the code review process — even when the user says 'push this' or 'merge the branch' without naming Git.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
Use when preparing PRs, finishing branches, or following the team's Git workflow.
Do NOT use when:
php-coder or code-review skill)github-ci skill)BEFORE ANY MERGE / PUSH / PR / BRANCH ACTION — OR ANY CLAIM OR QUESTION
ABOUT THEIR STATE — QUERY THE LIVE REMOTE. NEVER FROM MEMORY OR
CONVERSATION HISTORY. A PR MAY ALREADY BE MERGED OR CLOSED REMOTELY.
ASKING WHAT `gh pr view` ANSWERS IS A CHEAP QUESTION — CHECK, DON'T ASK.
The local branch view and the conversation's memory both go stale the moment anyone else — a maintainer, a parallel agent, an auto-merge rule — acts on the remote. Acting or asking on stale state is the recurring failure this section kills (canonical: asking "shall I merge these 4 PRs?" when all four were already merged remotely). Run first, every time:
git fetch origin --quiet
gh pr view <number> --json number,state,mergeStateStatus,mergedAt,baseRefName
# state: OPEN | MERGED | CLOSED — act only on the live value
gh pr view /
git fetch answers it. Asking is a cheap question (per no-cheap-questions).MERGED / CLOSED → there is nothing to merge or push; report the live
state and stop — do not attempt the action.state + mergeStateStatus in the
same turn; never merge on a status seen earlier in the conversation.npx tsx node_modules/@event4u/agent-config/src/scripts/check_branch_freshness.ts;
exit 1 ⇒ the branch is behind and is not current (or the named base does not exist on the remote; the message says which) — update it from the base per git.update_strategy (references/branch-update.md),
regenerate the derived files, then open the PR (see
/create-pr § 1b). Exit 0 means only that
the gate did not refuse: read the line. branch is current is the pass;
NOT VERIFIED means the base could not be reached and freshness is
unknown — the gate exits 0 there on purpose so an offline push is not
blocked, which makes reporting it as "current" the one misread it cannot
catch. Exit 0 also covers the paths with nothing to check — a no-op in CI, a
detached HEAD, standing on the base itself — and under --quiet a genuine
pass prints nothing, so run it without the flag when you need a verdict to
read.
Prefer it over git rev-list --count HEAD..origin/main, which is wrong twice
over: it pins main as the base for a branch whose PR may target something
else, and it reads the local tracking ref — a fetch from earlier in the
session, which is memory rather than a check. The gate asks the remote and
resolves the base from the open PR.→ See guideline docs/guidelines/php/git.md for branch naming, commit messages, PR conventions.
→ See commit-conventions rule for commit format, types, and scope rules; a team convention is declared in the git: settings (commit_format, branch_pattern, update_strategy).
→ Use conventional-commits-writing skill for generating/reviewing commit messages.
quality.local_auto_run: true (see quality-tools § Execution policy): type-checker → auto-fixer → linter → type-checker, then the project's test command (detect from manifest: php artisan test / vendor/bin/phpunit (PHP), npm test / pnpm test / vitest / jest (JS-TS), pytest (Python), cargo test (Rust), go test ./... (Go)). Under the default (false / missing) skip both — remote CI on the PR is the gate; say so instead of claiming they passed.references/branch-update.md.When implementation is complete and all tests pass:
Work complete. What would you like to do?
1. Push and create a Pull Request
2. Keep the branch as-is (I'll handle it later)
3. Discard this work
quality.local_auto_run: true; default false → skip, remote CI is the gate).git.update_strategy, references/branch-update.md) → regenerate →
verify → re-check freshness (this repo wires it as a push-ready task target;
a consumer wires its own). Not optional housekeeping: see § A push closes its
own loop. A stale push is refused, so skipping this buys the refusal.git push -u origin "<branch>" (a rendered name is always quoted) — after a rebase of a pushed branch, --force-with-lease per references/branch-update.md.gh pr create using PR template./fix ci § 0, with the PR number.A PUSH IS NOT A DELIVERY. THE EVIDENCE FOR A PUSH IS THE CI VERDICT,
NEVER THE PUSH'S OWN EXIT CODE.
BEHIND THE BASE → INTEGRATE BEFORE PUSHING, NEVER AFTER THE PR IS RED.
RED AFTER PUSHING → FIX IT IN THE SAME TURN, OR SAY PLAINLY THAT YOU DID NOT.
NEVER HAND THE USER A RED PR WITH ITS CAUSE NAMED AND UNFIXED.
Two halves, failing differently, over the 30 sessions and 50 PRs before
2026-09-04. Stale base: 25 of 50 PRs carried a Merge branch 'main' into …
commit (52 in total), and the three most-failing workflows are the base-relative
ones — a branch pushed behind its base was verified against a base it no longer
merges into. Unsettled push: 22 of 30 sessions ran gh run view --log-failed, and 20 of 50 PRs carried a follow-up fix(ci|gates|budget)
commit. Only 19 of 50 landed with neither. Each half now has a deterministic
carrier — the pre-push hook refuses a verified-behind branch and points at the
push-ready sequence; the push-settle PostToolUse concern fires the moment git
reports a ref advanced. Neither replaces the discipline: the hook is skippable
with AGENT_CONFIG_SKIP_PREPUSH_FRESHNESS=1 for a genuine WIP push, and the
settle reminder is advisory, because leaving a push deliberately unsettled is
legitimate — ending the turn silently on one is not.
ci_settle non-zero → read only the failing part
(gh run view --job <id> --log-failed | grep -E '×|FAIL|Error'), fix, push
again; the author of the red is irrelevant (fix-what-you-see). Three failed
attempts on one target trigger autonomous-execution's mandatory strategy shift.
Exit 2 is not a verdict — the wait timed out or the API could not be read.
Counts, carrier limits and the honest cost:
references/push-closes-its-loop.md.
The project uses .github/pull_request_template.md:
main is default/production branch./pr:merge § 9), never assumed; rebase-and-merge keeps every commit, so each subject must follow the convention.Use ONLY when the user explicitly authorized a squash on a branch that is already on origin. The whole sequence runs in one turn — never end the session between rewrite and push.
Trigger context: git-history-discipline rule routed here.
REMOTE/RB: the published ref, from the resolve block of references/branch-update.md § The rebase sequence — never @{u}; unresolved → no squash.
DATE=$(date +%F)
PUBLISHED=$(git ls-remote "$REMOTE" "refs/heads/$RB") || { echo "STOP: could not read $REMOTE/$RB — nothing was rewritten" >&2; exit 1; }; EXPECTED=$(cut -f1 <<<"$PUBLISHED")
git fetch -q "$REMOTE" "refs/heads/$RB"
SNAP="refs/agent-config/rewrites/squash-${DATE}-$$"
git update-ref "$SNAP/before" HEAD
git update-ref "$SNAP/published" "$EXPECTED"
Two refs = two recoveries (local tip + published tip), private — git push --tags cannot publish them; git reflog is TTL-bounded and unreliable across sessions.
git rev-list --left-right --count "HEAD...$EXPECTED"
0 0 → aligned, proceed.N 0 (local ahead) → unpushed work, proceed.0 N (published ref ahead) → git merge --ff-only "$EXPECTED" first, then re-check.M N (both non-zero) → divergent. Abandon the squash and run
§ Divergent-State Recovery below.Default — soft-reset path (single token-cheap rewrite):
git reset --soft "$(git merge-base HEAD <base>)"
git commit -m "<conventional commit message>"
Interactive rebase only when the user wants per-commit control — it replays
derived files (dist/agent-src/, router projections) and conflicts on every replay.
# $EXPECTED is the SHA pinned in step 1 — re-reading it would lease a collaborator's push
git push --force-with-lease="refs/heads/$RB:$EXPECTED" "$REMOTE" "HEAD:refs/heads/$RB"
[ "$(git ls-remote "$REMOTE" "refs/heads/$RB" | cut -f1)" = "$(git rev-parse HEAD)" ] \
&& echo "OK: the published ref matches HEAD" \
|| echo "MISMATCH — do not end session"
If the push fails (pre-push hook, network, token budget):
HEAD.Report exactly:
$SNAP — removed with git update-ref -d once step 4 verified parity; kept, with git reset --keep "$SNAP/before" printed, if anything failedFires when git rev-list --left-right --count "HEAD...$EXPECTED" (the published
ref's SHA, pinned as in § Safe squash-after-push step 1) shows both sides non-zero.
A blind git pull --rebase here replays remote commits on top of a
local history that may already represent the same work in a different
shape — guaranteed conflict storm in derived files, possible
double-application of the same change. This is the documented failure
mode behind git-history-discipline.
SNAP="refs/agent-config/rewrites/diverged-$(date +%Y%m%dT%H%M)"
git update-ref "$SNAP/before" HEAD
git update-ref "$SNAP/published" "$EXPECTED"
git log --oneline "$EXPECTED..HEAD" # local-only commits
git log --oneline "HEAD..$EXPECTED" # published-only commits
git diff "$EXPECTED..HEAD" --stat # shape of local-ahead work
Decision matrix:
| Pattern | Future | Action |
|---|---|---|
| Local has the same logical work as origin, just reshaped (squash/rebase) | Local | After PR-review check (step 4), git push --force-with-lease=refs/heads/<b>:<sha> <remote> HEAD:refs/heads/<b> |
| Origin has commits local does not reflect (another contributor pushed) | Origin | Keep any local-ahead work at the step-2 refs for cherry-pick, then git reset --hard "$EXPECTED" |
| Both sides have genuine independent work | ask user | Never decide silently — surface the two commit lists and let the user pick |
If a PR is open on this branch:
gh pr view --json reviews,comments
# or via GitHub API: /repos/<owner>/<repo>/pulls/<num>/{reviews,comments}
If review comments are anchored to commits that the force-push will erase → STOP, ask the user how to preserve them. A force-push that destroys live review feedback is unrecoverable from the agent side.
Use the refs from step 2 to restore either side if step 4 surfaces a
problem. After resolution, verify the published ref equals HEAD and report both
SHAs plus the refs recorded.
git pull --rebase after detecting divergent state.git push --force, and no --force-with-lease without its fully qualified refs/heads/<b>:<sha>.refs/agent-config/rewrites/ first.Depth for the git-history-discipline
Iron Law on inherited & shared-branch commits (migrated here per P4 of
road-to-kernel-and-router.md).
The user often works in parallel with the agent, and multiple agents may
share one PR branch. A commit that looks "unrelated" or "stray" may be
deliberate in-flight work the user expects to keep. Reseating a branch onto a
different base, git reset --hard-ing away inherited commits, force-pushing
over a branch you did not create, or branching from a base with unexpected
commits and then "cleaning" them out all silently discard work — the exact
failure that law prevents.
Before ANY of these, STOP and ask (one numbered-options prompt per
user-interaction):
git rebase --onto, git reset --hard <other-base>)
in a way that drops commits already on the branch;push <local>:<remote>-replacing) a branch that carries
commits you did not author;Preserve-first is necessary but not sufficient. Even when you keep the commits reachable (a save-branch / tag), you still ask before the branch the user sees loses them — "I preserved them locally" is not a substitute for the question, because the user may be mid-edit on the shared branch and a force-push would clobber their in-flight work regardless of your local backup.
Pre-rewrite stop. Before any squash / amend / rebase of a pushed branch: resolve the ref it publishes (@{push}, or the pull request's head repository — references/branch-update.md § The rebase sequence; never @{u}, which is the base for a branch pushed without -u), pin its SHA once, then git rev-list --left-right --count "HEAD...$EXPECTED". An unresolved target is no rewrite. Squash / amend: if either side is non-zero — STOP and run § Divergent-State Recovery. Rebase: the pinned SHA must already be in HEAD — your own unpushed commits travel with the rebase. A blind git pull --rebase in this state is the documented failure mode. (§ Safe squash-after-push steps 1–2 implement this stop.)
Post-rewrite stop. After the rewrite, push in the same turn with git push --force-with-lease=refs/heads/<b>:<pinned-sha> <remote> HEAD:refs/heads/<b> and verify git ls-remote <remote> refs/heads/<b> equals git rev-parse HEAD. A rejected lease is a stop — refetch and report, never a bare --force-with-lease, never --force. If the push fails (hook, network, token budget) — fix the cause and re-push before ending the session, committing new work, or handing off. (§ Safe squash-after-push step 4 implements this stop.)
If either stop fires and resolution is not immediate → record the state (git update-ref refs/agent-config/rewrites/<tx>/before HEAD) and hand control back to the user. Do not let a new session inherit a dirty divergence.
git rebase -i (interactive)git rebase --autosquashgit commit --fixup / --squash (helpers that feed autosquash)git commit --amend on already-pushed commitsgit push --force / --force-with-lease (unless paired with the protocol)git reset --hard past unpushed work the user might want--amend on the current local commit before the first push is the narrow exception (treated as continuing to compose the commit, not rewriting history).
When a pre-commit hook fails, the commit did NOT happen — no new commit
object was created. A reflexive git commit --amend at that point does not
"retry the commit"; it rewrites the previous, already-good commit,
destroying that work. This is the one place the narrow --amend exception
above turns into data loss.
Recovery — never amend after a hook failure:
git add).git commit, not --amend) — the prior commit was
never overwritten and must stay intact.(Migrated here from git-history-discipline — recovery now lives next to the
mechanism it protects.)
Interactive rebase + fixup loops generate disproportionate token cost on every iteration: re-running CI per replayed commit, resolving the same content conflict in two derived files (dist/router.json, .windsurfrules), losing the working tree to a stash that silently re-introduces older state. A single conflict can burn the budget of an entire feature.
A previous session squashed a pushed branch, the push hook failed at the token boundary, the session ended — and the next session saw local and origin pointing at different SHAs for the same logical work. A blind git pull --rebase cascaded into conflicts across every derived file. Recovery required forensic SHA-archaeology. The pre/post-rewrite stops make that sequence structurally impossible.
chore: regenerate commits, ugly." → don't. They are honest checkpoints.fix(scope): … on top.origin/main so my PR is clean." → don't, ask first. They may be the user's parallel work or another agent's. Preserve them and ask which base the user wants.git stash can lose work — prefer WIP commits.main.아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
Use when reviewing UI for accessibility — WCAG 2.2 AA, keyboard nav, focus, ARIA, contrast, screen-reader semantics — even on 'is this a11y-OK?' or 'mach das barrierefrei'.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when defining or auditing the activation event — aha-moment selection, retention correlation, falsifiable definition. Triggers on 'what is our aha moment', 'redefine activation'.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when capturing an architectural decision — file naming, next ADR number, Status / Context / Decision / Consequences, index regen; fires even without saying 'ADR'.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Adversarial critique — devil's advocate, stress-test, honest teardown ('poke holes', 'be brutal', 'was hältst du davon'); explicit request only. Routine code or design review → code-review.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when reading, creating, or updating agent documentation, module docs, roadmaps, or AGENTS.md. Understands the full .augment/, agents/, and copilot-instructions structure.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use for an adversarial red-team / blue-team / auditor review of an AI agent's CONFIG + behaviour (rules, skills, MCP, hooks, permissions) — attack-chain → defensive-gap list, not a code audit.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.