@jphutchins/code-review 0.1.0-alpha.40 → 0.1.0-alpha.41
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 +21 -10
- package/dist/index.js +575 -193
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schema/VERSIONING.md +3 -2
- package/schema/findings.schema.json +39 -0
- package/templates/comment.eta +12 -3
- package/templates/inline.eta +4 -0
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.41",
|
|
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
|
@@ -83,9 +83,10 @@ above describes only the agent-written document; the surfaced document has its o
|
|
|
83
83
|
|
|
84
84
|
| Version | Status | Notes |
|
|
85
85
|
|---|---|---|
|
|
86
|
-
| `v0.7.0` |
|
|
86
|
+
| `v0.7.0` | superseded | The surfaced document carries `convergence` + `round` — the deterministic stop signal an iterating author-agent decodes instead of the prose (issue #141). Both are omitted until at least one full-review round has completed, and both survive the in-progress banner (carried forward verbatim with the marker). `stripSurfaceFields` drops them when a surfaced blob feeds back into the agent channel (the re-review seed), restoring the draft version. This surface axis is deliberately **distinct** from the draft axis (now `v0.6.0` after issue #134) so a surfaced doc is never mistaken for an agent-written draft. |
|
|
87
|
+
| `v0.8.0` | **current** | Adds the agent-facing `scope_metastasis` entry (issue #150): per-code consecutive-round recurrence counts plus a decision prompt, computed from the same rounds history the prose metastasis note renders. Unlike `convergence`/`round` it is NOT stripped by `stripSurfaceFields` — the re-review seed must deliver the recurrence data to the next-round agent, so the agent can respond to the scope decision instead of letting the end state emerge piecemeal. To tolerate a seed-echoing draft, the flat draft schema (still `v0.6.0`) additionally accepts an optional `scope_metastasis` property — an in-place additive change, deliberately NOT a draft version bump: a `0.7.0` draft would collide with the surfaced axis's version gate (the axes must stay distinct so `stripSurfaceFields`/`parseSurfaceSignal` can tell a surfaced doc from a draft). |
|
|
87
88
|
|
|
88
|
-
The surfaced axis is independent of the draft-version registry: `v0.
|
|
89
|
+
The surfaced axis is independent of the draft-version registry: `v0.8.0` is the surface shape's
|
|
89
90
|
marker contract, while the agent-written document above remains at `v0.6.0`. `stripSurfaceFields`
|
|
90
91
|
and `parseSurfaceSignal` are version-gated on the surface axis, so a future draft bump can never be
|
|
91
92
|
mistaken for a surfaced document.
|
|
@@ -78,6 +78,45 @@
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
},
|
|
81
|
+
"scope_metastasis": {
|
|
82
|
+
"type": "object",
|
|
83
|
+
"additionalProperties": false,
|
|
84
|
+
"description": "Pipeline-stamped advisory (issue #150): the mechanisms whose findings recurred in consecutive prior full-review rounds — per-code consecutive-round counts plus a decision prompt. The review agent does NOT write this field: the commenter computes it from the carried round history and stamps it into the surfaced document. When it is present in the prior review context of a re-review, respond to the decision prompt — state in your summary whether you are committing to the expanding scope (planning the remaining facets of the recurring mechanism(s) as one unit) or narrowing the scope — so the decision is made explicitly rather than left to emerge piecemeal.",
|
|
85
|
+
"required": ["decision_prompt", "recurring"],
|
|
86
|
+
"properties": {
|
|
87
|
+
"decision_prompt": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"description": "The scope decision to make in the summary of the next review — a decision, not a directive."
|
|
90
|
+
},
|
|
91
|
+
"recurring": {
|
|
92
|
+
"type": "array",
|
|
93
|
+
"description": "The mechanisms flagged: one entry per code whose findings recurred in `consecutive_rounds` or more consecutive completed full-review rounds.",
|
|
94
|
+
"items": {
|
|
95
|
+
"type": "object",
|
|
96
|
+
"additionalProperties": false,
|
|
97
|
+
"required": ["code", "consecutive_rounds", "start_round"],
|
|
98
|
+
"properties": {
|
|
99
|
+
"code": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"description": "The finding code of the recurring mechanism."
|
|
102
|
+
},
|
|
103
|
+
"consecutive_rounds": {
|
|
104
|
+
"type": "integer",
|
|
105
|
+
"minimum": 1,
|
|
106
|
+
"maximum": 9007199254740991,
|
|
107
|
+
"description": "How many consecutive completed full-review rounds (ending at the last completed round) carried a finding with this code. Same-head CI retries are collapsed by the streak detector, so this is the de-duplicated streak, not the raw span: it may be less than `round - start_round + 1` when the history contains retries."
|
|
108
|
+
},
|
|
109
|
+
"start_round": {
|
|
110
|
+
"type": "integer",
|
|
111
|
+
"minimum": 1,
|
|
112
|
+
"maximum": 9007199254740991,
|
|
113
|
+
"description": "The 1-indexed round where the consecutive streak began."
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
},
|
|
81
120
|
"findings": {
|
|
82
121
|
"type": "array",
|
|
83
122
|
"description": "Zero or more specific findings.",
|
package/templates/comment.eta
CHANGED
|
@@ -26,6 +26,9 @@
|
|
|
26
26
|
<% if (it.metastasisNote) { -%>
|
|
27
27
|
<%~ it.metastasisNote %>
|
|
28
28
|
<% } -%>
|
|
29
|
+
<% if (it.answeredReRaiseNote) { -%>
|
|
30
|
+
<%~ it.answeredReRaiseNote %>
|
|
31
|
+
<% } -%>
|
|
29
32
|
<% } -%>
|
|
30
33
|
|
|
31
34
|
<%~ it.findings.summary %>
|
|
@@ -57,7 +60,7 @@
|
|
|
57
60
|
<% if (findingsTotal > 0) { %>
|
|
58
61
|
<% 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) } %>
|
|
59
62
|
**Findings:** <%~ parts.join(' · ') %>
|
|
60
|
-
<% } else if (!it.incomplete && it.systemic.length === 0) { %>
|
|
63
|
+
<% } else if (!it.incomplete && it.systemic.length === 0 && !it.answeredReRaiseNote) { %>
|
|
61
64
|
_No findings — clean review._
|
|
62
65
|
<% } %>
|
|
63
66
|
|
|
@@ -70,8 +73,10 @@ _No findings — clean review._
|
|
|
70
73
|
<% } %>
|
|
71
74
|
|
|
72
75
|
<% if (it.strays.length > 0) { %>
|
|
73
|
-
###
|
|
74
|
-
<% if (it.
|
|
76
|
+
### <% 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' %><% } %>
|
|
77
|
+
<% if (it.inlineDisposition && it.inlineDisposition.kind === 'no-envelope') { %>
|
|
78
|
+
_Every finding is listed below — the inline review could not be built because the result envelope was missing._
|
|
79
|
+
<% } else if (it.unanchoredCount && it.unanchoredCount > 0) { %>
|
|
75
80
|
_<%= 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<% } %>._
|
|
76
81
|
<% } %>
|
|
77
82
|
|
|
@@ -83,6 +88,10 @@ _<%= it.unanchoredCount %> finding<%= it.unanchoredCount === 1 ? '' : 's' %> bel
|
|
|
83
88
|
|
|
84
89
|
> ⚠️ <%~ it.sameRootNotes[f.code] %>
|
|
85
90
|
<% } -%>
|
|
91
|
+
<% if (f.answeredNote) { -%>
|
|
92
|
+
|
|
93
|
+
> ↩️ <%~ f.answeredNote %>
|
|
94
|
+
<% } -%>
|
|
86
95
|
<% if (f.recommendation) { -%>
|
|
87
96
|
|
|
88
97
|
**Recommended fix:** <%~ f.recommendation %>
|