@coldtea/pr-lens-agent-skill 0.1.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 +45 -0
- package/SKILL.md +83 -0
- package/package.json +43 -0
- package/references/config.md +90 -0
- package/references/graph-document.md +168 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ohans Emmanuel
|
|
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,45 @@
|
|
|
1
|
+
# @coldtea/pr-lens-agent-skill
|
|
2
|
+
|
|
3
|
+
The PR Lens skill for coding agents. It teaches an agent to draw the change it just made: author a graph document from the diff, validate it against the contract, render it, attach it to the pull request — and to fix a repository's map by writing corrections rather than editing generated output.
|
|
4
|
+
|
|
5
|
+
MIT © Ohans Emmanuel.
|
|
6
|
+
|
|
7
|
+
## Install it
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install --save-dev @coldtea/pr-lens-agent-skill
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**Claude Code** — copy it where skills live, per project or per user:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
mkdir -p .claude/skills/pr-lens
|
|
17
|
+
cp -R node_modules/@coldtea/pr-lens-agent-skill/{SKILL.md,references} .claude/skills/pr-lens/
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Cursor** — the same file works as a rule:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
mkdir -p .cursor/rules
|
|
24
|
+
cp node_modules/@coldtea/pr-lens-agent-skill/SKILL.md .cursor/rules/pr-lens.mdc
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Anything else** — point your agent's instructions file at `SKILL.md`. It is plain markdown with YAML frontmatter, and it assumes nothing beyond a shell and `npx`.
|
|
28
|
+
|
|
29
|
+
## What is in it
|
|
30
|
+
|
|
31
|
+
| | |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| `SKILL.md` | when to reach for PR Lens, and the write → validate → fix → render loop |
|
|
34
|
+
| `references/graph-document.md` | the document, field by field, and what the validator will catch |
|
|
35
|
+
| `references/config.md` | `.github/pr-lens.yml` corrections, with recipes |
|
|
36
|
+
|
|
37
|
+
The agent is usually the model. Rather than spending a provider key to describe a diff it already understands, it writes the document itself and lets `pr-lens validate` hold it to the contract — every failure is a path into the document, so the loop closes without a human in it.
|
|
38
|
+
|
|
39
|
+
## Why this exists
|
|
40
|
+
|
|
41
|
+
A coding agent that opens a pull request is asking a person to review code the person did not write. A diagram of what moved is the cheapest thing the agent can add to make that review possible.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
Part of [PR Lens](https://prlens.dev) — review what actually matters.
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pr-lens
|
|
3
|
+
description: Draw a code change as an architecture or data-flow diagram with PR Lens — author a graph document from a diff, validate it, render it to SVG, and attach it to a pull request; or correct a repository's map in .github/pr-lens.yml. Use when asked to diagram, visualise or explain the shape of a change, when attaching a diagram to a pull request you opened, or when an existing PR Lens diagram names things wrongly.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# PR Lens
|
|
7
|
+
|
|
8
|
+
PR Lens turns a diff into one JSON document — lanes, nodes, edges, ordered flows — and renders it as an animated SVG that reads inside a GitHub pull request comment. The document is the whole contract: if it validates, it renders.
|
|
9
|
+
|
|
10
|
+
You are usually the model. Rather than calling out to a provider, read the diff and write the document yourself, then let the tooling check it.
|
|
11
|
+
|
|
12
|
+
## The loop
|
|
13
|
+
|
|
14
|
+
1. **Read the diff.** `git diff --find-renames <base>...<head>`. The base is the merge base, not the tip of the base branch.
|
|
15
|
+
2. **Write the document** to `pr-lens/graph.json`, following `references/graph-document.md`. The authoritative shape is the JSON Schema that ships with the contract:
|
|
16
|
+
`node_modules/@coldtea/pr-lens-schema/json-schema/graph-doc.schema.json`
|
|
17
|
+
3. **Validate, and fix what it names.**
|
|
18
|
+
```bash
|
|
19
|
+
npx @coldtea/pr-lens-cli validate pr-lens/graph.json
|
|
20
|
+
```
|
|
21
|
+
Each failure is a path into your document, a reason and a code. Fix every one and run it again. Do not render an invalid document; do not "work around" a failure by deleting the element it names.
|
|
22
|
+
4. **Render and attach.**
|
|
23
|
+
```bash
|
|
24
|
+
npx @coldtea/pr-lens-cli render pr-lens/graph.json --out pr-lens/
|
|
25
|
+
```
|
|
26
|
+
Commit the SVGs somewhere durable — an orphan branch, or a release asset — and reference them from the pull request body with a `<picture>` pair so the diagram reads in both GitHub themes. `pr-lens comment --graph … --manifest …` composes that markdown for you.
|
|
27
|
+
|
|
28
|
+
If the repository has a model key configured and you would rather not author the document yourself, `npx @coldtea/pr-lens-cli analyze --base <ref>` does steps 1 and 2 with the provider of your choice.
|
|
29
|
+
|
|
30
|
+
## What makes a document worth reading
|
|
31
|
+
|
|
32
|
+
- **Include what did not change.** A diagram of only the changed nodes says nothing about blast radius. The unchanged neighbours a change touches are the context; mark them `delta: "unchanged"`.
|
|
33
|
+
- **Lanes are the reader's mental model** — a runtime, a tier, a boundary — not the folder tree.
|
|
34
|
+
- **One hero edge**, two at the outside: the connection the change is really about.
|
|
35
|
+
- **Add a flow only when there is a sequence** worth animating. One good flow beats three thin ones.
|
|
36
|
+
- **Attach file refs**: they become the permalinks a reviewer clicks.
|
|
37
|
+
- **There is no findings lens.** PR Lens is the comprehension layer, not another review bot. There is no field for a bug, a risk or a security note, and a document that invents one is rejected rather than trimmed.
|
|
38
|
+
|
|
39
|
+
## What the validator will catch
|
|
40
|
+
|
|
41
|
+
Read `references/graph-document.md` before writing. The four failures that account for nearly everything:
|
|
42
|
+
|
|
43
|
+
| Code | What you did |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| `BROKEN_REFERENCE` | an edge, a flow step or a view names an id you never declared |
|
|
46
|
+
| `INVALID_DOCUMENT` | an invented field — the schemas are strict, unknown keys are rejected |
|
|
47
|
+
| `DUPLICATE_ID` | two nodes, edges or views sharing an id |
|
|
48
|
+
| `UNSUPPORTED_SCHEMA_VERSION` | `schemaVersion` is not the contract version installed |
|
|
49
|
+
|
|
50
|
+
Four rules cannot be expressed in JSON Schema and are checked only by the parser, so structured output alone does not make a document valid: referential integrity, a line range that ends before it starts, a `self` message whose endpoints disagree, and a patch whose two commits are the same. Always validate.
|
|
51
|
+
|
|
52
|
+
## Fixing a map instead of writing one
|
|
53
|
+
|
|
54
|
+
When someone says the diagram is wrong — a node is misnamed, a folder should not be on it, something sits in the wrong lane — do not edit the generated document. It is regenerated on every run. Write the correction into `.github/pr-lens.yml`, which is an overlay applied over fresh inference every time:
|
|
55
|
+
|
|
56
|
+
```yaml
|
|
57
|
+
schemaVersion: 0.1.0
|
|
58
|
+
map:
|
|
59
|
+
rename:
|
|
60
|
+
- match: functions/src/broadcast/sendBroadcastBulk.ts
|
|
61
|
+
to: Broadcast sender
|
|
62
|
+
exclude:
|
|
63
|
+
- "**/*.test.ts"
|
|
64
|
+
lane:
|
|
65
|
+
- match: packages/broadcast-lib/**
|
|
66
|
+
lane: functions
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`references/config.md` has the full format and the recipes. Validate it the same way: `npx @coldtea/pr-lens-cli validate .github/pr-lens.yml`.
|
|
70
|
+
|
|
71
|
+
A `match` beginning with `id:` addresses one node exactly; anything else is a path glob matched against a node's file paths — prefer the glob, because it keeps holding when the next run names the node differently. A lane pin may name a lane the document never declared: the band is created, and takes the id for its label, so give it one a reader would want to see.
|
|
72
|
+
|
|
73
|
+
`pr-lens render` says so when a correction matched nothing, which is how a config that has drifted — the file it named moved or was deleted — becomes visible instead of quietly doing nothing.
|
|
74
|
+
|
|
75
|
+
## Reference documents
|
|
76
|
+
|
|
77
|
+
The contract ships worked examples. `postmark-refactor.graph.json` is the realistic one — three lanes, all four delta states, a hero edge, a seven-step flow, a nested drill-down tree — and `minimal.graph.json` is the smallest document that validates:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
ls node_modules/@coldtea/pr-lens-schema/examples/
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Read the realistic one before authoring your first document. It is faster than reading the schema.
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@coldtea/pr-lens-agent-skill",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The PR Lens skill for coding agents: author a graph document from a diff, validate it, render it, and correct a repository's map.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Ohans Emmanuel",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/coldteadotai/pr-lens.git",
|
|
10
|
+
"directory": "packages/agent-skill"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/coldteadotai/pr-lens/tree/main/packages/agent-skill#readme",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"pr-lens",
|
|
15
|
+
"agent-skill",
|
|
16
|
+
"claude-code",
|
|
17
|
+
"cursor",
|
|
18
|
+
"code-review",
|
|
19
|
+
"architecture-diagram"
|
|
20
|
+
],
|
|
21
|
+
"type": "module",
|
|
22
|
+
"files": [
|
|
23
|
+
"SKILL.md",
|
|
24
|
+
"references",
|
|
25
|
+
"README.md",
|
|
26
|
+
"LICENSE"
|
|
27
|
+
],
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^20.19.0",
|
|
33
|
+
"typescript": "7.0.2",
|
|
34
|
+
"vitest": "4.1.11",
|
|
35
|
+
"yaml": "^2.8.1",
|
|
36
|
+
"@coldtea/pr-lens-renderer": "^0.1.0",
|
|
37
|
+
"@coldtea/pr-lens-schema": "^0.1.0"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Correcting the map — `.github/pr-lens.yml`
|
|
2
|
+
|
|
3
|
+
The generated document is regenerated on every run, so editing it is pointless. Corrections live in `.github/pr-lens.yml`, an overlay applied over fresh inference every time. Inference never writes back into this file, which is why a correction keeps holding as the code moves.
|
|
4
|
+
|
|
5
|
+
```yaml
|
|
6
|
+
schemaVersion: 0.1.0 # required
|
|
7
|
+
lenses: [architecture, data-flow]
|
|
8
|
+
branding: true
|
|
9
|
+
map:
|
|
10
|
+
rename:
|
|
11
|
+
- match: functions/src/broadcast/sendBroadcastBulk.ts
|
|
12
|
+
to: Broadcast sender
|
|
13
|
+
exclude:
|
|
14
|
+
- "**/*.test.ts"
|
|
15
|
+
- scripts/**
|
|
16
|
+
lane:
|
|
17
|
+
- match: packages/broadcast-lib/**
|
|
18
|
+
lane: functions
|
|
19
|
+
group:
|
|
20
|
+
- match: id:build-bulk-payload
|
|
21
|
+
group: broadcast-lib
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Every field except `schemaVersion` is optional, and the file itself is optional. The JSON Schema for editor autocomplete ships with the contract:
|
|
25
|
+
|
|
26
|
+
```jsonc
|
|
27
|
+
{ "$ref": "node_modules/@coldtea/pr-lens-schema/json-schema/config.schema.json" }
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Selectors
|
|
31
|
+
|
|
32
|
+
A `match` beginning with `id:` addresses exactly one node — `id:build-bulk-payload`. Anything else is a repository-relative path glob matched against the node's file paths.
|
|
33
|
+
|
|
34
|
+
**Prefer the glob.** Ids come from inference and may change when the code does; a path correction survives that. Reach for `id:` only when no path distinguishes the node, or when the node has no files at all (an external service, a queue).
|
|
35
|
+
|
|
36
|
+
## The four corrections
|
|
37
|
+
|
|
38
|
+
| | What it does |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| `rename` | replaces the inferred label |
|
|
41
|
+
| `exclude` | drops matching nodes, and the edges and flow steps that hung from them |
|
|
42
|
+
| `lane` | moves matching nodes into a lane, **creating it** when the document declares no such id |
|
|
43
|
+
| `group` | clusters matching nodes under a sub-group inside their lane |
|
|
44
|
+
|
|
45
|
+
Up to 128 of each. They are about intent rather than structure: there is no way to add a node or draw an edge here, and the one thing a correction can bring into existence is a lane — a band a repository wants that inference did not find. It takes the id for its label, because the id is the only name this file carries, so write `lane: infrastructure` rather than `lane: l3`. If the map is wrong in a way corrections cannot express, the fix belongs in the analysis, not in this file.
|
|
46
|
+
|
|
47
|
+
## Recipes
|
|
48
|
+
|
|
49
|
+
**"Stop showing me the test files."**
|
|
50
|
+
```yaml
|
|
51
|
+
map:
|
|
52
|
+
exclude: ["**/*.test.ts", "**/__tests__/**"]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**"That node is called the wrong thing."** Match the file it comes from, not its id:
|
|
56
|
+
```yaml
|
|
57
|
+
map:
|
|
58
|
+
rename:
|
|
59
|
+
- match: server/lib/broadcast/createBroadcastSendTask.ts
|
|
60
|
+
to: Send task
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**"These belong in a band of their own."** The lane need not exist yet:
|
|
64
|
+
```yaml
|
|
65
|
+
map:
|
|
66
|
+
lane:
|
|
67
|
+
- match: infra/**
|
|
68
|
+
lane: infrastructure
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**"Keep the shared library together."**
|
|
72
|
+
```yaml
|
|
73
|
+
map:
|
|
74
|
+
group:
|
|
75
|
+
- match: packages/broadcast-lib/**
|
|
76
|
+
group: broadcast-lib
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**"Only draw the architecture."**
|
|
80
|
+
```yaml
|
|
81
|
+
lenses: [architecture]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Check it
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx @coldtea/pr-lens-cli validate .github/pr-lens.yml
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`pr-lens render` reports any correction that changed nothing about the document it drew — that is a config that has drifted out of date, usually because the file a selector named has moved or gone. It is not an error and nothing stops, but it is worth fixing: a correction that matches nothing is a correction nobody is getting.
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Authoring a graph document
|
|
2
|
+
|
|
3
|
+
The authoritative shape is `node_modules/@coldtea/pr-lens-schema/json-schema/graph-doc.schema.json`. This page is what that schema cannot tell you: which parts matter, and where documents actually go wrong.
|
|
4
|
+
|
|
5
|
+
Every schema here is **strict** — an unknown key is a rejection, not a warning. A field with a default may be left out.
|
|
6
|
+
|
|
7
|
+
## The document
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"schemaVersion": "0.1.0",
|
|
12
|
+
"kind": "graph",
|
|
13
|
+
"title": "Batch broadcast sending through Postmark",
|
|
14
|
+
"summary": "One paragraph answering: what does this change do?",
|
|
15
|
+
"lenses": ["architecture", "data-flow"],
|
|
16
|
+
"provenance": { "repo": { "owner": "…", "name": "…" }, "base": { "sha": "…" }, "head": { "sha": "…" } },
|
|
17
|
+
"lanes": [],
|
|
18
|
+
"nodes": [],
|
|
19
|
+
"edges": [],
|
|
20
|
+
"flows": [],
|
|
21
|
+
"stats": {},
|
|
22
|
+
"views": []
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`lenses` declares what the document carries enough detail to draw: `architecture`, `data-flow`, or both. A document carrying flows must declare `data-flow`.
|
|
27
|
+
|
|
28
|
+
`provenance` is where the document came from: the repository, the base and head commit shas (lowercase hex, 7–40 characters), optionally the pull request and the generator. When you produce a document through the CLI these are filled in from the repository — do not invent them.
|
|
29
|
+
|
|
30
|
+
## Ids
|
|
31
|
+
|
|
32
|
+
`^[A-Za-z0-9][A-Za-z0-9._:/-]*$`, at most 128 characters, unique within their own collection. Use readable kebab-case: `broadcast-sender`, not `n1`. An id ends up in an SVG id, a URL fragment and a comment anchor, so nothing else is allowed through.
|
|
33
|
+
|
|
34
|
+
## Deltas
|
|
35
|
+
|
|
36
|
+
Every node, edge, flow and flow step declares one: `added`, `modified`, `removed`, `unchanged`.
|
|
37
|
+
|
|
38
|
+
`unchanged` is not padding. It is the neighbouring code the change touches, and it is what turns a diagram into a blast radius. A document whose every element is `added` describes a change nobody can place.
|
|
39
|
+
|
|
40
|
+
## Lanes
|
|
41
|
+
|
|
42
|
+
1 to 16. Every node belongs to exactly one.
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{ "id": "functions", "label": "Cloud Functions", "subtitle": "Node 20", "order": 1 }
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`order` (0–64) places lanes left to right; ties fall back to array order. Give a lane a `delta` only when the lane itself is new or gone.
|
|
49
|
+
|
|
50
|
+
## Nodes
|
|
51
|
+
|
|
52
|
+
1 to 256.
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"id": "send-broadcast-bulk",
|
|
57
|
+
"label": "sendBroadcastBulk",
|
|
58
|
+
"kind": "function",
|
|
59
|
+
"delta": "added",
|
|
60
|
+
"lane": "functions",
|
|
61
|
+
"group": "broadcast-lib",
|
|
62
|
+
"subtitle": "(broadcastId) => Promise<void>",
|
|
63
|
+
"summary": "Claims the broadcast, builds one bulk payload and posts it.",
|
|
64
|
+
"files": [{ "path": "functions/src/broadcast/sendBroadcastBulk.ts", "startLine": 1, "endLine": 142 }],
|
|
65
|
+
"badges": ["retry"]
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`kind` is one of `service app module function route job queue datastore cache external ui config test package other`. It drives the card's icon and shape and nothing else; when in doubt, `other` still renders.
|
|
70
|
+
|
|
71
|
+
`group` clusters nodes inside a lane — a package, a folder that means something. `files` (up to 64) become diff permalinks. `badges` (up to 6) are extra chips; the delta badge is drawn for you, so do not restate it.
|
|
72
|
+
|
|
73
|
+
## Edges
|
|
74
|
+
|
|
75
|
+
Up to 512.
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"id": "bulk-to-postmark",
|
|
80
|
+
"from": "send-broadcast-bulk",
|
|
81
|
+
"to": "postmark",
|
|
82
|
+
"kind": "http",
|
|
83
|
+
"delta": "added",
|
|
84
|
+
"label": "POST /email/bulk",
|
|
85
|
+
"emphasis": "hero",
|
|
86
|
+
"animated": true
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`kind` is one of `call http rpc event queue data dependency render other`. `emphasis` is `normal` (default), `hero` or `muted`. More than one or two heroes and the emphasis stops meaning anything. `from` and `to` must be node ids you declared — this is the single most common failure.
|
|
91
|
+
|
|
92
|
+
## Flows
|
|
93
|
+
|
|
94
|
+
Up to 16, for the data-flow lens.
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"id": "send-pipeline",
|
|
99
|
+
"title": "Sending a broadcast",
|
|
100
|
+
"delta": "modified",
|
|
101
|
+
"participants": [{ "node": "queue-route" }, { "node": "send-broadcast-bulk" }, { "node": "postmark" }],
|
|
102
|
+
"messages": [
|
|
103
|
+
{ "id": "enqueue", "from": "queue-route", "to": "send-broadcast-bulk", "label": "enqueue job", "kind": "async", "delta": "modified" },
|
|
104
|
+
{ "id": "send", "from": "send-broadcast-bulk", "to": "postmark", "label": "POST /email/bulk", "kind": "sync", "delta": "added", "repeat": 4 },
|
|
105
|
+
{ "id": "accepted", "from": "postmark", "to": "send-broadcast-bulk", "label": "200 Accepted", "kind": "return", "delta": "added" }
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
- 2 to 12 participants, ordered by array position; each names a node id.
|
|
111
|
+
- 1 to 64 messages. **Step order is array order** — there is no step number field, so a document cannot disagree with its own animation.
|
|
112
|
+
- `kind` is `sync`, `async`, `return` or `self`. `self` requires `from === to`, and no other kind may have them equal.
|
|
113
|
+
- Both endpoints must be participants of that flow, not merely nodes of the document.
|
|
114
|
+
- `repeat` says a step happens more than once per run, e.g. 4 batched requests.
|
|
115
|
+
|
|
116
|
+
## Stats
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{ "filesChanged": 27, "additions": 1979, "deletions": 1370, "chips": [{ "label": "Postmark calls", "value": "500x fewer", "tone": "hero" }] }
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Up to 8 chips, `tone` one of `neutral added modified removed hero`. Per-delta element counts are deliberately absent from the schema: they are derivable from the document, and a stored copy can only go stale.
|
|
123
|
+
|
|
124
|
+
## Views
|
|
125
|
+
|
|
126
|
+
The drill-down tree in the comment: up to 32 at the root, nesting up to 32 children each. A document with no views renders as one picture and nothing else.
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"id": "the-new-path",
|
|
131
|
+
"title": "The new batch path",
|
|
132
|
+
"lens": "architecture",
|
|
133
|
+
"summary": "What replaced the per-recipient loop.",
|
|
134
|
+
"defaultOpen": false,
|
|
135
|
+
"scope": { "kind": "selection", "nodes": ["send-broadcast-bulk", "postmark"] },
|
|
136
|
+
"children": []
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
`scope` is either `{ "kind": "all" }` (the default) or a selection naming at least one lane, node, edge or flow. The two are distinct states on purpose: removing the last element a view pointed at can never quietly turn it into a view of everything. A view's `lens` must be one the document declares.
|
|
141
|
+
|
|
142
|
+
## Layout
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{ "direction": "right", "laneOrder": ["api", "functions", "external"], "rank": { "send-broadcast-bulk": 2 } }
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Hints, not instructions — the renderer owns final placement so a diagram stays deterministic and a stale hint cannot break it. Absolute coordinates are not expressible. Omitting `layout` entirely is normal.
|
|
149
|
+
|
|
150
|
+
## File references
|
|
151
|
+
|
|
152
|
+
```json
|
|
153
|
+
{ "path": "functions/src/broadcast/sendBroadcastBulk.ts", "startLine": 1, "endLine": 142, "revision": "head" }
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Repository-relative POSIX paths: no leading `/`, no drive letter, no backslash, no `..` segment. Lines are 1-based, `endLine` requires `startLine` and may not precede it. `revision` defaults to `head`; use `base` on elements the change removes.
|
|
157
|
+
|
|
158
|
+
## Length limits
|
|
159
|
+
|
|
160
|
+
Labels 120 characters, summaries 2000, chip values 32. They are display fields — a label that needs 120 characters is a label the diagram cannot draw.
|
|
161
|
+
|
|
162
|
+
## Then validate
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
npx @coldtea/pr-lens-cli validate pr-lens/graph.json
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Every problem is reported at once, with a path into the document. Fix them all and run it again until it is clean.
|