@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.
@@ -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('**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)) } else { meta.push('_usage unavailable_') } %><%~ meta.join(' · ') %>
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 === 'suppressed-existing-review') { %>
25
- → Inline review suppressed — `<%= it.inlineDisposition.sha.slice(0, 7) %>` was already reviewed.
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
- #### ⚠️ Findings outside the diff
30
-
31
- These findings are on lines not in the diff, so they can't be anchored as inline comments:
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
- - <%= it.severityEmoji(f.severity) %> `<%= f.path %>:<%= f.start_line %><% if (f.start_line !== f.end_line) { %>–<%= f.end_line %><% } %>` — <%= f.title %>
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
- <% if (it.usageAvailable && it.costReport.lines.length > 0) { %>
58
- <sub>
59
-
60
- | Model | Input | Output | Cache read | Cache write | Cost |
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
- </sub>
68
- <% } else if (it.usageAvailable) { %>
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
- > [!NOTE]
75
- > **LLM Disclosure** — this review was produced by <%= it.modelNames || "unknown model" %> running
76
- > headless in an ephemeral, egress-locked CI runner with no write access to the repository. It is
77
- > advisory and does not block merge.
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 %>)<% } %>._
@@ -1,9 +1,40 @@
1
- <%~ it.body %>
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.suggestion %>
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
- <sub>🤖 AI-generated — advisory only</sub>
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>