syft-pr-review
Skill10k starsChanged 6 days agoApache-2.0View on GitHub
Write a review document for a syft pull request. Takes a PR number or URL, reads the diff, and produces a checkbox-structured summary of the flows that changed with the new and changed code under each, the tests, and any code-standards problems in the new code. Use when the user says "review PR 1234", "write me a review doc for <PR link>", or "what changed in this PR".
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 0 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 9
Write a document a reader finishes in a few minutes and still knows what changed and what was decided.
- Very specific: line 39
Read base-check.txt first.
- Very specific: line 46
Keep the script in step with this file: If a step below needs something /tmp/pr-<N>/ does not hold — because the skill changed, or because …
- Very specific: line 58
Check before you write: whether a name is a method or a plain function, whether a folder is really a package, and whether each claim in …
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Review a syft PR
Write a document a reader finishes in a few minutes and still knows what changed and what was
decided. Explain the change, and flag where the new code breaks a house standard. Do not hunt for
bugs — that is /code-review.
Input
A PR number or URL. If none was given, ask for it.
Step 1 — Prefetch, in one call
./.claude/skills/syft-pr-review/prefetch.sh <N> # writes /tmp/pr-<N>/It prints an index and writes:
| file | what is in it |
meta.json | title, body, author, state, base, head, +/-, file count |
body.md | the description, to check its claims against the diff |
files.txt | every changed path with its +/-, largest first |
files-skippable.txt | lock files, notebooks and generated data — count these, do not read |
commits.txt | non-merge commits on the head branch that are not in the base |
merges.txt | merge commits in that same range |
base-check.txt | every branch named in the body, and whether it has landed yet |
full.diff | the whole diff |
diff-index.txt | path<TAB>per-file diff; cat the chunk you want |
new-symbols.txt | every def/class the diff adds, with its line number on the head |
new-tests.txt | every test function and class the diff adds |
Read base-check.txt first. A branch marked NOT-MERGED is a base that has not landed, so its
commits land with this PR and belong in the document — say so in one sentence at the top and tag
each item with the branch it came from. commits.txt is the author's own work.
new-symbols.txt is a candidate list, not the answer: it also catches a nested function and a
pre-existing def whose signature changed. Confirm each one is really new before you call it new.
Keep the script in step with this file. If a step below needs something /tmp/pr-<N>/ does not
hold — because the skill changed, or because this PR has a shape the script does not cover — add it
to prefetch.sh and re-run, rather than running the command by hand. The point of the script is
that one call answers the whole of steps 1 and 2.
Step 2 — Read the diff, not the description
cat the per-file chunks from diff-index.txt, source files first, then the places that call them
— that is where the flows are. For tests, read the name and what it asserts, not the whole body.
Say what you skipped, with counts, using files-skippable.txt. Open the changed file from the repo
when a diff chunk alone is not enough to describe something correctly.
Check before you write: whether a name is a method or a plain function, whether a folder is really a
package, and whether each claim in body.md is still true.
Step 3 — Write it
Save to koen/reviews/<N>/summary.md when a git-ignored koen/ folder exists, otherwise
reviews/<N>/summary.md in the repo root — and say the file is untracked. One folder per PR, so
anything else about that review lands beside the summary later.
Flows come first, because they are why the reader opened the document.
# PR <N> — <title>
`<repo>#<N>` · <author> · <head> → <base> · +<add>/-<del> across <files> files · <state>
<2-4 plain sentences: what this PR does and why.>
> Read time ~<n> min. Not read: <what, with counts>.
---
- [ ] **1. Flows**
- [ ] **1.1 <Flow name>** _(new)_
- [ ] When <trigger>, `A.start()` calls `B.handle()`, which calls `C.save()`.
- [ ] Decision: we could have done Z; we do A because <reason>.
- [ ] **New code**
- [ ] NEW CLASS `Name` — `path/file.py:<line>` — <what it is for>. Built by `A.b()`.
- [ ] NEW helpers in `path/file.py` — `f()` <does X>, `g()` <does Y>.
- [ ] **Changed code**
- [ ] `path/file.py: Class.method()` — previously <did Z>, now <does A>.
- [ ] DELETED `Class.old()` and `file.py: helper()`, because <reason>.
- [ ] **1.2 <Flow name>** _(changed)_
- [ ] When we <do X>, we previously <did Z>. Now <A>.
- [ ] **New code** — `Name` (1.1.3.1); here it <does Y>.
- [ ] **2. Other new code** — only code no flow uses; usually dropped
- [ ] **3. Other changes** — only changes no flow uses, grouped by theme; usually dropped
- [ ] **4. Tests**
- [ ] **4.1 NEW `path/test_file.py`** — <n> tests<, and how they are set up, when it is worth a clause>
- [ ] `test_a()` — <the condition, what runs, and what is then true>
- [ ] `test_b()` — <the condition, what runs, and what is then true>
- [ ] **4.2 REWRITTEN `test_c()`** — `path/test_file.py` — now asserts <X> instead of <Y>, because
<reason>.
- [ ] **4.3 UPDATED for the new code** — <n> tests across <n> files follow the new
`Class.method()` signature. Nothing is asserted differently.
- [ ] Decision: <only when a test settles something a reader would otherwise wonder about>
- [ ] **5. Code standards** — only where the new code breaks one; drop the section when it does not
- [ ] **5.1** `path/file.py: Class.method()` — <the problem, one line>
- [ ] **6. Blocked on** — drop this section unless something real stops the merge
- [ ] **6.1** <the problem, and what has to happen before this can go in>
- [ ] **7. Comments for the author** — leave it empty; the review UI writes into itNumber the sections that survive in order. The comments section is always last, and always there.
What counts as a code-standards problem
Judge only the lines this PR touched. Do not review the code around them, and do not turn this into
a second review. Name the file and the Class.method() or file.py: function(), keep each to one
line, and write nothing when there is nothing wrong. Look for:
- a function or method you have to scroll to read; aim for 30 lines, and allow more only when it calls nothing else. Test functions are exempt — a long test is normal, so never flag one for length
- a method that calls out and then works on the answer inline —
ab = Y.Z()followed by logic onabbelongs in its own helper - string building that is not an f-string
- a repeated or magic value that belongs in a module-level constant
- two functions or methods that do substantially the same work; one of them belongs, called from both places. Name the pair and what they share. Let a repeated line or two go — the copy has to be big enough that pulling it out is worth a helper
- an import inside a function; fine only to break a circular import, and worth one short note
- a name that does not say what the thing is, or pads a name that does. Length is free when every
word earns it, so drop articles and filler. Say it as a plain sentence and stop there:
test_no_hint_when_the_do_owns_none_of_the_jobs() violates the no-filler rule, rename to test_no_hint_when_do_owns_no_jobs()
Rules
- Every bullet is a checkbox, at every depth.
- Scannable, not prose. Keep a bullet to two or three lines. When a bullet reaches for a semicolon to join items, or repeats the same shape three times over, those items are separate child bullets. The reader is looking for one thing, not reading front to back.
- Length and position follow the code. Word count and placement are both claims about how much something matters, so a ten-line class gets a few words, not five bullets. Group small related additions under one bullet. Collect mechanical cleanups — a moved import, a renamed local, a deleted comment — into one short note at the end of the theme they belong to, never a bullet of their own.
- Code sits under the flow that uses it, said once. Describe a class or function in full under the first flow that uses it; a later flow gets one bullet naming it and its number. When parts of one class serve different flows, split them over those flows. The "Other" sections hold only code no flow uses. Tests belong only in the tests section.
- One test, one bullet, nested under its file. The file gets the parent bullet with the count, each test a child bullet. Do not walk through test bodies.
- A test bullet carries its own context. One sentence naming the condition, what runs, and what is then true — the reader has only that line. Write if a job list holds no unique name, the hint under the table renders a position instead of a name, not with no unique name left, the hint gives a position. Give the minimum that makes it stand up, not the whole setup.
- Tests, in proportion. Collapse tests that only follow the new code — a changed call, a rebuilt fixture — into a single bullet with a count, since nothing is asserted differently. Give a bullet of its own to a test whose meaning actually changed, and say why.
- Standards: new code only. Flag a standards problem only in lines this PR touched, and only when there is one. Never audit the surrounding code.
- No question list. A reviewer can ask their own questions, so do not collect them. Only name something that genuinely blocks the merge, and leave that section out when nothing does.
- Plain words. Explain any term you have to use. Do not write "on the wire" (say sent over the network), "opaque", "envelope", "surface", "inert" or "residual".
- Every bullet stands alone. A reader three levels deep must not need the bullet above it. A theme heading is a filing label, not context: "B — Errors that name both sides" says nothing about what raises the error or who the two sides are, so every bullet under it names its own subject.
- Name both sides. Never just "a version mismatch" — say which versions, held by whom, and compared against what: this client against the peer's version file, the local folder against the copy on Drive, one protocol against another. The same goes for any comparison or hand-off.
- Qualify every name.
Class.method()for a method,file.py: function()for a plain function. Never a bare_helper()— the reader will guess the wrong owner. - Say who calls whom, and when it runs. "
A.b()callsc.py: d()", not "A.b()→d()". - Before and after, everywhere: When we do X, we previously did Z. Now we do A.
- Say what was decided — the alternative and why it lost — not only what changed. Only for decisions that change how someone reads the code; skip the rest.
- Budget reading time: roughly 40 bullets for a normal PR, 120 for a very large one.
- Do not repeat the PR description. If your text matches it, you read the wrong thing.
- Number every section and subsection,
**<N>.<M> <label>**, in every section and to the same depth as the template shows. Deeper bullets are not numbered — the review UI numbers them by position (the first bullet under 1.1 is 1.1.1), so an explicit number there would clash. This is what lets a comment say which bullet it is about. - Cross-reference by number, e.g.
(Flow 1.2)or(1.1.2). Links such as[x](#slug)do not work: GitHub gives headings noidinside a comment, so there is nothing to point at.
Finally
Print the file path and a short spoken summary. Do not paste the document back.
Offer to post it as a PR comment. If the user agrees, post a new comment — never edit an
existing one, because editing discards any checkboxes they have already ticked. Their ticks can be
recovered from userContentEdits in the GraphQL API, but only before the history is trimmed.
Trending
Quiet this year.about the whole repository
Who's talking about OpenMined/PySyft
- A Hacker News story“Jupyter Notebook Tutorial – Privacy-Preserving Deep Learning in PyTorch”Hacker News · Dec 4, 2018 · 218 points
- A Hacker News story“Show HN: Encrypted Deep Learning in PyTorch”Hacker News · Oct 23, 2018 · 37 points
- A Hacker News story“Beginner Tutorial: Privacy Preserving, Decentralized Deep Learning in PyTorch”Hacker News · Nov 22, 2018 · 11 points
- udacity/private-ai“Modification in readme for pysyft installation”GitHub · May 30, 2019 · 8 reactions
- protocolbuffers/protobuf“Protobufs creation is slow when using nested objects compared to using bytes”GitHub · May 5, 2021 · 3 reactions
The biggest 5 of 62 mentions linking to the repository that our crawl found. Each line is their own headline.
See all 62
Talked about on GitHub, Hacker News, Stack Overflow and the web (62 times).
On GitHub · 50
- May 30, 2019Modification in readme for pysyft installation — udacity/private-ai8 reactions
- May 5, 2021Protobufs creation is slow when using nested objects compared to using bytes — protocolbuffers/protobuf3 reactions · 3 comments
- May 16, 2019PySyft Integration — tf-encrypted/tf-encrypted3 reactions · 1 comment
- Oct 18, 2021FOI: OpenMined for federated data analysis — datalad/datalad2 reactions · 1 comment
- Apr 29, 2021Add implementation of Max / Argmax — OpenMined/SyMPC2 reactions
45 more on GitHub
- Apr 18, 2020Jupyter Notebooks examples and tutorials to not work with docker-compose — OpenMined/PyGrid-deprecated---see-PySyft-2 reactions · 15 comments
- Apr 4, 2020Add Sentiment Classifier Training Usecase — OpenMined/SyferText2 reactions · 1 comment
- Oct 13, 2019Relay setup.py logic to a setup.cfg — OpenMined/PyGrid-deprecated---see-PySyft-2 reactions · 3 comments
- Jul 5, 2022ERROR: syft from git+http://github.com/OpenMined/PySyft@dev#egg=syft does not appear to be a Python project: neither 'setup.py' nor 'pyproject.toml' found. — OpenMined/courses1 reaction · 3 comments
- Jun 7, 2021poetry install at `PyGrid/apps/domain` does not work... — OpenMined/PyGrid-deprecated---see-PySyft-1 reaction · 3 comments
- Jul 13, 2020Enforcing type checking in SyferText — OpenMined/SyferText1 reaction · 2 comments
- Mar 27, 2020Torchscript field in Plan — OpenMined/syft-proto1 reaction
- Mar 12, 2020PyGrid integration — OpenMined/syft.js1 reaction · 1 comment
- Feb 5, 2020Migrate PyGrid from Travis to Github Actions — OpenMined/PyGrid-deprecated---see-PySyft-1 reaction
- Feb 3, 2020Allow PyGrid to serve plan operations as either a list of individual commands (syft.js) or as TorchScript (Android and iOS) — OpenMined/PyGrid-deprecated---see-PySyft-1 reaction · 1 comment
- Feb 2, 2020Add "host_federated_training" method to PyGrid — OpenMined/PyGrid-deprecated---see-PySyft-1 reaction · 7 comments
- Dec 5, 2019(WIP) Add Protobuf schemas for existing PySyft messages and types — OpenMined/syft-proto1 reaction · 17 comments
- Jul 30, 2025docker.io/openmined/syft-backend — DaoCloud/public-image-mirror0 reactions · 1 comment
- Jan 7, 2025Daily Review: `OpenMined/PySyft` — hsiangjenli/star-to-review0 reactions
- Nov 5, 2024Bump syft from 0.9.3b1 to 0.9.3b2 — Smartappli/AIMER0 reactions · 1 comment
- Nov 1, 2024Add PySyft to rejection list — YunoHost/apps0 reactions · 4 comments
- Nov 1, 2024Bump syft from 0.9.2b7 to 0.9.3b1 — Smartappli/AIMER0 reactions · 1 comment
- Oct 30, 2024Bump syft from 0.9.2b7 to 0.9.2 — Smartappli/AIMER0 reactions · 2 comments
- Oct 16, 2024Bump syft from 0.9.2b5 to 0.9.2b7 — Smartappli/AIMER0 reactions
- Oct 14, 2024Bump syft from 0.9.2b5 to 0.9.2b6 — Smartappli/AIMER0 reactions · 1 comment
- Oct 7, 2024Bump syft from 0.9.2b2 to 0.9.2b5 — Smartappli/AIMER0 reactions · 1 comment
- Oct 4, 2024Bump syft from 0.9.2b2 to 0.9.2b4 — Smartappli/AIMER0 reactions · 2 comments
- Sep 16, 2024Bump syft from 0.9.2b2 to 0.9.2b3 — Smartappli/AIMER0 reactions · 2 comments
- Sep 16, 2024Bump syft from 0.9.2b2 to 0.9.2b3 — Smartappli/AIMER20 reactions · 3 comments
- Sep 9, 2024Bump syft from 0.9.2b1 to 0.9.2b2 — Smartappli/AIMER0 reactions · 1 comment
- Sep 9, 2024Bump syft from 0.9.2b1 to 0.9.2b2 — Smartappli/AIMER20 reactions · 3 comments
- Sep 5, 2024Bump syft from 0.9.1b10 to 0.9.2b1 — Smartappli/AIMER0 reactions · 1 comment
- Sep 4, 2024Bump syft from 0.9.1b10 to 0.9.1 — Smartappli/AIMER0 reactions · 2 comments
- Sep 3, 2024Bump syft from 0.9.1b8 to 0.9.1b10 — Smartappli/AIMER0 reactions · 1 comment
- Aug 26, 2024Bump syft from 0.9.1b5 to 0.9.1b6 — Smartappli/AIMER0 reactions · 1 comment
- Aug 20, 2024Bump syft from 0.9.1b4 to 0.9.1b5 — Smartappli/AIMER0 reactions · 1 comment
- Apr 2, 2024Bump syft from 0.8.5.post1 to 0.8.5.post2 — Smartappli/AIMER0 reactions · 1 comment
- Mar 29, 2024Bump syft from 0.8.5 to 0.8.5.post1 — Smartappli/AIMER0 reactions · 1 comment
- Mar 29, 2024Added OpenMined PySyft — google/season-of-docs0 reactions
- Mar 22, 2024Bump syft from 0.8.5b9 to 0.8.6b1 — Smartappli/AIMER0 reactions · 1 comment
- Mar 21, 2024Bump syft from 0.8.5b9 to 0.8.5b10 — Smartappli/AIMER0 reactions · 2 comments
- Mar 14, 2024Bump syft from 0.8.5b5 to 0.8.5b6 — Smartappli/AIMER0 reactions · 1 comment
- Mar 14, 2024Bump syft from 0.8.5b2 to 0.8.5b4 — Smartappli/AIMER0 reactions · 1 comment
- Mar 13, 2024Bump syft from 0.8.5b1 to 0.8.5b2 — Smartappli/AIMER0 reactions · 2 comments
- Feb 19, 2024Bump syft from 0.8.4b28 to 0.8.4b30 — Smartappli/AIMER0 reactions
- Feb 16, 2024Bump syft from 0.8.4b23 to 0.8.4b28 — Smartappli/AIMER0 reactions
- Feb 15, 2024Bump syft from 0.8.4b23 to 0.8.4b27 — Smartappli/AIMER0 reactions · 1 comment
- Feb 12, 2024Bump syft from 0.8.4b21 to 0.8.4b22 — Smartappli/AIMER0 reactions
- Feb 8, 2024Bump syft from 0.8.4b19 to 0.8.4b21 — Smartappli/AIMER0 reactions
- Feb 2, 2024Bump syft from 0.8.4b15 to 0.8.4b19 — Smartappli/AIMER0 reactions
On Hacker News · 6
- Dec 4, 2018Jupyter Notebook Tutorial – Privacy-Preserving Deep Learning in PyTorch218 points · 5 comments
- Oct 23, 2018Show HN: Encrypted Deep Learning in PyTorch37 points
- Nov 22, 2018Beginner Tutorial: Privacy Preserving, Decentralized Deep Learning in PyTorch11 points
- Feb 21, 2020Jupyter Tutorial – Privacy-Preserving Deep Learning in PyTorch – Now Translated2 points
- Nov 23, 2018PySyft Step-By-Step Tutorial2 points
1 more on Hacker News
- Oct 24, 2017OpenMined/PySyft: Encrypted Deep Learning Library2 points
On Stack Overflow · 3
- Feb 19, 2020Pysyft Federated learning, Error with Websockets1 vote
- Feb 13, 2020Pysyft Federated learning, Error with Websockets1 vote · 1 answer
- Mar 10, 2021Error Launching Blob Trigger function in Azure Functions expected str, bytes or os.PathLike object, not PosixPath0 votes · 1 answer
On the web · 3
- May 9, 2022FL use Pysyft 0.6.0 · Issue #6467 — google.com
- Dec 18, 2021Need credentials of PyGrid admin UI · Issue #6235 — google.com
- Sep 2, 2020How to run pysyft-notebook docker image with ... — google.com
In this repository2 other files it gives its agents.
- syft-pr-quickfix-iterateSkill
- syft-pr-quickfixSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

