@jphutchins/code-review 0.1.0-alpha.6 โ†’ 0.1.0-alpha.60

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.
@@ -1,52 +1,206 @@
1
1
  <!-- code-review -->
2
2
  <!-- reviewed-sha: <%= it.reviewedSha %> -->
3
- <% if (it.embeddedFindings) { -%>
4
- <!-- code-review:findings-json;base64 <%~ it.embeddedFindings %> -->
5
- <% } else if (it.jsonUrl) { -%>
6
- <!-- code-review:findings-json <%~ it.jsonUrl %> -->
3
+ <% if (!it.incomplete && it.route) { -%>
4
+ <!-- reviewed-route: <%= it.route %> -->
7
5
  <% } -%>
6
+ <% if (!it.incomplete) { -%>
7
+ <!-- review-complete -->
8
+ <% } -%>
9
+ <% if (it.findingsPointer) { -%>
10
+ <%~ it.findingsPointer %>
11
+ <% } -%>
12
+
13
+ ## <%= it.verdictBadge(it.findings.verdict) %>
8
14
 
9
- ### <%= it.verdictBadge(it.findings.verdict) %>
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>
10
34
 
11
- <% const meta = [] %><% if (it.route) { meta.push('**Route:** ' + it.route) } %><% if (it.effort) { meta.push('**effort:** ' + it.effort) } %><% if (it.usageAvailable) { 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_') } %><%~ meta.join(' ยท ') %>
35
+ <% } -%>
36
+ <% if (it.metastasisNote) { -%>
37
+ <%~ it.metastasisNote %>
38
+ <% } -%>
39
+ <% if (it.answeredReRaiseNote) { -%>
40
+ <%~ it.answeredReRaiseNote %>
41
+ <% } -%>
42
+ <% } -%>
12
43
 
13
44
  <%~ it.findings.summary %>
14
45
 
46
+ <% if (!it.incomplete && it.systemic.length > 0) { -%>
47
+
48
+ ## ๐Ÿ”— Systemic problems
49
+
50
+ <% it.systemic.forEach(function(s) { -%>
51
+ ### <%= it.severityEmoji(s.severity) %> (<%= s.severity %>) <%= s.title %>
52
+ <sub>confidence <%= it.formatConfidence(s.confidence) %><% if (s.id) { %> ยท id <% if (s.code_url) { %>[`<%~ s.id %>`](<%~ s.code_url %>)<% } else { %>`<%~ s.id %>`<% } %><% } %></sub>
53
+ <% const meta = [] %><% if (s.paths && s.paths.length > 0) { meta.push('Affects: ' + s.paths.map(function(p) { return '`' + p + '`' }).join(', ')) } %><% if (s.finding_ids && s.finding_ids.length > 0) { meta.push('Ties together: ' + s.finding_ids.map(function(c) { return '`' + c + '`' }).join(', ')) } %><% if (meta.length > 0) { %>_<%~ meta.join(' ยท ') %>_<% } %>
54
+
55
+ <%~ s.description %>
56
+ <% if (s.discussionHtml) { -%>
57
+
58
+ <details><summary>๐Ÿ’ฌ Discussion</summary>
59
+
60
+ <%~ s.discussionHtml %>
61
+ </details>
62
+ <% } -%>
63
+
64
+ > <details><summary>Reasoning</summary>
65
+ >
66
+ <% s.reasoning.split("\n").forEach(function(rl) { -%>
67
+ > <%= rl %>
68
+ <% }) -%>
69
+ >
70
+ > </details>
71
+ <% }) -%>
72
+ <% } -%>
73
+
15
74
  ---
16
75
 
17
76
  <% const c = it.severityCounts %><% const findingsTotal = c.critical + c.major + c.minor + c.nit %>
77
+ <% if (it.unverifiedNoLogs && findingsTotal > 0) { %>
78
+ > [!WARNING]
79
+ > **Unverified โ€” no failing-job logs were available.** This route reads the failing CI job's log to
80
+ > name the failure; none could be staged for this run, so every finding below was reasoned from the
81
+ > diff or from local reproduction of the checks. Treat them as hypotheses until the failing log is
82
+ > checked.
83
+
84
+ <% } %>
85
+
18
86
  <% if (findingsTotal > 0) { %>
19
87
  <% 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) } %>
20
88
  **Findings:** <%~ parts.join(' ยท ') %>
21
- <% } else { %>
22
- _No findings โ€” clean review._
89
+ <% } else if (!it.incomplete && it.systemic.length === 0 && !it.answeredReRaiseNote) { %>
90
+ <% if (it.unverifiedNoLogs) { %>_No findings โ€” but no failing-job logs were staged, so this pass could not read the CI failure. "No findings" is not evidence of none._<% } else { %>_No findings โ€” clean review._<% } %>
23
91
  <% } %>
24
92
 
25
93
  <% if (it.inlineDisposition && it.inlineDisposition.kind === 'posted') { %>
26
- โ†’ <%= 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<% } %>.
94
+ โ†’ <%= 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 %>)<% } %>.
27
95
  <% } else if (it.inlineDisposition && it.inlineDisposition.kind === 'none-in-diff') { %>
28
96
  โ†’ No inline comments โ€” all findings are outside the diff (listed below).
29
- <% } else if (it.inlineDisposition && it.inlineDisposition.kind === 'suppressed-existing-review') { %>
30
- โ†’ Inline review suppressed โ€” `<%= it.inlineDisposition.sha.slice(0, 7) %>` was already reviewed.
97
+ <% } else if (it.inlineDisposition && it.inlineDisposition.kind === 'inline-unavailable') { %>
98
+ โ†’ โš ๏ธ Inline comments couldn't be posted for this review (GitHub rejected a comment's position) โ€” every finding is listed below instead.
99
+ <% } else if (it.inlineDisposition && it.inlineDisposition.kind === 'whole-document') { %>
100
+ โ†’ This run's <%= it.incomplete ? 'review record' : 'complete review' %><% if (it.reviewUrl) { %> โ€” [see the review](<%~ it.reviewUrl %>)<% } %>.
31
101
  <% } %>
32
102
 
33
103
  <% if (it.strays.length > 0) { %>
34
- #### โš ๏ธ Findings outside the diff
35
-
36
- These findings are on lines not in the diff, so they can't be anchored as inline comments:
104
+ ## <% if (it.inlineDisposition && (it.inlineDisposition.kind === 'disabled' || it.inlineDisposition.kind === 'whole-document')) { %>Findings<% } else 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' %><% } %>
105
+ <% if (it.inlineDisposition && it.inlineDisposition.kind === 'no-envelope') { %>
106
+ _Every finding is listed below โ€” the inline review could not be built because the result envelope was missing._
107
+ <% } else if (it.inlineDisposition && it.inlineDisposition.kind === 'whole-document') { %>
108
+ _Every finding from this run<% if (it.inlineDisposition.inlineCount > 0) { %>, including the <%= it.inlineDisposition.inlineCount %> posted as inline comment<%= it.inlineDisposition.inlineCount === 1 ? '' : 's' %> on the diff<% } %><% if (it.inlineDisposition.rejectedCount > 0) { %>; <%= it.inlineDisposition.rejectedCount %> could not be anchored (GitHub rejected the position)<% } %>._
109
+ <% } else if (it.unanchoredCount && it.unanchoredCount > 0) { %>
110
+ _<%= 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<% } %>._
111
+ <% } %>
37
112
 
38
113
  <% it.strays.forEach(function(f) { -%>
39
- - <%= it.severityEmoji(f.severity) %> `<%= f.path %>:<%= f.start_line %><% if (f.start_line !== f.end_line) { %>โ€“<%= f.end_line %><% } %>` โ€” <%= f.title %><% if (typeof f.confidence === "number") { %> ยท confidence <%= f.confidence %><% } %>
40
- <% if (f.reasoning) { -%>
41
- <details><summary>Reasoning</summary>
114
+ ### <%= it.severityEmoji(f.severity) %> (<%= f.severity %>) `<%= f.path %>:<%= f.rangeLabel %><% if (f.side) { %> (<%= f.side %>)<% } %>` โ€” <%= f.title %>
115
+ <sub>confidence <%= it.formatConfidence(f.confidence) %> ยท likelihood <%= it.formatConfidence(f.likelihood) %><% if (f.id) { %> ยท id <% if (f.code_url) { %>[`<%~ f.id %>`](<%~ f.code_url %>)<% } else { %>`<%~ f.id %>`<% } %><% } %></sub>
116
+ <% if (f.permalink) { -%>
117
+
118
+ <%~ f.permalink %><% if (f.permalinkAnchored) { %> ยท _agent-reported location_<% } %>
119
+ <% } -%>
42
120
 
121
+ <%~ f.description %>
122
+ <% if (it.sameRootNotes && Object.prototype.hasOwnProperty.call(it.sameRootNotes, f.idKey)) { -%>
123
+
124
+ > โš ๏ธ <%~ it.sameRootNotes[f.idKey] %>
125
+ <% } -%>
126
+ <% if (f.answeredNote) { -%>
127
+
128
+ > โ†ฉ๏ธ <%~ f.answeredNote %>
129
+ <% } -%>
130
+ <% if (f.recommendation) { -%>
131
+
132
+ **Recommended fix:** <%~ f.recommendation %>
133
+ <% } -%>
134
+ <% if (f.patchProjection.kind === "suggestion") { -%>
135
+
136
+ ```suggestion
137
+ <%~ f.patchProjection.text %>
138
+ ```
139
+ <% } else if (f.patchProjection.kind === "patch") { -%>
140
+
141
+ ```patch
142
+ <%~ f.patchProjection.raw %>
143
+ ```
144
+ <% } -%>
145
+ <% if (f.discussionHtml) { -%>
146
+
147
+ <details><summary>๐Ÿ’ฌ Discussion</summary>
148
+
149
+ <%~ f.discussionHtml %>
150
+ </details>
151
+ <% } -%>
152
+
153
+ > <details><summary>Reasoning</summary>
154
+ >
43
155
  <% f.reasoning.split("\n").forEach(function(rl) { -%>
44
- <%= rl %>
156
+ > <%= rl %>
157
+ <% }) -%>
158
+ >
159
+ > </details>
160
+ <% }) %>
161
+ <% } %>
162
+
163
+ <% if (it.discussionDropped > 0) { %>
164
+ _<%= it.discussionDropped %> discussion thread<%= it.discussionDropped === 1 ? '' : 's' %> not listed<% if ((it.discussionDroppedIds && it.discussionDroppedIds.length > 0) || (it.discussionDroppedSystemicIds && it.discussionDroppedSystemicIds.length > 0) || (it.discussionDroppedOrphanedIds && it.discussionDroppedOrphanedIds.length > 0)) { %> (<% if (it.discussionDroppedIds && it.discussionDroppedIds.length > 0) { %>finding<%= it.discussionDroppedIds.length === 1 ? '' : 's' %> <% it.discussionDroppedIds.forEach(function(id) { %>`<%~ id %>` <% }) %><% if ((it.discussionDroppedSystemicIds && it.discussionDroppedSystemicIds.length > 0) || (it.discussionDroppedOrphanedIds && it.discussionDroppedOrphanedIds.length > 0)) { %>ยท <% } %><% } %><% if (it.discussionDroppedSystemicIds && it.discussionDroppedSystemicIds.length > 0) { %>systemic<%= it.discussionDroppedSystemicIds.length === 1 ? '' : 's' %> <% it.discussionDroppedSystemicIds.forEach(function(id) { %>`<%~ id %>` <% }) %><% if (it.discussionDroppedOrphanedIds && it.discussionDroppedOrphanedIds.length > 0) { %>ยท <% } %><% } %><% if (it.discussionDroppedOrphanedIds && it.discussionDroppedOrphanedIds.length > 0) { %>earlier-round<% if (it.discussionDroppedOrphanedIds.length > 1) { %> (ร—<%= it.discussionDroppedOrphanedIds.length %>)<% } %> <% it.discussionDroppedOrphanedIds.forEach(function(id) { %>`<%~ id %>` <% }) %><% } %>)<% } %><% if (it.discussionDroppedExtra > 0) { %> +<%= it.discussionDroppedExtra %> more<% } %> โ€” the links live on the comment thread._
165
+ <% } %>
166
+
167
+ <% if ((it.orphanedLines && it.orphanedLines.length > 0) || it.orphanedUnresolvable) { %>
168
+ ## ๐Ÿ’ฌ Discussions on findings from earlier rounds
169
+
170
+ <% if (it.orphanedUnresolvable && (!it.orphanedLines || it.orphanedLines.length === 0)) { %>
171
+ _Comments naming tokens outside this round's report could not be matched against the prior findings โ€” the prior findings artifact could not be resolved, so whether they name departed findings is unknown._
172
+ <% } else { %>
173
+ <details><summary>Comments naming findings this round no longer reports (fixed or re-id'd) โ€” the conversation stays discoverable.<% if (it.orphanedTotal > it.orphanedLines.length) { %> (showing <%= it.orphanedLines.length %> of <%= it.orphanedTotal %>)<% } %></summary>
174
+
175
+ <% it.orphanedLines.forEach(function(line) { -%>
176
+ <%~ line %>
45
177
  <% }) -%>
46
178
 
47
- </details>
179
+ </details>
180
+ <% } %>
181
+ <% } %>
182
+
183
+ <% if (it.suppressedNits && it.suppressedNits.length > 0) { %>
184
+ > [!NOTE]
185
+ > <details><summary>๐Ÿ”‡ <%= it.suppressedNits.length %> nit<%= it.suppressedNits.length === 1 ? '' : 's' %> below the visibility floor (confidence ร— likelihood < <%= it.nitVisibilityFloor %>) โ€” hidden</summary>
186
+ >
187
+ <% it.suppressedNits.forEach(function(n) { -%>
188
+ > - `<%= n.path %>:<%= n.startLine %>` โ€” <%= n.title %><% if (n.id) { %> (<% if (n.codeUrl) { %>[`<%~ n.id %>`](<%~ n.codeUrl %>)<% } else { %>`<%~ n.id %>`<% } %>)<% } %> _(m = <%= n.m %>)_
189
+ <% if (n.discussionHtml) { %><%~ n.discussionHtml %><% } %>
190
+ > <%~ '<!-- code-review:suppressed-nit' %>
191
+ > <%~ 'severity: ' + n.severity %>
192
+ > <%~ 'location: ' + n.path + ':' + n.startLine + '-' + n.endLine + (n.side ? ' (' + n.side + ')' : '') %>
193
+ > <%~ 'confidence: ' + n.confidence + ' \u00b7 likelihood: ' + n.likelihood %>
194
+ <% n.carried.forEach(function(cl) { -%>
195
+ > <%~ cl %>
196
+ <% }) -%>
197
+ > <%~ '-->' %>
198
+ <% }) -%>
199
+ <% if (it.carriedDroppedNits > 0) { -%>
200
+ > <%~ '<!-- code-review:suppressed-nit ' + it.carriedDroppedNits + ' nit(s) dropped from the sticky โ€” their findings are in the artifact -->' %>
48
201
  <% } -%>
49
- <% }) %>
202
+ >
203
+ > </details>
50
204
  <% } %>
51
205
 
52
206
  <% if (it.testReport) { %>
@@ -83,5 +237,9 @@ All <%= it.testReport.total %> tests passed.
83
237
  <% } else { -%>
84
238
  > **Usage/cost unavailable** โ€” the result envelope for this run was missing or malformed.
85
239
  <% } -%>
240
+ <% if (it.usageAvailable && !it.pricesProvided) { -%>
241
+ >
242
+ > _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._
243
+ <% } -%>
86
244
  >
87
245
  > _Generated by [code-review](https://github.com/JPHutchins/code-review)<% if (it.runUrl) { %> ยท [view the run & traces](<%~ it.runUrl %>)<% } %>._
@@ -1,19 +1,35 @@
1
- <% if (it.jsonUrl) { -%>
2
- <!-- code-review:findings-json <%~ it.jsonUrl %> -->
1
+ <% if (it.findingsPointer) { -%>
2
+ <%~ it.findingsPointer %>
3
3
  <% } -%>
4
- <%= it.severityEmoji(it.severity) %> **<%= it.severity %>** โ€” <%= it.title %>
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
5
 
6
- <%~ it.body %>
7
- <% if (it.suggestion !== null && it.suggestion !== undefined) { -%>
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") { -%>
8
20
 
9
21
  ```suggestion
10
- <%~ it.suggestion %>
22
+ <%~ it.patchProjection.text %>
23
+ ```
24
+ <% } else if (it.patchProjection.kind === "patch") { -%>
25
+
26
+ ```patch
27
+ <%~ it.patchProjection.raw %>
11
28
  ```
12
29
  <% } -%>
13
30
 
14
31
  > [!TIP]
15
- > Generated by <%~ it.modelsText %><% if (typeof it.confidence === "number") { %> at <%= it.confidence %> confidence<% } %>.
16
- <% if (it.reasoning) { -%>
32
+ > Generated by <%~ it.modelsText %>.
17
33
  > <details>
18
34
  > <summary>Reasoning</summary>
19
35
  >
@@ -22,4 +38,3 @@
22
38
  <% }) -%>
23
39
  >
24
40
  > </details>
25
- <% } -%>