@jphutchins/code-review 0.1.0-alpha.63 → 0.1.0-alpha.65
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 +3 -3
- package/dist/index.js +635 -486
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schema/VERSIONING.md +2 -1
- package/schema/findings.schema.json +9 -1
- package/templates/comment.eta +13 -1
- package/templates/inline.eta +5 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jphutchins/code-review",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.65",
|
|
4
4
|
"description": "Deterministic commenter for agentic PR review — gather, render, inline, post, adapt, extract, cost, validate, print-schema",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/schema/VERSIONING.md
CHANGED
|
@@ -74,7 +74,8 @@ ignored); a version outside the supported set degrades to a §5.5 sticky notice.
|
|
|
74
74
|
| `v0.5.0` | superseded | Widens the `verdict` enum with a pipeline-reserved `error` value: a run that produced no verdict about the diff (operational failure or security refusal) now carries `verdict: "error"` with `findings: []`, so its machine-readable blob is no longer byte-identical to a clean pass. Backwards-compatible (a `0.4` document is a valid `0.5` document); the CLI keeps resolving `0.4` via an identity upcast, so a sticky embedded by a `0.4` CLI still seeds a re-review. |
|
|
75
75
|
| `v0.6.0` | superseded | Adds optional `systemic_problems` — an array of cross-cutting observations that tie findings together and are hard to express with a line range, each item with required `title`/`description`/`severity`/`reasoning`/`confidence` and optional `code`/`code_url`/`finding_codes`/`paths` (no line anchors). Refocuses `summary` on justifying the overall verdict rather than restating findings. Backwards-compatible (a `0.5` document is a valid `0.6` document); the CLI keeps resolving `0.4`/`0.5` via identity upcasts. |
|
|
76
76
|
| `v0.9.0` | superseded (frozen at `schema/v0.9/`) | Adds a REQUIRED `likelihood` (0..1) to every finding and systemic problem (issue #163): the probability the triggering input/state actually occurs — distinct from `confidence` (whether the defect is real) — folded into the convergence score as a second multiplier. **Breaking**: a pre-0.9 document lacks `likelihood` and no longer validates, so a stale sticky degrades to a sentinel-only seed (one cold re-review) rather than seeding. The draft axis skips `0.7`/`0.8`: those are the surface-signal axis's versions (below), so the draft jumps past them to keep the two version spaces distinct — a draft must never be mistaken for a legacy surfaced blob (issue #156). |
|
|
77
|
-
| `v0.10.0` |
|
|
77
|
+
| `v0.10.0` | superseded | Renames the mechanism identifier `code` → `id` and makes it **required** on every finding (issue #246), so every finding is always trackable across rounds and discussions. Systemic problems rename `code`/`finding_codes` → `id`/`finding_ids`; convergence rounds rename `codes` → `ids`; `scope_metastasis.recurring` renames `code` → `id`. `change_size.code` (the role bucket) and `code_url` keep their names. **Breaking**: a pre-0.10 document lacks `id` — the registry upcasts every pre-0.10 minor through one tolerant legacy codec (`code` → `id`, or a synthesized content-derived id — sha256 of path+title — when a finding carried none), so a legacy sticky still seeds a re-review with its ids intact, and the pre-0.10 shape stays frozen at `schema/v0.9/` (above). |
|
|
78
|
+
| `v0.11.0` | **current** (draft) | Adds an optional `rebuttal` to every finding and systemic problem: on a re-raise, the reviewer's answer to the response recorded against that id (the review dialogue, #247). A re-raise that carries a non-blank `rebuttal` is never a verbatim re-raise. A rebuttal answers one round's response, so the re-review seed strips rebuttals from the prior review it carries forward, and a re-raise must supply its own. The legacy codec drops a `rebuttal` on a pre-0.10 document, which the frozen `v0.9` file rejects: the one deliberate codec-only tolerance, since only a hybrid document ever carries one. The systemic `id` description now states that a re-raise of the same class reuses the id. Backwards-compatible: a `0.10` document is a valid `0.11` document, so both minors resolve through the same live file and codec, the way `0.4`–`0.9` share the frozen legacy file. Draft until the next release, so the dialogue's later phases may still add to it. |
|
|
78
79
|
|
|
79
80
|
### Surface channel (stop signal)
|
|
80
81
|
|
|
@@ -46,6 +46,10 @@
|
|
|
46
46
|
"type": "string",
|
|
47
47
|
"description": "Rationale/evidence for why the systemic problem holds, so a human or downstream agent can judge its soundness — distinct from `description`, which explains the pattern to the reader. Mirrors the finding field of the same name."
|
|
48
48
|
},
|
|
49
|
+
"rebuttal": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"description": "On a re-raise, why the response recorded against this id does not hold."
|
|
52
|
+
},
|
|
49
53
|
"confidence": {
|
|
50
54
|
"type": "number",
|
|
51
55
|
"minimum": 0,
|
|
@@ -60,7 +64,7 @@
|
|
|
60
64
|
},
|
|
61
65
|
"id": {
|
|
62
66
|
"type": "string",
|
|
63
|
-
"description": "Stable mechanism identifier (e.g. \"repeated-null-check\") for rule-based filtering, suppression, and cross-run dedup — mirrors the finding field of the same name."
|
|
67
|
+
"description": "Stable mechanism identifier (e.g. \"repeated-null-check\") for rule-based filtering, suppression, and cross-run dedup — mirrors the finding field of the same name. A re-raise of the same class reuses the id."
|
|
64
68
|
},
|
|
65
69
|
"code_url": {
|
|
66
70
|
"type": "string",
|
|
@@ -271,6 +275,10 @@
|
|
|
271
275
|
"type": "string",
|
|
272
276
|
"description": "1-2 sentence markdown prose describing what to do about the finding — distinct from `patch`, which is a machine-applicable unified diff. Use this when the fix is best explained rather than mechanically applied, or to accompany a `patch` with rationale."
|
|
273
277
|
},
|
|
278
|
+
"rebuttal": {
|
|
279
|
+
"type": "string",
|
|
280
|
+
"description": "On a re-raise, why the response recorded against this id does not hold."
|
|
281
|
+
},
|
|
274
282
|
"confidence": {
|
|
275
283
|
"type": "number",
|
|
276
284
|
"minimum": 0,
|
package/templates/comment.eta
CHANGED
|
@@ -47,6 +47,11 @@
|
|
|
47
47
|
<% } -%>
|
|
48
48
|
|
|
49
49
|
<%~ it.findings.summary %>
|
|
50
|
+
<% const c = it.severityCounts %><% const findingsTotal = c.critical + c.major + c.minor + c.nit %>
|
|
51
|
+
<% if (it.teachesResponses && (findingsTotal > 0 || it.systemic.length > 0)) { -%>
|
|
52
|
+
|
|
53
|
+
<sub><%~ it.responseTeaching %></sub>
|
|
54
|
+
<% } -%>
|
|
50
55
|
|
|
51
56
|
<% if (!it.incomplete && it.systemic.length > 0) { -%>
|
|
52
57
|
|
|
@@ -58,6 +63,10 @@
|
|
|
58
63
|
<% 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(' · ') %>_<% } %>
|
|
59
64
|
|
|
60
65
|
<%~ s.description %>
|
|
66
|
+
<% if (it.hasRebuttal(s)) { -%>
|
|
67
|
+
|
|
68
|
+
**Rebuttal:** <%~ s.rebuttal %>
|
|
69
|
+
<% } -%>
|
|
61
70
|
<% if (s.discussionHtml) { -%>
|
|
62
71
|
|
|
63
72
|
<details><summary>💬 Discussion</summary>
|
|
@@ -78,7 +87,6 @@
|
|
|
78
87
|
|
|
79
88
|
---
|
|
80
89
|
|
|
81
|
-
<% const c = it.severityCounts %><% const findingsTotal = c.critical + c.major + c.minor + c.nit %>
|
|
82
90
|
<% if (it.unverifiedNoLogs && findingsTotal > 0) { %>
|
|
83
91
|
> [!WARNING]
|
|
84
92
|
> **Unverified — no failing-job logs were available.** This route reads the failing CI job's log to
|
|
@@ -138,6 +146,10 @@ _<%= it.unanchoredCount %> finding<%= it.unanchoredCount === 1 ? '' : 's' %> bel
|
|
|
138
146
|
|
|
139
147
|
> ↩️ <%~ f.answeredNote %>
|
|
140
148
|
<% } -%>
|
|
149
|
+
<% if (it.hasRebuttal(f)) { -%>
|
|
150
|
+
|
|
151
|
+
**Rebuttal:** <%~ f.rebuttal %>
|
|
152
|
+
<% } -%>
|
|
141
153
|
<% if (f.recommendation) { -%>
|
|
142
154
|
|
|
143
155
|
**Recommended fix:** <%~ f.recommendation %>
|
package/templates/inline.eta
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<% if (it.findingsPointer) { -%>
|
|
2
2
|
<%~ it.findingsPointer %>
|
|
3
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
|
|
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<% if (it.idLabel) { %> · id `<%~ it.idLabel %>`<% } %>
|
|
5
5
|
|
|
6
6
|
<%~ it.description %>
|
|
7
7
|
<% if (it.sameRootNote) { -%>
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
> ↩️ <%~ it.answeredNote %>
|
|
14
14
|
<% } -%>
|
|
15
|
+
<% if (it.hasRebuttal(it)) { -%>
|
|
16
|
+
|
|
17
|
+
**Rebuttal:** <%~ it.rebuttal %>
|
|
18
|
+
<% } -%>
|
|
15
19
|
<% if (it.recommendation) { -%>
|
|
16
20
|
|
|
17
21
|
**Recommended fix:** <%~ it.recommendation %>
|