pi-visualize-code-changes 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +108 -0
- package/package.json +42 -0
- package/preview.png +0 -0
- package/skills/visualize-code-changes/SKILL.md +331 -0
- package/skills/visualize-code-changes/assets/template.md +71 -0
- package/skills/visualize-code-changes/references/diagram-types.md +340 -0
- package/skills/visualize-code-changes/references/syntax-pitfalls.md +191 -0
- package/skills/visualize-code-changes/scripts/validate_mermaid.py +576 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BlockedPath
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# pi-visualize-code-changes
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Pi skill that turns a code change into **before / after / what-changed** Mermaid diagrams — so reviewers see behaviour, not just hunks.
|
|
6
|
+
|
|
7
|
+
Installable as a [Pi package](https://pi.dev/packages). Works with any Agent Skills harness that loads `SKILL.md`.
|
|
8
|
+
|
|
9
|
+
## Install (Pi)
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pi install npm:pi-visualize-code-changes
|
|
13
|
+
|
|
14
|
+
# Recommended: structured lens prompts (ask_user_question)
|
|
15
|
+
pi install npm:@juicesharp/rpiv-ask-user-question
|
|
16
|
+
|
|
17
|
+
# or from git:
|
|
18
|
+
# pi install git:github.com/BlockedPath/pi-visualize-code-changes
|
|
19
|
+
# or local path while developing:
|
|
20
|
+
# pi install /Users/justin/dev/pi-visualize-code-changes
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Without the ask-user extension the skill still works — it just picks a lens
|
|
24
|
+
itself instead of offering a short questionnaire when `--lens` is omitted.
|
|
25
|
+
|
|
26
|
+
Then in a Pi session:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
/skill:visualize-code-changes
|
|
30
|
+
/skill:visualize-code-changes uncommitted
|
|
31
|
+
/skill:visualize-code-changes pr 42 --lens sequence
|
|
32
|
+
/skill:visualize-code-changes main...HEAD --focus src/auth --out docs/diagrams/auth.md
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## What it produces
|
|
36
|
+
|
|
37
|
+
One Markdown file (default `docs/diagrams/<slug>.md`) with:
|
|
38
|
+
|
|
39
|
+
1. **Before** — how the flow worked
|
|
40
|
+
2. **After** — how it works now
|
|
41
|
+
3. **What changed** — merged, colour-coded diff view (added / removed / changed / same)
|
|
42
|
+
|
|
43
|
+
GitHub and GitLab render the Mermaid blocks natively.
|
|
44
|
+
|
|
45
|
+
## Arguments
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
[scope] [--lens TYPE] [--focus PATH]... [--out PATH] [--slug NAME] [--render]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
| Token | Meaning |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| `scope` | `uncommitted`, `staged`, `pr <n>`, `branch <name>`, `main...HEAD`, `<sha>`, … |
|
|
54
|
+
| `--lens` | `control-flow`, `dependency`, `sequence`, `state`, `data-flow` |
|
|
55
|
+
| `--focus` | Limit deep-read/diagram to path(s) |
|
|
56
|
+
| `--out` / `--slug` | Output path control |
|
|
57
|
+
| `--render` | Also emit SVGs (needs mermaid-cli) |
|
|
58
|
+
|
|
59
|
+
## Requirements
|
|
60
|
+
|
|
61
|
+
No npm runtime dependencies — this package is a skill (Markdown + one stdlib Python script).
|
|
62
|
+
|
|
63
|
+
| Need | Required? |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| Pi (or another Agent Skills host) | Yes |
|
|
66
|
+
| Git | Typical — diff discovery (`git diff`, `git show`, ranges). Session-edited files still work without it |
|
|
67
|
+
| [`@juicesharp/rpiv-ask-user-question`](https://www.npmjs.com/package/@juicesharp/rpiv-ask-user-question) (or any host tool that exposes `ask_user_question` / `AskUserQuestion`) | **Recommended** — interactive lens choice when `--lens` is omitted. Without it, the skill auto-picks |
|
|
68
|
+
| Python 3 | For diagram validation only (stdlib; no pip deps) |
|
|
69
|
+
| [`gh`](https://cli.github.com/) (GitHub CLI) | Only for `pr <n>` scope (`gh pr diff`). Other scopes use git alone |
|
|
70
|
+
| [`@mermaid-js/mermaid-cli`](https://github.com/mermaid-js/mermaid-cli) (`mmdc`) + Chrome/Chromium | **Optional** — authoritative validation and `--render` SVGs. Without it, validation falls back to built-in heuristics |
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# recommended — lens questionnaire
|
|
74
|
+
pi install npm:@juicesharp/rpiv-ask-user-question
|
|
75
|
+
|
|
76
|
+
# optional — PR scope
|
|
77
|
+
# brew install gh # or see https://cli.github.com/
|
|
78
|
+
|
|
79
|
+
# optional but recommended — stronger Mermaid validation / SVG render
|
|
80
|
+
npm i -g @mermaid-js/mermaid-cli
|
|
81
|
+
# mmdc needs a Chrome/Chromium on PATH (or Puppeteer's bundled browser)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Package layout
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
pi-visualize-code-changes/
|
|
88
|
+
├── package.json # pi.skills → ./skills
|
|
89
|
+
└── skills/
|
|
90
|
+
└── visualize-code-changes/
|
|
91
|
+
├── SKILL.md
|
|
92
|
+
├── assets/template.md
|
|
93
|
+
├── references/
|
|
94
|
+
└── scripts/validate_mermaid.py
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Development
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# try without publishing
|
|
101
|
+
pi install /absolute/path/to/pi-visualize-code-changes
|
|
102
|
+
# or one-shot
|
|
103
|
+
pi -e /absolute/path/to/pi-visualize-code-changes
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-visualize-code-changes",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Pi skill: Mermaid before/after/diff diagrams that explain what a code change actually does",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"pi-package",
|
|
7
|
+
"pi-skill",
|
|
8
|
+
"pi",
|
|
9
|
+
"mermaid",
|
|
10
|
+
"diagrams",
|
|
11
|
+
"code-review",
|
|
12
|
+
"refactor",
|
|
13
|
+
"diff",
|
|
14
|
+
"visualization"
|
|
15
|
+
],
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"author": "BlockedPath",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"files": [
|
|
20
|
+
"skills",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE",
|
|
23
|
+
"preview.png"
|
|
24
|
+
],
|
|
25
|
+
"pi": {
|
|
26
|
+
"skills": [
|
|
27
|
+
"./skills"
|
|
28
|
+
],
|
|
29
|
+
"image": "https://raw.githubusercontent.com/BlockedPath/pi-visualize-code-changes/main/preview.png"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18"
|
|
33
|
+
},
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/BlockedPath/pi-visualize-code-changes.git"
|
|
37
|
+
},
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/BlockedPath/pi-visualize-code-changes/issues"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/BlockedPath/pi-visualize-code-changes#readme"
|
|
42
|
+
}
|
package/preview.png
ADDED
|
Binary file
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: visualize-code-changes
|
|
3
|
+
description: >
|
|
4
|
+
Generate Mermaid diagrams of how code worked BEFORE a change, how it works AFTER,
|
|
5
|
+
and a merged colour-coded diff view showing exactly what moved — written to a
|
|
6
|
+
Markdown file that renders natively on GitHub. Use this whenever someone wants to
|
|
7
|
+
see, picture, visualise, map, or "actually understand" a code change rather than
|
|
8
|
+
read its diff: after finishing a refactor, when reviewing a PR or branch, when
|
|
9
|
+
onboarding someone onto unfamiliar code, or when a diff is too large or too
|
|
10
|
+
scattered to hold in your head. Trigger it for phrases like "diagram this",
|
|
11
|
+
"show me what changed", "visualise this refactor", "draw the flow", "help me
|
|
12
|
+
grasp this PR", "what did this change actually do", or any request for a
|
|
13
|
+
flowchart, sequence diagram, call graph, or architecture picture of code —
|
|
14
|
+
even when Mermaid is never mentioned by name.
|
|
15
|
+
argument-hint: "[scope] [--lens TYPE] [--focus PATH]... [--out PATH] [--render]"
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# Visualize code changes
|
|
19
|
+
|
|
20
|
+
A diff tells you which *lines* changed. It does not tell you what the code now
|
|
21
|
+
*does* differently — that has to be reconstructed in the reader's head, which is
|
|
22
|
+
exactly the expensive part. These diagrams do that reconstruction once, on paper,
|
|
23
|
+
so nobody has to redo it.
|
|
24
|
+
|
|
25
|
+
The output is one Markdown file holding three diagrams: **Before**, **After**, and
|
|
26
|
+
**What changed** (a merged, colour-coded view). The third is the one people
|
|
27
|
+
actually look at; the first two exist to make it trustworthy.
|
|
28
|
+
|
|
29
|
+
## Arguments
|
|
30
|
+
|
|
31
|
+
Slash-command invocations can pass arguments. How they arrive depends on the harness:
|
|
32
|
+
|
|
33
|
+
| Harness | How args show up |
|
|
34
|
+
|---|---|
|
|
35
|
+
| Claude Code | `$ARGUMENTS` is substituted below (also `$0`, `$1`, … by position) |
|
|
36
|
+
| Pi | Appended after the skill body as plain text (not substituted) |
|
|
37
|
+
| Plain chat | Treat the user's message as the args / request |
|
|
38
|
+
|
|
39
|
+
**Invoked arguments:** `$ARGUMENTS`
|
|
40
|
+
|
|
41
|
+
If that line is empty, missing, or still the literal `$ARGUMENTS`, check for a
|
|
42
|
+
trailing freeform args block after the skill (Pi). If neither is present, there
|
|
43
|
+
were no slash args — fall through to normal discovery in step 1.
|
|
44
|
+
|
|
45
|
+
### Grammar
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
[scope] [--lens TYPE] [--focus PATH]... [--out PATH] [--slug NAME] [--render]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
All tokens are optional. Flags may appear in any order. Unknown tokens that look
|
|
52
|
+
like paths become extra `--focus` entries; other free text is treated as scope.
|
|
53
|
+
|
|
54
|
+
| Token | Meaning |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `scope` | What to diagram. See scope forms below. |
|
|
57
|
+
| `--lens TYPE` | Skip the lens prompt. One of: `control-flow`, `dependency`, `sequence`, `state`, `data-flow` (aliases: `flow`, `deps`, `seq`). |
|
|
58
|
+
| `--focus PATH` | Limit the diagram to this file/dir (repeatable). Still read callers/callees one hop out for context. |
|
|
59
|
+
| `--out PATH` | Write the markdown here instead of `docs/diagrams/<slug>.md`. |
|
|
60
|
+
| `--slug NAME` | Filename slug when `--out` is omitted (default: derive from branch/PR/files). |
|
|
61
|
+
| `--render` | After validation, also write SVGs via `validate_mermaid.py --render-to <dir>` next to the markdown (or `docs/diagrams/render/`). |
|
|
62
|
+
|
|
63
|
+
**Scope forms** (first positional token(s)):
|
|
64
|
+
|
|
65
|
+
| Form | Resolves to |
|
|
66
|
+
|---|---|
|
|
67
|
+
| *(omitted)* | Discover from context: uncommitted → staged → current branch vs main/master |
|
|
68
|
+
| `uncommitted` / `working` | `git diff` + `git diff --staged` |
|
|
69
|
+
| `staged` | `git diff --staged` only |
|
|
70
|
+
| `pr <n>` / `PR #<n>` / `#<n>` | `gh pr diff <n>` (fallback: `git diff main...FETCH_HEAD` after `gh pr checkout` metadata) |
|
|
71
|
+
| `branch <name>` | `git diff main...<name>` (or `master` if that is the default) |
|
|
72
|
+
| `<base>...<head>` | Exact `git diff` range (three-dot preferred for PRs) |
|
|
73
|
+
| `<base>..<head>` | Two-dot range when explicitly given |
|
|
74
|
+
| `<sha>` / `<sha>..<sha>` | `git show` / `git diff` on that commit or range |
|
|
75
|
+
| `HEAD` / `HEAD~N` | That commit against its parent(s) |
|
|
76
|
+
|
|
77
|
+
### Examples
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
/skill:visualize-code-changes
|
|
81
|
+
/skill:visualize-code-changes uncommitted
|
|
82
|
+
/skill:visualize-code-changes pr 42
|
|
83
|
+
/skill:visualize-code-changes main...HEAD --lens sequence
|
|
84
|
+
/skill:visualize-code-changes branch feature/auth --focus src/auth --out docs/diagrams/auth-rewrite.md
|
|
85
|
+
/skill:visualize-code-changes abc1234 --lens control-flow --render
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Claude Code also accepts `/visualize-code-changes` with the same args.
|
|
89
|
+
|
|
90
|
+
### Parsing rules
|
|
91
|
+
|
|
92
|
+
1. Apply args **before** step 1 of the workflow. They pin scope/lens/output; do not re-ask for something already specified.
|
|
93
|
+
|
|
94
|
+
2. If `--lens` is set, skip the lens question in step 3 and state the chosen lens in one line.
|
|
95
|
+
|
|
96
|
+
3. If `--focus` is set, still run `git diff --stat` on the full scope, but only deep-read and diagram the focused paths (plus one hop of callers/callees). Mention omitted files briefly in the doc Notes.
|
|
97
|
+
|
|
98
|
+
4. If scope is a PR or range and git/gh fails, say so and stop — do not silently diagram the working tree instead.
|
|
99
|
+
|
|
100
|
+
5. Shell-style quoting applies when the harness splits args (`--out "docs/my diagrams/auth.md"`). On Pi, the trailing args block is one string — parse flags with simple tokenization (split on spaces, respect double quotes).
|
|
101
|
+
|
|
102
|
+
## Workflow
|
|
103
|
+
|
|
104
|
+
### 1. Pin down what you're diagramming
|
|
105
|
+
|
|
106
|
+
If Arguments already pinned a scope, use that and skip discovery. Otherwise
|
|
107
|
+
establish the exact change set before drawing anything:
|
|
108
|
+
|
|
109
|
+
| Situation | Command |
|
|
110
|
+
|---|---|
|
|
111
|
+
| Work you just did / uncommitted | `git diff` and `git diff --staged` |
|
|
112
|
+
| A branch or PR | `git diff main...HEAD`, or `gh pr diff <n>` |
|
|
113
|
+
| A specific commit | `git show <sha>` |
|
|
114
|
+
| Not a git repo, or changes made in-session | Use your own record of what you edited |
|
|
115
|
+
|
|
116
|
+
Start with `git diff --stat` to see the shape of the change before reading hunks.
|
|
117
|
+
If the change spans many files, that stat output tells you which two or three
|
|
118
|
+
files carry the actual behaviour — diagram those, not all of them (unless
|
|
119
|
+
`--focus` already chose).
|
|
120
|
+
|
|
121
|
+
### 2. Read both sides, not just the diff
|
|
122
|
+
|
|
123
|
+
This is the step that gets skipped, and skipping it produces confidently wrong
|
|
124
|
+
diagrams. A diff hunk shows changed lines stripped of the surrounding logic, so
|
|
125
|
+
you cannot see the control flow the diagram needs to depict.
|
|
126
|
+
|
|
127
|
+
Read the real *before* state:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
git show HEAD:path/to/file.py # before, uncommitted work
|
|
131
|
+
git show main:path/to/file.py # before, branch work
|
|
132
|
+
git show <base-sha>:path/to/file.py # before, explicit range
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
and read the current file for the *after* state. Two distinctions matter because
|
|
136
|
+
a naive diff reading gets both backwards:
|
|
137
|
+
|
|
138
|
+
- **Moved ≠ rewritten.** A function relocated to another module shows up as a big
|
|
139
|
+
delete plus a big add. Behaviour is unchanged; the diagram should say *moved*,
|
|
140
|
+
not invent a new code path.
|
|
141
|
+
- **Renamed ≠ replaced.** `checkPassword` → `verifyCredentials` with the same body
|
|
142
|
+
is one node with a new name, not a removal and an addition.
|
|
143
|
+
|
|
144
|
+
If a file is newly added there is no before state, and if deleted there is no
|
|
145
|
+
after — say so in the document rather than fabricating a diagram.
|
|
146
|
+
|
|
147
|
+
### 3. Choose the lens
|
|
148
|
+
|
|
149
|
+
Different changes are legible through different diagram types. If `--lens` was
|
|
150
|
+
passed in Arguments, use it and skip asking. Otherwise, if an
|
|
151
|
+
`AskUserQuestion` / `ask_user_question` tool is available, offer the choice — the user usually knows
|
|
152
|
+
which view they want, and asking costs one turn.
|
|
153
|
+
On Pi, install that tool with:
|
|
154
|
+
`pi install npm:@juicesharp/rpiv-ask-user-question`.
|
|
155
|
+
Claude Code exposes `AskUserQuestion` built-in.
|
|
156
|
+
Other hosts may ship an equivalent under a different package name.
|
|
157
|
+
|
|
158
|
+
- Recommend the row below that best fits the change, marked as recommended
|
|
159
|
+
- Offer the plausible alternatives, not all five
|
|
160
|
+
|
|
161
|
+
When that tool isn't available, pick using this mapping and state your choice:
|
|
162
|
+
|
|
163
|
+
| The change is about… | Use | Mermaid type |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| Logic, branching, error paths | Control flow | `flowchart TD` |
|
|
166
|
+
| Moving code between files/modules/layers | Dependency graph | `flowchart LR` |
|
|
167
|
+
| A request path, API call, or service hop | Sequence | `sequenceDiagram` |
|
|
168
|
+
| Status/lifecycle transitions | State machine | `stateDiagram-v2` |
|
|
169
|
+
| How data is shaped and passed along | Data flow | `flowchart LR` |
|
|
170
|
+
|
|
171
|
+
For anything beyond a basic flowchart, read `references/diagram-types.md` for the
|
|
172
|
+
syntax recipe and worked examples.
|
|
173
|
+
|
|
174
|
+
### 4. Find the right altitude
|
|
175
|
+
|
|
176
|
+
Altitude is what separates a diagram that helps from one that gets glanced at and
|
|
177
|
+
closed. Two failure modes, equally common:
|
|
178
|
+
|
|
179
|
+
- **Too low** — a node per statement or per function call. Reproduces the code
|
|
180
|
+
without compressing it, so it costs as much to read as the source did.
|
|
181
|
+
- **Too high** — three boxes saying `Input → Process → Output`. True of every
|
|
182
|
+
program ever written, therefore worthless.
|
|
183
|
+
|
|
184
|
+
The rule that lands in the right place: **one node per step you would name if you
|
|
185
|
+
explained this code aloud to a colleague.** That is roughly a decision, an
|
|
186
|
+
externally-visible effect (network, disk, database, queue), or a meaningful
|
|
187
|
+
transformation. Plumbing — getters, logging, type conversion, argument shuffling
|
|
188
|
+
— belongs inside a node, not as its own.
|
|
189
|
+
|
|
190
|
+
Aim for **5–15 nodes**. Past that, either raise the altitude or group with
|
|
191
|
+
`subgraph`. And scope the picture to **the region the change touches plus one hop
|
|
192
|
+
of context** on either side; redrawing an entire module because three lines moved
|
|
193
|
+
buries the signal you were hired to surface.
|
|
194
|
+
|
|
195
|
+
Every node must map to code that genuinely exists. A diagram is read as
|
|
196
|
+
authoritative, so an invented branch is worse than an omitted one — when a path is
|
|
197
|
+
unclear, go read it rather than guessing.
|
|
198
|
+
|
|
199
|
+
### 5. Write the three diagrams
|
|
200
|
+
|
|
201
|
+
Write to `--out` if given, else `docs/diagrams/<slug>.md` where `<slug>` comes
|
|
202
|
+
from `--slug` or is derived from the branch/PR/files — or alongside existing docs
|
|
203
|
+
if the repo keeps them elsewhere. Follow `assets/template.md` for the structure.
|
|
204
|
+
|
|
205
|
+
Keep the diagrams as fenced ` ```mermaid ` source rather than exporting images.
|
|
206
|
+
GitHub, GitLab, and most Markdown viewers render those blocks natively, and source
|
|
207
|
+
stays greppable and reviewable in future diffs — an exported PNG goes stale the
|
|
208
|
+
moment the code moves on.
|
|
209
|
+
|
|
210
|
+
Lead the file with two or three sentences of plain prose on what the change
|
|
211
|
+
accomplishes. Someone skimming should get the point without decoding a diagram.
|
|
212
|
+
|
|
213
|
+
**The diff view** is a single merged graph containing before and after, with each
|
|
214
|
+
node and edge marked by its fate:
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
classDef added fill:#d4f8d4,stroke:#2ea043,color:#1f2328
|
|
218
|
+
classDef removed fill:#ffd7d5,stroke:#cf222e,color:#1f2328
|
|
219
|
+
classDef changed fill:#fff5cc,stroke:#bf8700,color:#1f2328
|
|
220
|
+
classDef same fill:#f6f8fa,stroke:#8c959f,color:#1f2328
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Apply with `NodeId:::added`. Always set `color:` explicitly — without it, dark-mode
|
|
224
|
+
readers get dark text on a light fill and the diagram is unreadable for them.
|
|
225
|
+
|
|
226
|
+
Edges change too, and a graph that only colours nodes hides half the story. Show
|
|
227
|
+
removed edges as dotted (`-.->`) and style them by index with
|
|
228
|
+
`linkStyle N stroke:#cf222e` (indices are 0-based in declaration order).
|
|
229
|
+
|
|
230
|
+
Include a short legend so the colours don't need explaining. If before and after
|
|
231
|
+
differ so structurally that the merged graph turns to spaghetti, fall back to two
|
|
232
|
+
`subgraph` blocks side by side and note why.
|
|
233
|
+
|
|
234
|
+
**When the change is mostly relocation**, colour alone under-delivers, because
|
|
235
|
+
every node is technically "removed here, added there" and the reader still can't
|
|
236
|
+
tell which parts need reviewing. Draw a *fate map* instead: old container on one
|
|
237
|
+
side, new containers on the other, one edge per unit labelled with what actually
|
|
238
|
+
happened to it — `moved verbatim`, `moved, 3 lines changed`, `deleted, not moved`.
|
|
239
|
+
That labels the provenance directly rather than asking the reader to infer it, and
|
|
240
|
+
it answers the question people actually have during a big refactor: what can I
|
|
241
|
+
skip? Verify those labels by diffing the extracted function bodies, not by reading
|
|
242
|
+
hunks — git reports a wholesale file replacement identically whether the code was
|
|
243
|
+
moved or rewritten, which is the single easiest way to mislead someone.
|
|
244
|
+
|
|
245
|
+
**A fourth diagram earns its place** when one unit holds essentially all the real
|
|
246
|
+
logic change. The overview answers "what moved"; it cannot answer "how does this
|
|
247
|
+
function behave differently now". Giving that one function its own control-flow
|
|
248
|
+
diagram, clearly marked as a zoom, costs little and is usually where the review
|
|
249
|
+
actually happens. Resist adding a fourth that re-answers a question the first
|
|
250
|
+
three already covered — that is padding, and it dilutes the ones that matter.
|
|
251
|
+
|
|
252
|
+
### 6. Validate before handing it over
|
|
253
|
+
|
|
254
|
+
A diagram that doesn't parse renders as a red error box — worse than no diagram,
|
|
255
|
+
because it looks like something went wrong with the repo. Always run:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
python3 <skill-dir>/scripts/validate_mermaid.py docs/diagrams/<file>.md
|
|
259
|
+
# with --render:
|
|
260
|
+
python3 <skill-dir>/scripts/validate_mermaid.py --render-to <dir> docs/diagrams/<file>.md
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
It parses every block with `mermaid-cli` when available and falls back to built-in
|
|
264
|
+
heuristics otherwise, reporting errors against real line numbers in your file.
|
|
265
|
+
Fix anything it flags and re-run until clean. It also catches style classes that
|
|
266
|
+
are used but never defined — those render without error but silently lose their
|
|
267
|
+
colour, which is exactly the kind of bug that survives a visual skim.
|
|
268
|
+
|
|
269
|
+
Always pass `--render-to` when Arguments included `--render`; also use it when
|
|
270
|
+
the user asks for images even without the flag.
|
|
271
|
+
|
|
272
|
+
## Syntax that will bite you
|
|
273
|
+
|
|
274
|
+
The overwhelmingly common break is **unquoted special characters in labels**.
|
|
275
|
+
Parentheses, brackets, and pipes terminate a label early:
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
A[login(req)] ← breaks the parser
|
|
279
|
+
A["login(req)"] ← correct
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Quote every label containing `()`, `[]`, `{}`, `|`, `:`, or `,` — quoting
|
|
283
|
+
defensively costs nothing. `references/syntax-pitfalls.md` covers the rest
|
|
284
|
+
(reserved words like `end`, subgraph IDs, arrow-label escaping).
|
|
285
|
+
|
|
286
|
+
## Worked example
|
|
287
|
+
|
|
288
|
+
A change that swapped password auth for token auth, at the right altitude:
|
|
289
|
+
|
|
290
|
+
```mermaid
|
|
291
|
+
flowchart TD
|
|
292
|
+
R["POST /login"]:::same --> V{"payload valid?"}:::same
|
|
293
|
+
V -->|no| E["400 invalid request"]:::same
|
|
294
|
+
V -->|yes| P["checkPassword(user, pw)"]:::removed
|
|
295
|
+
V -->|yes| T["verifyToken(jwt)"]:::added
|
|
296
|
+
P --> S["issueSession()"]:::changed
|
|
297
|
+
T --> S
|
|
298
|
+
S --> OK["200 + session cookie"]:::same
|
|
299
|
+
|
|
300
|
+
classDef added fill:#d4f8d4,stroke:#2ea043,color:#1f2328
|
|
301
|
+
classDef removed fill:#ffd7d5,stroke:#cf222e,color:#1f2328
|
|
302
|
+
classDef changed fill:#fff5cc,stroke:#bf8700,color:#1f2328
|
|
303
|
+
classDef same fill:#f6f8fa,stroke:#8c959f,color:#1f2328
|
|
304
|
+
linkStyle 2,4 stroke:#cf222e,stroke-dasharray:5
|
|
305
|
+
linkStyle 3 stroke:#2ea043
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Counting the links in declaration order: `0` R→V, `1` V→E, `2` V→P, `3` V→T,
|
|
309
|
+
`4` P→S, `5` T→S, `6` S→OK. So the dead password path is links 2 and 4, and the
|
|
310
|
+
new token path is link 3. Miscounting here is easy and silently mislabels the
|
|
311
|
+
change, so recount against the finished diagram before you ship it.
|
|
312
|
+
|
|
313
|
+
Seven nodes, and the change reads at a glance: the password branch is gone, a
|
|
314
|
+
token branch replaces it, session issuance was touched, and the surrounding
|
|
315
|
+
request handling is untouched. Note what is *absent* — request parsing, logging,
|
|
316
|
+
and DB connection handling all exist in the real code but would have added noise
|
|
317
|
+
without adding understanding.
|
|
318
|
+
|
|
319
|
+
## Finishing up
|
|
320
|
+
|
|
321
|
+
Report the file path and summarise the change in a sentence or two. If you had to
|
|
322
|
+
guess at any behaviour, say which parts and why — a reader who knows where the
|
|
323
|
+
soft spots are can trust the rest.
|
|
324
|
+
|
|
325
|
+
## Reference files
|
|
326
|
+
|
|
327
|
+
- `references/diagram-types.md` — picking a lens; syntax recipes for sequence,
|
|
328
|
+
state, class, and dependency diagrams
|
|
329
|
+
- `references/syntax-pitfalls.md` — escaping, reserved words, theme-safe styling
|
|
330
|
+
- `assets/template.md` — the output document skeleton
|
|
331
|
+
- `scripts/validate_mermaid.py` — the validator from step 6
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# <Change name> — before & after
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
Structure notes (delete this comment in the real document):
|
|
5
|
+
* Lead with prose. Someone skimming should understand the change without
|
|
6
|
+
decoding a diagram.
|
|
7
|
+
* Keep diagrams as ```mermaid source, not exported images — GitHub renders
|
|
8
|
+
them natively and the source stays reviewable in future diffs.
|
|
9
|
+
* The "What changed" diagram is the one people actually read. Before/After
|
|
10
|
+
exist to make it trustworthy.
|
|
11
|
+
-->
|
|
12
|
+
|
|
13
|
+
**Scope:** `<git ref, PR, or "uncommitted working tree">`
|
|
14
|
+
**Files:** `path/one.py`, `path/two.py`
|
|
15
|
+
|
|
16
|
+
<Two or three sentences: what this change accomplishes and why. Plain language,
|
|
17
|
+
no diagram vocabulary.>
|
|
18
|
+
|
|
19
|
+
<!--
|
|
20
|
+
For a change that touches several files -- especially a move or a split -- a
|
|
21
|
+
table like this is often the most useful thing in the document, because it tells
|
|
22
|
+
the reader where NOT to spend time. Drop it when only one file changed.
|
|
23
|
+
|
|
24
|
+
| File | What happened | Review effort |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `pkg/calculator.py` | moved byte-for-byte | none |
|
|
27
|
+
| `pkg/invoice.py` | moved, 3 lines changed | a minute |
|
|
28
|
+
| `pkg/tax.py` | rewritten from scratch | all of it |
|
|
29
|
+
-->
|
|
30
|
+
|
|
31
|
+
## Before
|
|
32
|
+
|
|
33
|
+
<One line naming the key property of the old design — usually the thing the
|
|
34
|
+
change was made to fix.>
|
|
35
|
+
|
|
36
|
+
```mermaid
|
|
37
|
+
flowchart TD
|
|
38
|
+
%% 5-15 nodes, scoped to the region the change touches plus one hop
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## After
|
|
42
|
+
|
|
43
|
+
<One line on what is structurally different now.>
|
|
44
|
+
|
|
45
|
+
```mermaid
|
|
46
|
+
flowchart TD
|
|
47
|
+
%% same altitude and same node names as Before wherever behaviour is unchanged,
|
|
48
|
+
%% so the two diagrams are visually comparable
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## What changed
|
|
52
|
+
|
|
53
|
+
```mermaid
|
|
54
|
+
flowchart TD
|
|
55
|
+
%% Merged view: before and after in one graph, every node marked by its fate.
|
|
56
|
+
|
|
57
|
+
classDef added fill:#d4f8d4,stroke:#2ea043,color:#1f2328
|
|
58
|
+
classDef removed fill:#ffd7d5,stroke:#cf222e,color:#1f2328
|
|
59
|
+
classDef changed fill:#fff5cc,stroke:#bf8700,color:#1f2328
|
|
60
|
+
classDef same fill:#f6f8fa,stroke:#8c959f,color:#1f2328
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Legend** — 🟩 added · 🟥 removed · 🟨 modified · ⬜ unchanged.
|
|
64
|
+
Dotted red edges are call paths that no longer exist.
|
|
65
|
+
|
|
66
|
+
## Notes
|
|
67
|
+
|
|
68
|
+
- <Anything the diagram can't carry: perf implications, migration ordering,
|
|
69
|
+
follow-up work.>
|
|
70
|
+
- <Any behaviour you inferred rather than confirmed, so a reader knows which
|
|
71
|
+
parts to double-check.>
|