tenstorrent/tt-emule

shepherd-emule-pr

Take an open tt-emule PR to a mergeable, ethos-compliant state.

Zobacz źródło

Jak używać

  1. Skopiuj polecenie instalacji i sprawdź źródła przed instalacją we własnym środowisku agenta.
  2. W oryginale sprawdź wymagane narzędzia, dane dostępowe i obsługiwane środowiska.
  3. Opisz dane wejściowe i oczekiwany rezultat; porównaj wynik ze źródłami.
npx skills add https://github.com/tenstorrent/tt-emule --skill shepherd-emule-pr

Przed rozpoczęciem

  • Instalacja nie obejmuje subskrypcji modelu, limitu API ani uprawnień do plików.
  • Gwiazdki i instalacje pokazują aktywność, a nie niezależny test jakości lub bezpieczeństwa.
Oryginalny dokument Skill

Treść z repozytorium z zachowaniem nagłówków, przykładów, kodu, tabel, linków i obrazów.

Shepherd an emule PR to mergeable

The job: take an open PR and get it ready to land — review it against the repo ethos, confirm every review comment is actually resolved, fix what's still wrong, rebase onto origin/main locally, and hand the developer a change+verification summary (with a drafted per-point comment) to review and push. The PR author's later commits usually claim to have addressed the review ("Address review …"); an automated reviewer (Copilot) and a human reviewer have usually weighed in. None of that is trustworthy on its own.

Human-in-the-loop for the push. The skill rebases and prepares, but it does not force-push the author's branch or post the comment on its own — force pushing a shared branch rewrites someone else's history and is a human decision. The deliverable is a rebased local branch plus a summary the developer signs off on before pushing.

The governing principle, learned across three PRs: verify by building and reading, not by trusting an "addressed in commit X" claim or a green CI label — and always run your own ethos pass, because the reviewers miss the emule-specific bug classes. In #237/#238/#239, the human + Copilot reviewers each missed a hard JIT-compile bug that a 5-line compile-probe surfaces immediately.

The ethos you are enforcing (from .claude/CLAUDE.md): faithful to the canonical silicon implementation, a single code path (no divergent duplicate), the minimal jit_hw surface, surface caller bugs rather than mask them, and be skeptical of automated-reviewer suggestions — judge each against these rules, don't apply reflexively.

When to invoke

  • You're asked to review an open PR, address its comments, and prepare it to land

(rebase locally, then hand off a summary for the developer to push/comment).

  • A PR is CONFLICTING or behind main and needs a rebase plus a review pass.

Not this skill:

  • A pin bump turned the regression red (device-open crash, broad JIT-compile

drift, hang) → /uplift.

  • Reviewing your own uncommitted working diff for quality → /code-review

(built-in). Generic GitHub PR review with no landing → /review (built-in).

  • This skill is for shepherding a feature / shim PR to merge against review +

ethos, and it borrows /uplift's prove-by-build discipline and rebase mechanics.

Step 0 — Gather the full picture

Read every comment surface — reviews live in three different API buckets and gh pr view only shows one:

  • gh pr view <n> --json number,title,state,headRefName,baseRefName,author,mergeable,body,files,commits,statusCheckRollup
  • Issue comments: gh pr view <n> --json comments
  • Review bodies (CHANGES_REQUESTED / APPROVED verdicts): gh api repos/<owner>/tt-emule/pulls/<n>/reviews
  • Inline (line-level) comments: gh api repos/<owner>/tt-emule/pulls/<n>/comments

Note who requested changes vs approved, and reconcile: a reviewer may approve after leaving unresolved concerns. Read the CI artifact, not the label — a "pass" can hide smoke/JIT failures, and a FAILURE row named "All checks passed" is a required-check quirk, not the signal. Beware the rtk wrapper summarizing git status to ok; get real status with git status --porcelain | wc -l.

Step 1 — Check out and measure the rebase

git fetch origin <branch> && git checkout <branch>
git merge-base --is-ancestor origin/main HEAD && echo up-to-date || echo REBASE NEEDED
git log --oneline origin/main..HEAD          # commits to replay
git merge-tree $(git merge-base origin/main HEAD) origin/main HEAD | grep -i conflict

The branch may carry force-pushed "agent-storm" history (transient symbols, edits, repeated docs: refresh structure index). Work from the actual tip (git ls-remote origin refs/heads/<branch>), not the commit-message narrative.

Step 2 — Verify each review point against current code, in the ethos lens

For every comment, confirm the fix in the tree — a commit titled "Address review" often only partially fixes, or fixes one call site. Categorize each point:

VerdictMeaning
resolvedfixed in the tree; confirm it compiles / matches the ethos
partialone instance fixed, another remains (e.g. one requires converted, two left)
opennot addressed; you must fix or register it
mootthe flagged file/line no longer exists after a force-push

Judge against the ethos, not just "does it compile" — a change can compile and still be a divergent duplicate or a silent silicon divergence.

Step 3 — Own ethos pass (the catalog reviewers miss)

Sweep the diff for these recurring emule bug classes:

  1. Dangling refactored symbol. A bare __emule_dst (the DST file moved into

__emule_compute_ctx().dst in #223), or any symbol a git grep finds only in comments plus the new code. A non-dependent name in a plain inline/non-template function errors at parse time, so any TU that #includes the header fails to compile — even if the function is never instantiated. Bit #238 (gelu_tanh_tile) and #239 (transpose_wh_dest). Fix: route through the current accessor, match the sibling ops in the same file, add the __emule_dst_check those siblings use.

  1. Divergent-duplicate / ODR. The same symbol defined in two headers under one

#ifdef guard with non-identical bodies (#239 sigmoid_tile_pack forwarded to two different sigmoid_tile overloads); or a header that inline-defines a symbol the tt-metal runner also defines (#237 asan_cb_state.h vs emulated_program_runner.cpp). Fix: one definition site; the other path defers to it.

  1. Silent silicon divergence. A core-op special-case that masks an upstream bug

rather than reproducing silicon — e.g. skipping zero-multiplier lanes so inf*0 doesn't become NaN, when silicon FP does produce NaN (#239). Not faithful. Fix: fix the upstream inf source, or — when that's blocked — register it in /workarounds with the root cause + removal path and a code-site WORKAROUND comment. Never ship it silently.

  1. C++ standard mismatch. A requires-expression / C++20 construct in a JIT

header. Confirm the JIT -std: it is TT_EMULE_CXX_STANDARD = 20 (documented in docs/metal-integration.md), so C++20 is fine on the real path; a doc still claiming C++17 is stale and a separate cleanup, not a blocker (#237).

  1. Superseded-by-main. Main independently solved the PR's problem a different

way. Check current origin/main and the pinned tt-metal runner for the symbols the branch reworks. If so, a mechanical rebase re-introduces a parallel path — trim the PR to what's still needed instead (#237: ASAN restructure was dead; runner already defined the symbols and the log moved to the fiber ctx).

Step 4 — Prove by build (the JIT compile-probe)

The load-bearing verification. It catches classes 1, 2, and 4 in seconds without a full build. Reconstruct the JIT flags from tt_metal/impl/emulation/emulated_program_runner.cpp (-std=c++<TT_EMULE_CXX_STANDARD>, -I jit_inc, -I parent_inc, -DTT_EMULE_USE_L1_POOL):

bash
# probe.cpp — include the umbrella FIRST so the compute ctx / VectorMode / ALWI
# exist, THEN the header under test. A jit_hw header alone usually can't be the
# first include.
cat > probe.cpp <<'EOF'
#include "jit_hw/api/compute/compute_kernel_api.h"
#include "jit_hw/<header under review>"          // e.g. api/compute/eltwise_unary/gelu.h
EOF

clang++-20 -std=c++20 -fsyntax-only \
  -DTT_EMULE_USE_L1_POOL -DARCH_WORMHOLE -DNUM_DRAM_BANKS=12 -DNUM_L1_BANKS=64 \
  -I <tt-emule>/include/jit_hw -I <tt-emule>/include \
  -I <tt-metal>/tt_metal/hostdevcommon/api  probe.cpp
  • For a header on the matmul AVX2 path, add -DEMULE_MATMUL_USE_AVX2 -mavx2 -mfma.
  • For the fused-activation aggregator, define SFPU_ACTIVATION and include

compute_kernel_hw_startup.h after the umbrella.

  • To decide a C++20-vs-17 concern, run the probe at both -std=c++20 and

-std=c++17 — clean at 20 / error at 17 proves it's std-only, and the JIT is 20.

  • Grep-corroborate class 1: git grep '<symbol>' should find a real definition,

not only comments; emule_thread_ctx.h records what a symbol "was".

This is a targeted probe of the changed headers, not the full suite — see the Step 8 caveat.

Step 5 — Make changes as needed

  • Faithful fix. Match the file's existing idiom and sibling ops; single code

path; no defensive divergence (/verify-mock, /memory-debug for residuals).

  • Register a workaround. When the faithful fix is blocked, add a /workarounds

entry (what it is, why it bends a rule, real root cause, removal path, tracking issue) and a WORKAROUND (WA-n) code-site comment. Don't leave a silent divergence.

  • Trim superseded work. Drop the parts main already provides; keep the genuinely

new contribution.

  • Surface scope-changing calls to the user before putting them in the

handoff — trimming a large chunk (#237) or keeping-vs-reverting a workaround (#239) is the reviewer's decision, not yours. Use AskUserQuestion with a concrete recommendation.

Step 6 — Rebase onto origin/main (supersession-aware)

git fetch origin main && git rebase origin/main
  • Resolve each conflict by asking **"does main + the pinned runner already provide

this?"** — git grep the tt-metal runner (.../impl/emulation/) for the symbols. Favor main's evolved model over a superseded branch approach.

  • structure.yaml conflicts: resolve crudely (take either side), finish the

rebase, then regenerate against the final tree: python3 scripts/gen_structure.py --write, and confirm python3 scripts/gen_structure.py --check + git diff --check.

  • Trimming pattern: after the rebase, a single self-documenting cleanup commit

is cleaner than commit surgery (interactive rebase is unavailable here) — git checkout origin/main -- <superseded files>, git rm <orphaned files>, regenerate structure.yaml, commit with the rationale. The net tree is what ships.

  • Keep the branch's own PR ref intact — detach/rebase, don't reset a shared branch

onto something unexpected.

  • The rebase stays local. Pushing the rewritten history is Step 7's handoff,

performed by the developer — the skill never pushes it.

Step 7 — Hand the developer a summary (don't push)

Stop at the rebased local branch. Do not git push — force-pushing a shared branch rewrites the author's history and is the developer's call, not the skill's. Instead present a handoff the developer can act on:

  • What changed and why — per fix: the review point / ethos-class it resolves,

the mechanism (not just "done"), and the file:line.

  • Verification evidence — the compile-probe command(s) you ran and the result

(the actual use of undeclared identifier line, or a clean exit), plus the honest caveat (a targeted header probe is not run_regression.sh).

  • The drafted per-point PR comment (Step 8) for the developer to post.
  • The exact commands to run, so the human performs the branch mutation:
  git push --force-with-lease origin <branch>   # rebase rewrote history; --force-with-lease
                                                 # guards a concurrent update to the tip you based on
  gh pr comment <n> --body-file <file>

The developer reviews the summary, then pushes and posts (or tells you to). If the user explicitly directs you to push a specific branch, that direction is the authorization for that branch only — don't extend it to others, and still surface the summary first.

Step 8 — Draft the per-point comment (developer posts it)

Draft the comment as part of the handoff — gh pr comment <n> --body-file <file> is the command the developer runs (Step 7). Include:

  • Per-point verdict for every review comment: resolved / fixed-here /

registered (WA-n) / trimmed / moot — with the mechanism, not just "done".

  • Any extra bug you found, with the compile-error proof pasted (the

use of undeclared identifier line, etc.) so it's not an assertion.

  • The honest verification caveat: targeted compile-probes are not a full

run_regression.sh (there is usually no build_emule in-workspace) → recommend a per-arch regression before merge.

  • The alternative you didn't take (e.g. "revert vs register the workaround —

say the word") so the reviewer can redirect.

Anti-patterns (consolidated)

  1. Trusting "addressed in commit X" without reading the resulting tree.
  2. Trusting a green CI label — or rtk's filtered git status ok. Read the

artifact; get --porcelain status.

  1. Skipping the own-ethos pass. Reviewers missed a hard compile bug in all

three reference PRs; the compile-probe finds it in seconds.

  1. Blindly rebasing a superseded PR — re-introducing a divergent parallel path

main already replaced.

  1. Pushing the author's branch yourself. The skill rebases locally and

hands off; the developer reviews the summary and runs the --force-with-lease push (and posts the comment). Never force-push a shared branch on your own — it rewrites someone else's history. This is doubly true for a scope-changing reconciliation (a trim, a revert), which needs explicit sign-off besides.

  1. Claiming verification you didn't do — a targeted header compile is not the

regression suite; say which you ran.

  1. Applying Copilot/automated suggestions reflexively — judge each against the

ethos (a suggested defensive clamp is usually the wrong fix).

References

  • /uplift — prove-by-build discipline, rebase/pin & cross-repo push mechanics,

reading the CI artifact over the label.

  • /workarounds — how to register a deliberate divergence (Step 5 / class 3).
  • /memory-debug, /verify-mock — residual triage and mock-completeness checks.
  • .claude/CLAUDE.md — the ethos rules this skill enforces.
  • scripts/gen_structure.py (--write / --check), scripts/find_symbol.py

(--supports / --shadows to probe whether a symbol/include is modelable).

Powiązane zadania

z tego samego repozytorium

Więcej Skills

Wszystkie Skills
tenstorrent
Społeczność

index-based-ops

Bring up or debug index-based compute ops (TopK, Sort, Argmax) in tt-emule — ops that return values + indices, where ties make the index choice non-unique. Use when implementing one of these ops or triaging its value/index test failures.

instalacje
1
GitHub Stars
5
Aktualizacja
16 paź
tenstorrent
Społeczność

memory-debug

Diagnose data-corruption failures in tt-emule operations (wrong values, partial zeros, off-by-N row/col writes). Use when a regression test reports ATOL 1e-3 on otherwise-functional kernel paths.

instalacje
1
GitHub Stars
5
Aktualizacja
16 paź
tenstorrent
Społeczność

verify-mock

Verification checklist to walk before declaring a tt-emule mock complete. Use after implementing a stub (typically at the end of /implement-mock or /compute-llk-bringup) to catch the recurring failure modes — signature drift, no-op math, missing format dispatch, JIT-cache staleness, regression baseline drift.

instalacje
1
GitHub Stars
5
Aktualizacja
16 paź
tenstorrent
Społeczność

workarounds

Registry of deliberate, non-ideal workarounds currently live in tt-emule (hacks we accepted to make something pass, NOT normal development practice). Read this before adding any new workaround, and when touching code that carries one — each entry records what the hack is, why it is not the right fix, the real root cause, and the path to removing it.

instalacje
1
GitHub Stars
5
Aktualizacja
16 paź