Review at scale¶
The conclusion first¶
Reviewing agent output line by line does not scale. Reviewing its structure does. explain
is the half of this tool that produces the structure, and it is the only command that never
blocks anything.
check answers "is this allowed". explain answers "what did this do to the shape of the
code" — for a human before they open a file, or for an agent that needs to know what its own
change touched.
The change summary¶
$ scitools-hook explain --staged
change summary
database: /home/you/.cache/scitools-hook/e7cde7af638ed147/after.und
files (1)
pricing/settle.py [Directory Structure/pricing]
added file pricing/settle.py
CountDeclFunction - -> 1 (+1)
CountLineCode - -> 35 (+35)
MaxCyclomaticStrict - -> 14 (+14)
RatioCommentToCode - -> 0.06 (+0.06)
added routine pricing.settle.settle line 6
CountLineCode - -> 34 (+34)
CountParams - -> 5 (+5)
CountPath - -> 44 (+44)
CountStmt - -> 25 (+25)
CyclomaticModified - -> 13 (+13)
CyclomaticStrict - -> 14 (+14)
Essential - -> 1 (+1)
MaxNesting - -> 4 (+4)
dependencies (1)
Directory Structure/pricing
added pricing/settle.py -> pricing/rates.py
largest deltas (10)
1. pricing.settle.settle (pricing/settle.py) CountPath - -> 44 (+44)
2. pricing/settle.py CountLineCode - -> 35 (+35)
3. pricing.settle.settle (pricing/settle.py) CountLineCode - -> 34 (+34)
4. pricing.settle.settle (pricing/settle.py) CountStmt - -> 25 (+25)
5. pricing/settle.py MaxCyclomaticStrict - -> 14 (+14)
6. pricing.settle.settle (pricing/settle.py) CyclomaticStrict - -> 14 (+14)
7. pricing.settle.settle (pricing/settle.py) CyclomaticModified - -> 13 (+13)
8. pricing.settle.settle (pricing/settle.py) CountParams - -> 5 (+5)
9. pricing.settle.settle (pricing/settle.py) MaxNesting - -> 4 (+4)
10. pricing/settle.py CountDeclFunction - -> 1 (+1)
largest values (10)
1. pricing.settle.settle (pricing/settle.py) CountPath 44
2. pricing/settle.py CountLineCode 35
3. pricing.settle.settle (pricing/settle.py) CountLineCode 34
...
impact (0)
none
graphs (0)
none
open in the Understand GUI: understand /home/you/.cache/scitools-hook/e7cde7af638ed147/after.und
Every entity is labelled added, modified or deleted, with the architecture node it sits
in. largest deltas is what to read first on a change you did not write: it is the list of
what moved most, ordered, regardless of whether anything broke a rule.
The last line is a command you can paste. It opens the exact database the report was built from, in the Understand GUI, so a reviewer who wants to keep digging does not have to reproduce the analysis.
Selections¶
| Flag | Analyses |
|---|---|
--staged |
The index, against HEAD. What the hook runs. |
--worktree |
The working tree, staged or not. What an agent runs while editing. |
--all |
The whole project. No before side, so no ratchet and no pre-existing. |
--files PATH |
Exactly these paths. Repeatable. Bare trailing paths mean the same thing. |
--range A..B |
What happened between two commits. explain only. |
--range is the pull-request form:
Graphs and the impact set¶
$ scitools-hook explain --range HEAD~1..HEAD --graphs --impact --out review/
impact (4)
pricing.settle.goods_line (pricing/settle.py) 2 total; depth 1: 1, depth 2: 1
pricing.settle.line_total (pricing/settle.py) 1 total; depth 1: 1
pricing.settle.service_line (pricing/settle.py) 2 total; depth 1: 1, depth 2: 1
pricing.settle.settle (pricing/settle.py) 0 total
graphs (5)
Depends On pricing/settle.py review/pricing_settle_py-ccbe74db8212-Depends_On.svg
Butterfly pricing.settle.goods_line (pricing/settle.py) review/pricing_settle_goods_line-6fa67e526589-Butterfly.svg
Butterfly pricing.settle.line_total (pricing/settle.py) review/pricing_settle_line_total-0f12cee419a5-Butterfly.svg
Butterfly pricing.settle.service_line (pricing/settle.py) review/pricing_settle_service_line-106fff5a5eb7-Butterfly.svg
Butterfly pricing.settle.settle (pricing/settle.py) review/pricing_settle_settle-9cd08e5b4901-Butterfly.svg
--out DIR without --graphs is refused rather than ignored.
What a butterfly graph is¶
One graph per changed routine or class: what calls it on the left, what it calls on the
right. This is review/pricing_settle_line_total-0f12cee419a5-Butterfly.svg, exactly as
Understand rendered it:
settle calls line_total, which calls goods_line and service_line. On a repository the
size of one you would actually review, this is the picture that tells you whether a change
sits at a leaf or in the middle of everything.
Two kinds are exported, and only two, because they are the two Understand 6.5 will actually render for the entities in question:
| Kind | Drawn for |
|---|---|
Butterfly |
each affected routine and class |
Depends On |
each affected file |
A routine draws Butterfly, Calls and Called By, and refuses Depends On with
UnderstandError('Unknown Graph') while writing no file. A refused graph is a warning, not a
failure: one target the installed Understand will not render must not cost the reviewer every
other graph.
File names are <slug of the long name>-<12 hex of the key digest>-<slug of the graph>.svg.
Neither part can contain a path separator, which is what confines the export to the directory
you chose.
The impact set¶
--impact lists what references each changed routine and class, by depth:
One entity references it directly and one more at two hops. The depth is
output.impact_depth, default 3. An entity is reported at the shallowest depth that reaches
it and never again, and the entity the walk started from is never part of its own impact set
— reference graphs are full of cycles.
depth = 0 is a legal answer meaning "report nothing".
Sizing¶
[output]
graphs_max = 20 # per group: routines/classes, and files, counted separately
impact_depth = 3
show_highest = false
graphs_max is applied to each group on its own. Leaving the files unbounded would let a
whole-project run draw one graph per file in the repository. Zero draws nothing and opens no
database at all.
Output formats¶
scitools-hook explain --staged --format markdown --output review.md
scitools-hook explain --staged --format json | jq '.largest_deltas[0]'
human, json and markdown. The markdown form is the one to paste into a pull request.
A reviewing workflow¶
For a large agent-authored branch:
# 1. What moved, structurally, and by how much.
scitools-hook explain --range "origin/main...HEAD" --format markdown --output review.md
# 2. The pictures, for the parts of it that look load-bearing.
scitools-hook explain --range "origin/main...HEAD" --graphs --impact --out review/
# 3. Whether any of it broke a rule, or made an existing problem worse.
scitools-hook check --files $(git diff --name-only origin/main...HEAD)
# 4. Open the database and keep digging, if step 2 raised a question.
understand "$(scitools-hook db path)"
Read the shape first. Open files second, and only the ones the shape made interesting.