@jphutchins/code-review 0.1.0-alpha.5 → 0.1.0-alpha.50
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/README.md +92 -8
- package/dist/index.js +5033 -1099
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
- package/schema/VERSIONING.md +34 -2
- package/schema/findings.schema.json +223 -14
- package/schema/prices.example.json +8 -2
- package/schema/prices.schema.json +77 -24
- package/schema/v0.2/findings.schema.json +88 -0
- package/templates/comment.eta +131 -27
- package/templates/inline.eta +36 -5
package/templates/comment.eta
CHANGED
|
@@ -1,40 +1,144 @@
|
|
|
1
1
|
<!-- code-review -->
|
|
2
2
|
<!-- reviewed-sha: <%= it.reviewedSha %> -->
|
|
3
|
+
<% if (!it.incomplete && it.route) { -%>
|
|
4
|
+
<!-- reviewed-route: <%= it.route %> -->
|
|
5
|
+
<% } -%>
|
|
6
|
+
<% if (!it.incomplete) { -%>
|
|
7
|
+
<!-- review-complete -->
|
|
8
|
+
<% } -%>
|
|
9
|
+
<% if (it.findingsPointer) { -%>
|
|
10
|
+
<%~ it.findingsPointer %>
|
|
11
|
+
<% } -%>
|
|
3
12
|
|
|
4
13
|
### <%= it.verdictBadge(it.findings.verdict) %>
|
|
5
14
|
|
|
6
|
-
<% const meta = [] %><% if (it.route) { meta.push('**
|
|
15
|
+
<% const meta = [] %><% if (it.postedAt) { meta.push('**Reviewed** `' + it.reviewedSha.slice(0, 7) + '` at ' + it.postedAt) } %><% if (it.route) { meta.push('**route:** ' + it.route) } %><% if (it.effort) { meta.push('**effort:** ' + it.effort) } %><% if (it.hasUsage) { meta.push('**turns:** ' + it.envelope.turns); meta.push('**wall:** ' + it.formatDuration(it.envelope.duration_ms)); meta.push('**models:** ' + it.modelNames); meta.push('**cost:** ' + it.formatCost(it.costReport.totalCostUSD)) } else { meta.push('_usage unavailable_') } %><sub><%~ meta.join(' · ') %></sub>
|
|
16
|
+
<% if (!it.incomplete) { -%>
|
|
17
|
+
<% if (it.roundsSummary) { -%>
|
|
18
|
+
<sub><%~ it.roundsSummary %></sub>
|
|
19
|
+
<% } -%>
|
|
20
|
+
<% if (it.convergenceSummary) { -%>
|
|
21
|
+
<sub><%~ it.convergenceSummary %></sub>
|
|
22
|
+
<% } -%>
|
|
23
|
+
<% if (it.changeSummary) { -%>
|
|
24
|
+
<sub>**Changes:** <%~ it.changeSummary %></sub>
|
|
25
|
+
<% } -%>
|
|
26
|
+
<% if (it.clocDiff) { -%>
|
|
27
|
+
<details><summary>📏 cloc</summary>
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
<%~ it.clocDiff %>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
</details>
|
|
34
|
+
<% } -%>
|
|
35
|
+
<% if (it.metastasisNote) { -%>
|
|
36
|
+
<%~ it.metastasisNote %>
|
|
37
|
+
<% } -%>
|
|
38
|
+
<% if (it.answeredReRaiseNote) { -%>
|
|
39
|
+
<%~ it.answeredReRaiseNote %>
|
|
40
|
+
<% } -%>
|
|
41
|
+
<% } -%>
|
|
7
42
|
|
|
8
43
|
<%~ it.findings.summary %>
|
|
9
44
|
|
|
45
|
+
<% if (!it.incomplete && it.systemic.length > 0) { -%>
|
|
46
|
+
|
|
47
|
+
### 🔗 Systemic problems
|
|
48
|
+
|
|
49
|
+
<% it.systemic.forEach(function(s) { -%>
|
|
50
|
+
#### <%= it.severityEmoji(s.severity) %> (<%= s.severity %>) <%= s.title %> · confidence <%= it.formatConfidence(s.confidence) %>
|
|
51
|
+
<% const meta = [] %><% if (s.paths && s.paths.length > 0) { meta.push('Affects: ' + s.paths.map(function(p) { return '`' + p + '`' }).join(', ')) } %><% if (s.finding_codes && s.finding_codes.length > 0) { meta.push('Ties together: ' + s.finding_codes.map(function(c) { return '`' + c + '`' }).join(', ')) } %><% if (meta.length > 0) { %>_<%~ meta.join(' · ') %>_<% } %>
|
|
52
|
+
|
|
53
|
+
<%~ s.description %>
|
|
54
|
+
|
|
55
|
+
> [!TIP]
|
|
56
|
+
> <details><summary>Reasoning</summary>
|
|
57
|
+
>
|
|
58
|
+
<% s.reasoning.split("\n").forEach(function(rl) { -%>
|
|
59
|
+
> <%= rl %>
|
|
60
|
+
<% }) -%>
|
|
61
|
+
>
|
|
62
|
+
> </details>
|
|
63
|
+
<% }) -%>
|
|
64
|
+
<% } -%>
|
|
65
|
+
|
|
10
66
|
---
|
|
11
67
|
|
|
12
68
|
<% const c = it.severityCounts %><% const findingsTotal = c.critical + c.major + c.minor + c.nit %>
|
|
13
69
|
<% if (findingsTotal > 0) { %>
|
|
14
70
|
<% const parts = [] %><% if (c.critical) { parts.push(it.severityEmoji('critical') + ' ' + c.critical) } %><% if (c.major) { parts.push(it.severityEmoji('major') + ' ' + c.major) } %><% if (c.minor) { parts.push(it.severityEmoji('minor') + ' ' + c.minor) } %><% if (c.nit) { parts.push(it.severityEmoji('nit') + ' ' + c.nit) } %>
|
|
15
71
|
**Findings:** <%~ parts.join(' · ') %>
|
|
16
|
-
<% } else { %>
|
|
72
|
+
<% } else if (!it.incomplete && it.systemic.length === 0 && !it.answeredReRaiseNote) { %>
|
|
17
73
|
_No findings — clean review._
|
|
18
74
|
<% } %>
|
|
19
75
|
|
|
20
76
|
<% if (it.inlineDisposition && it.inlineDisposition.kind === 'posted') { %>
|
|
21
|
-
→ <%= it.inlineDisposition.count %> comment<%= it.inlineDisposition.count === 1 ? '' : 's' %> posted inline on `<%= it.inlineDisposition.sha.slice(0, 7) %>` — see the review.
|
|
77
|
+
→ <%= it.inlineDisposition.count %> comment<%= it.inlineDisposition.count === 1 ? '' : 's' %> posted inline on `<%= it.inlineDisposition.sha.slice(0, 7) %>` — <% if (it.reviewUrl) { %>[see the review](<%~ it.reviewUrl %>)<% } else { %>see the review<% } %>.
|
|
22
78
|
<% } else if (it.inlineDisposition && it.inlineDisposition.kind === 'none-in-diff') { %>
|
|
23
79
|
→ No inline comments — all findings are outside the diff (listed below).
|
|
24
|
-
<% } else if (it.inlineDisposition && it.inlineDisposition.kind === '
|
|
25
|
-
→ Inline
|
|
80
|
+
<% } else if (it.inlineDisposition && it.inlineDisposition.kind === 'inline-unavailable') { %>
|
|
81
|
+
→ ⚠️ Inline comments couldn't be posted for this review (GitHub rejected a comment's position) — every finding is listed below instead.
|
|
26
82
|
<% } %>
|
|
27
83
|
|
|
28
84
|
<% if (it.strays.length > 0) { %>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
85
|
+
### <% if (it.inlineDisposition && it.inlineDisposition.kind === 'no-envelope') { %>Findings (no inline review — result envelope lost)<% } else { %><%= (it.unanchoredCount && it.unanchoredCount > 0) ? 'Findings' : 'Findings outside the diff' %><% } %>
|
|
86
|
+
<% if (it.inlineDisposition && it.inlineDisposition.kind === 'no-envelope') { %>
|
|
87
|
+
_Every finding is listed below — the inline review could not be built because the result envelope was missing._
|
|
88
|
+
<% } else if (it.unanchoredCount && it.unanchoredCount > 0) { %>
|
|
89
|
+
_<%= it.unanchoredCount %> finding<%= it.unanchoredCount === 1 ? '' : 's' %> below couldn't be posted as inline comment<%= it.unanchoredCount === 1 ? '' : 's' %> (GitHub rejected the position)<% if (it.strays.length > it.unanchoredCount) { %>; the rest are outside the diff<% } %>._
|
|
90
|
+
<% } %>
|
|
32
91
|
|
|
33
92
|
<% it.strays.forEach(function(f) { -%>
|
|
34
|
-
|
|
93
|
+
#### <%= it.severityEmoji(f.severity) %> (<%= f.severity %>) `<%= f.path %>:<%= f.start_line %><% if (f.start_line !== f.end_line) { %>–<%= f.end_line %><% } %>` — <%= f.title %> · confidence <%= it.formatConfidence(f.confidence) %> · likelihood <%= it.formatConfidence(f.likelihood) %>
|
|
94
|
+
|
|
95
|
+
<%~ f.description %>
|
|
96
|
+
<% if (f.code && it.sameRootNotes && Object.prototype.hasOwnProperty.call(it.sameRootNotes, f.code)) { -%>
|
|
97
|
+
|
|
98
|
+
> ⚠️ <%~ it.sameRootNotes[f.code] %>
|
|
99
|
+
<% } -%>
|
|
100
|
+
<% if (f.answeredNote) { -%>
|
|
101
|
+
|
|
102
|
+
> ↩️ <%~ f.answeredNote %>
|
|
103
|
+
<% } -%>
|
|
104
|
+
<% if (f.recommendation) { -%>
|
|
105
|
+
|
|
106
|
+
**Recommended fix:** <%~ f.recommendation %>
|
|
107
|
+
<% } -%>
|
|
108
|
+
<% if (f.patchProjection.kind === "suggestion") { -%>
|
|
109
|
+
|
|
110
|
+
```suggestion
|
|
111
|
+
<%~ f.patchProjection.text %>
|
|
112
|
+
```
|
|
113
|
+
<% } else if (f.patchProjection.kind === "patch") { -%>
|
|
114
|
+
|
|
115
|
+
```patch
|
|
116
|
+
<%~ f.patchProjection.raw %>
|
|
117
|
+
```
|
|
118
|
+
<% } -%>
|
|
119
|
+
|
|
120
|
+
> [!TIP]
|
|
121
|
+
> <details><summary>Reasoning (<%= it.formatConfidence(f.confidence) %> confidence · <%= it.formatConfidence(f.likelihood) %> likelihood)</summary>
|
|
122
|
+
>
|
|
123
|
+
<% f.reasoning.split("\n").forEach(function(rl) { -%>
|
|
124
|
+
> <%= rl %>
|
|
125
|
+
<% }) -%>
|
|
126
|
+
>
|
|
127
|
+
> </details>
|
|
35
128
|
<% }) %>
|
|
36
129
|
<% } %>
|
|
37
130
|
|
|
131
|
+
<% if (it.suppressedNits && it.suppressedNits.length > 0) { %>
|
|
132
|
+
> [!NOTE]
|
|
133
|
+
> <details><summary>🔇 <%= it.suppressedNits.length %> nit<%= it.suppressedNits.length === 1 ? '' : 's' %> below the visibility floor (confidence × likelihood < <%= it.nitVisibilityFloor %>) — hidden</summary>
|
|
134
|
+
>
|
|
135
|
+
<% it.suppressedNits.forEach(function(n) { -%>
|
|
136
|
+
> - `<%= n.path %>:<%= n.startLine %>` — <%= n.title %><% if (n.code) { %> (`<%= n.code %>`)<% } %> _(m = <%= n.m %>)_
|
|
137
|
+
<% }) -%>
|
|
138
|
+
>
|
|
139
|
+
> </details>
|
|
140
|
+
<% } %>
|
|
141
|
+
|
|
38
142
|
<% if (it.testReport) { %>
|
|
39
143
|
---
|
|
40
144
|
|
|
@@ -54,24 +158,24 @@ All <%= it.testReport.total %> tests passed.
|
|
|
54
158
|
|
|
55
159
|
---
|
|
56
160
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
161
|
+
> [!WARNING]
|
|
162
|
+
> **LLM Disclosure** — this review was produced by <%= it.modelNames || "unknown model" %>.
|
|
163
|
+
>
|
|
164
|
+
<% if (it.usageAvailable && it.costReport.lines.length > 0) { -%>
|
|
165
|
+
> | Model | Input | Output | Cache read | Cache write | Cost |
|
|
166
|
+
> |---|--:|--:|--:|--:|--:|
|
|
62
167
|
<% it.costReport.lines.forEach(function(l) { -%>
|
|
63
|
-
| <%= l.model %> | <%= it.formatTokens(l.inputTokens) %> | <%= it.formatTokens(l.outputTokens) %> | <%= it.formatTokens(l.cacheReadTokens) %> | <%= it.formatTokens(l.cacheWriteTokens) %> | <%= it.formatCost(l.costUSD) %> |
|
|
168
|
+
> | <%= l.model %> | <%= it.formatTokens(l.inputTokens) %> | <%= it.formatTokens(l.outputTokens) %> | <%= it.formatTokens(l.cacheReadTokens) %> | <%= it.formatTokens(l.cacheWriteTokens) %> | <%= it.formatCost(l.costUSD) %> |
|
|
64
169
|
<% }) -%>
|
|
65
|
-
| **Total** | **<%= it.formatTokens(it.costReport.totalInputTokens) %>** | **<%= it.formatTokens(it.costReport.totalOutputTokens) %>** | **<%= it.formatTokens(it.costReport.totalCacheReadTokens) %>** | **<%= it.formatTokens(it.costReport.totalCacheWriteTokens) %>** | **<%= it.formatCost(it.costReport.totalCostUSD) %>** |
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
<% } else
|
|
69
|
-
<sub>No per-model usage was recorded for this run.</sub>
|
|
70
|
-
<% } else { %>
|
|
170
|
+
> | **Total** | **<%= it.formatTokens(it.costReport.totalInputTokens) %>** | **<%= it.formatTokens(it.costReport.totalOutputTokens) %>** | **<%= it.formatTokens(it.costReport.totalCacheReadTokens) %>** | **<%= it.formatTokens(it.costReport.totalCacheWriteTokens) %>** | **<%= it.formatCost(it.costReport.totalCostUSD) %>** |
|
|
171
|
+
<% } else if (it.usageAvailable) { -%>
|
|
172
|
+
> No per-model usage was recorded for this run.
|
|
173
|
+
<% } else { -%>
|
|
71
174
|
> **Usage/cost unavailable** — the result envelope for this run was missing or malformed.
|
|
72
|
-
<% }
|
|
73
|
-
|
|
74
|
-
>
|
|
75
|
-
>
|
|
76
|
-
|
|
77
|
-
>
|
|
175
|
+
<% } -%>
|
|
176
|
+
<% if (it.usageAvailable && !it.pricesProvided) { -%>
|
|
177
|
+
>
|
|
178
|
+
> _Cost shown as **N/A** — [No `.github/prices.json`](https://github.com/JPHutchins/code-review/blob/main/schema/prices.example.json) price map to recompute from._
|
|
179
|
+
<% } -%>
|
|
180
|
+
>
|
|
181
|
+
> _Generated by [code-review](https://github.com/JPHutchins/code-review)<% if (it.runUrl) { %> · [view the run & traces](<%~ it.runUrl %>)<% } %>._
|
package/templates/inline.eta
CHANGED
|
@@ -1,9 +1,40 @@
|
|
|
1
|
-
|
|
1
|
+
<% if (it.findingsPointer) { -%>
|
|
2
|
+
<%~ it.findingsPointer %>
|
|
3
|
+
<% } -%>
|
|
4
|
+
<%= it.severityEmoji(it.severity) %> <%= it.severity.charAt(0).toUpperCase() + it.severity.slice(1) %>: **<%= it.title %>** · <%= it.formatConfidence(it.confidence) %> confidence · <%= it.formatConfidence(it.likelihood) %> likelihood
|
|
5
|
+
|
|
6
|
+
<%~ it.description %>
|
|
7
|
+
<% if (it.sameRootNote) { -%>
|
|
8
|
+
|
|
9
|
+
> ⚠️ <%~ it.sameRootNote %>
|
|
10
|
+
<% } -%>
|
|
11
|
+
<% if (it.answeredNote) { -%>
|
|
12
|
+
|
|
13
|
+
> ↩️ <%~ it.answeredNote %>
|
|
14
|
+
<% } -%>
|
|
15
|
+
<% if (it.recommendation) { -%>
|
|
16
|
+
|
|
17
|
+
**Recommended fix:** <%~ it.recommendation %>
|
|
18
|
+
<% } -%>
|
|
19
|
+
<% if (it.patchProjection.kind === "suggestion") { -%>
|
|
2
20
|
|
|
3
|
-
<% if (it.suggestion !== null && it.suggestion !== undefined) { %>
|
|
4
21
|
```suggestion
|
|
5
|
-
<%~ it.
|
|
22
|
+
<%~ it.patchProjection.text %>
|
|
23
|
+
```
|
|
24
|
+
<% } else if (it.patchProjection.kind === "patch") { -%>
|
|
25
|
+
|
|
26
|
+
```patch
|
|
27
|
+
<%~ it.patchProjection.raw %>
|
|
6
28
|
```
|
|
7
|
-
<% }
|
|
29
|
+
<% } -%>
|
|
8
30
|
|
|
9
|
-
|
|
31
|
+
> [!TIP]
|
|
32
|
+
> Generated by <%~ it.modelsText %>.
|
|
33
|
+
> <details>
|
|
34
|
+
> <summary>Reasoning</summary>
|
|
35
|
+
>
|
|
36
|
+
<% it.reasoning.split("\n").forEach(function(rl) { -%>
|
|
37
|
+
> <%= rl %>
|
|
38
|
+
<% }) -%>
|
|
39
|
+
>
|
|
40
|
+
> </details>
|