@jphutchins/code-review 0.1.0-alpha.6 → 0.1.0-alpha.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jphutchins/code-review",
3
- "version": "0.1.0-alpha.6",
3
+ "version": "0.1.0-alpha.7",
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",
@@ -66,7 +66,8 @@ ignored); a version outside the supported set degrades to a §5.5 sticky notice.
66
66
  |---|---|---|
67
67
  | `v0.1.0` | superseded | Initial schema. Matches the proven camas reference implementation. |
68
68
  | `v0.2.0` | superseded | Adds required `schema_version`; optional `code`/`code_url` finding fields; normative `suggestion` `""`/`null` semantics; abstract vendor-neutral envelope (see SPEC §6.1). |
69
- | `v0.3.0` | **current** | Adds optional `reasoning` finding field. |
69
+ | `v0.3.0` | superseded | Adds optional `reasoning` finding field. |
70
+ | `v0.4.0` | **current** | Breaking: renames finding `body` → `description`; makes `reasoning` and `confidence` **required**; adds optional `recommendation` (prose fix); removes the free-text `suggestion` field (a `patch`, now `string \| null`, is the sole mechanical fix, projected into a suggestion by the commenter). The CLI supports only `0.4` — `0.2`/`0.3` documents cannot supply the now-required `reasoning`/`confidence`, so they degrade to a §5.5 unsupported-version notice rather than being upcast. |
70
71
 
71
72
  ### Price-map schema
72
73
 
@@ -27,7 +27,16 @@
27
27
  "items": {
28
28
  "type": "object",
29
29
  "additionalProperties": false,
30
- "required": ["path", "start_line", "end_line", "severity", "title", "body"],
30
+ "required": [
31
+ "path",
32
+ "start_line",
33
+ "end_line",
34
+ "severity",
35
+ "title",
36
+ "description",
37
+ "reasoning",
38
+ "confidence"
39
+ ],
31
40
  "properties": {
32
41
  "path": {
33
42
  "type": "string",
@@ -67,27 +76,27 @@
67
76
  "type": "string",
68
77
  "description": "One-line summary of the finding."
69
78
  },
70
- "body": {
79
+ "description": {
71
80
  "type": "string",
72
- "description": "Markdown explanation; rendered as the inline comment body."
81
+ "description": "Markdown explanation of what is wrong; rendered as the inline comment body."
73
82
  },
74
- "suggestion": {
75
- "type": ["string", "null"],
76
- "description": "Proposed replacement text for start_line..end_line: null = no mechanical fix; \"\" (empty string) = the range should be deleted; a non-empty string = the exact, verbatim replacement text, so it must carry correct indentation."
83
+ "recommendation": {
84
+ "type": "string",
85
+ "description": "Markdown prose describing what to do about the finding, in human terms 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."
77
86
  },
78
87
  "confidence": {
79
88
  "type": "number",
80
89
  "minimum": 0,
81
90
  "maximum": 1,
82
- "description": "Optional 0..1 confidence; a commenter MAY suppress findings below a configurable threshold to control noise, but MUST NOT suppress a critical-severity finding on confidence alone."
91
+ "description": "0..1 confidence; a commenter MAY suppress findings below a configurable threshold to control noise, but MUST NOT suppress a critical-severity finding on confidence alone."
83
92
  },
84
93
  "reasoning": {
85
94
  "type": "string",
86
- "description": "Optional rationale/evidence for why the finding holds, so a human or downstream agent can judge its soundness — distinct from `body`, which explains the finding to the reader."
95
+ "description": "Rationale/evidence for why the finding holds, so a human or downstream agent can judge its soundness — distinct from `description`, which explains the finding to the reader."
87
96
  },
88
97
  "patch": {
89
- "type": "string",
90
- "description": "Optional single-hunk unified diff of a mechanical fix, against this file's post-change (RIGHT-side) content. A machine-verifiable alternative to `suggestion`: because it can be validated exactly against the file, a consumer can derive a precise replacement from it or reject it if it no longer applies — preferred over a hand-authored `suggestion`, which is prone to wrong indentation or an over-wide range."
98
+ "type": ["string", "null"],
99
+ "description": "Single-hunk unified diff of a mechanical fix, against this file's post-change (RIGHT-side) content, or null when there is no mechanical fix. Validated exactly against the file and deterministically projected into a suggestion (or dropped) by the commenter, so it never posts with wrong indentation or an over-wide range."
91
100
  }
92
101
  }
93
102
  }
@@ -1,9 +1,7 @@
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.findingsPointer) { -%>
4
+ <%~ it.findingsPointer %>
7
5
  <% } -%>
8
6
 
9
7
  ### <%= it.verdictBadge(it.findings.verdict) %>
@@ -36,8 +34,7 @@ _No findings — clean review._
36
34
  These findings are on lines not in the diff, so they can't be anchored as inline comments:
37
35
 
38
36
  <% 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) { -%>
37
+ - <%= it.severityEmoji(f.severity) %> `<%= f.path %>:<%= f.start_line %><% if (f.start_line !== f.end_line) { %>–<%= f.end_line %><% } %>` — <%= f.title %> · confidence <%= f.confidence %>
41
38
  <details><summary>Reasoning</summary>
42
39
 
43
40
  <% f.reasoning.split("\n").forEach(function(rl) { -%>
@@ -45,6 +42,20 @@ These findings are on lines not in the diff, so they can't be anchored as inline
45
42
  <% }) -%>
46
43
 
47
44
  </details>
45
+ <% if (f.recommendation) { -%>
46
+
47
+ **Recommended fix:** <%~ f.recommendation %>
48
+ <% } -%>
49
+ <% if (f.patchProjection.kind === "suggestion") { -%>
50
+
51
+ ```suggestion
52
+ <%~ f.patchProjection.text %>
53
+ ```
54
+ <% } else if (f.patchProjection.kind === "patch") { -%>
55
+
56
+ ```patch
57
+ <%~ f.patchProjection.raw %>
58
+ ```
48
59
  <% } -%>
49
60
  <% }) %>
50
61
  <% } %>
@@ -83,5 +94,9 @@ All <%= it.testReport.total %> tests passed.
83
94
  <% } else { -%>
84
95
  > **Usage/cost unavailable** — the result envelope for this run was missing or malformed.
85
96
  <% } -%>
97
+ <% if (it.usageAvailable && !it.pricesProvided) { -%>
98
+ >
99
+ > _Cost shown as **N/A** — [No `.github/prices.json`](https://github.com/JPHutchins/code-review/blob/main/SPEC.md#62-price-map) price map to recompute from._
100
+ <% } -%>
86
101
  >
87
102
  > _Generated by [code-review](https://github.com/JPHutchins/code-review)<% if (it.runUrl) { %> · [view the run & traces](<%~ it.runUrl %>)<% } %>._
@@ -1,19 +1,27 @@
1
- <% if (it.jsonUrl) { -%>
2
- <!-- code-review:findings-json <%~ it.jsonUrl %> -->
1
+ <% if (it.findingsPointer) { -%>
2
+ <%~ it.findingsPointer %>
3
3
  <% } -%>
4
4
  <%= it.severityEmoji(it.severity) %> **<%= it.severity %>** — <%= it.title %>
5
5
 
6
- <%~ it.body %>
7
- <% if (it.suggestion !== null && it.suggestion !== undefined) { -%>
6
+ <%~ it.description %>
7
+ <% if (it.recommendation) { -%>
8
+
9
+ **Recommended fix:** <%~ it.recommendation %>
10
+ <% } -%>
11
+ <% if (it.patchProjection.kind === "suggestion") { -%>
8
12
 
9
13
  ```suggestion
10
- <%~ it.suggestion %>
14
+ <%~ it.patchProjection.text %>
15
+ ```
16
+ <% } else if (it.patchProjection.kind === "patch") { -%>
17
+
18
+ ```patch
19
+ <%~ it.patchProjection.raw %>
11
20
  ```
12
21
  <% } -%>
13
22
 
14
23
  > [!TIP]
15
- > Generated by <%~ it.modelsText %><% if (typeof it.confidence === "number") { %> at <%= it.confidence %> confidence<% } %>.
16
- <% if (it.reasoning) { -%>
24
+ > Generated by <%~ it.modelsText %> at <%= it.confidence %> confidence.
17
25
  > <details>
18
26
  > <summary>Reasoning</summary>
19
27
  >
@@ -22,4 +30,3 @@
22
30
  <% }) -%>
23
31
  >
24
32
  > </details>
25
- <% } -%>