@jphutchins/code-review 0.1.0-alpha.46 → 0.1.0-alpha.48
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/dist/index.js +237 -57
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schema/VERSIONING.md +17 -12
- package/schema/findings.schema.json +34 -0
- package/schema/prices.example.json +8 -2
- package/schema/prices.schema.json +77 -24
- package/templates/comment.eta +12 -3
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.48",
|
|
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
|
@@ -76,21 +76,25 @@ ignored); a version outside the supported set degrades to a §5.5 sticky notice.
|
|
|
76
76
|
|
|
77
77
|
The commenter embeds the agent's **complete** findings document verbatim in review comments
|
|
78
78
|
(`<!-- code-review:findings-json -->`) — no surfaced copy, no added fields (issue #156). The
|
|
79
|
-
deterministic stop signal an iterating author-agent needs
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
marker
|
|
79
|
+
deterministic stop signal an iterating author-agent needs is the pipeline-stamped `convergence` field
|
|
80
|
+
INSIDE that document (issue #174): `{score, threshold, converged}` (a literal boolean, so a decoding
|
|
81
|
+
agent cannot re-derive the weights) plus the per-round `rounds` trajectory. It is the single source of
|
|
82
|
+
truth — the agent never writes it (it cannot know the score; the weights and threshold are
|
|
83
|
+
commenter-side), and the findings schema above describes the whole embedded document, `convergence`
|
|
84
|
+
included. When an oversized review falls to the link form (the blob is a URL, not base64), the same
|
|
85
|
+
stamped object rides a compact `<!-- code-review:convergence -->` marker beside the link (issue #185)
|
|
86
|
+
so the trajectory and stop signal survive; the embedded blob always wins on read.
|
|
87
|
+
|
|
88
|
+
Two older surface formats survive only as READ-ONLY migration inputs — a re-review may still parse a
|
|
89
|
+
sticky posted by an earlier release. Nothing writes either anymore:
|
|
86
90
|
|
|
87
91
|
| Version | Status | Notes |
|
|
88
92
|
|---|---|---|
|
|
89
|
-
| `v0.7.0` |
|
|
90
|
-
| `v0.8.0` |
|
|
93
|
+
| `v0.7.0` | legacy (read-only) | The pre-#156 surface axis: the commenter embedded a **surfaced** copy of the findings document carrying `convergence` + `round` inside it (issue #141). A sticky written by a `0.7.0` release still seeds — `stripSurfaceFields` peels the surfaced copy back to the agent's draft. |
|
|
94
|
+
| `v0.8.0` | legacy (read-only) | The version a compact `<!-- code-review:signal -->` marker declared (and a legacy `0.8.0` surfaced blob). Its writer is retired (issue #186); `parseSignalMarker` / `parseSurfaceSignal` still decode it so a pre-#185 sticky seeds. `0.8.0` also added the agent-facing `scope_metastasis` entry (issue #150): per-code consecutive-round recurrence counts plus a decision prompt. Post-#156 that entry is embedded in no document — the re-review seed re-derives it from the carried trajectory. The flat draft schema (now `v0.9.0`) accepts an optional `scope_metastasis` property so a seed-echoing draft validates — an in-place additive change, deliberately NOT a draft version bump: a draft sharing a `0.7.0`/`0.8.0` number would collide with the surface axis's version gate, so the draft axis skips past them to `0.9.0` (issue #163); the axes must stay distinct so `stripSurfaceFields`/`parseSurfaceSignal` can tell a legacy surfaced blob from a draft). |
|
|
91
95
|
|
|
92
|
-
The surface axis is independent of the draft-version registry:
|
|
93
|
-
|
|
96
|
+
The surface axis is independent of the draft-version registry: it numbers the legacy read-only signal
|
|
97
|
+
formats, while the agent-written document above is `v0.9.0`. `stripSurfaceFields` and
|
|
94
98
|
`parseSurfaceSignal` are version-gated on the surface axis, so a future draft bump can never be
|
|
95
99
|
mistaken for a legacy surfaced blob — and no fresh document is ever surfaced.
|
|
96
100
|
|
|
@@ -102,7 +106,8 @@ policy; the `main` `$id` tracks latest, tagged releases pin to the version. Its
|
|
|
102
106
|
|
|
103
107
|
| Version | Status | Notes |
|
|
104
108
|
|---|---|---|
|
|
105
|
-
| `v0.1.0` |
|
|
109
|
+
| `v0.1.0` | superseded | Initial price-map schema. Per-model `in`/`out`/`cache_read`/`cache_write` (USD per 1M tokens); `_updated` date; `_unit`. |
|
|
110
|
+
| `v0.2.0` | **current** | A model's value is now a `oneOf` (issue #170): the flat shape above, OR `{ "slots": [ { "utc_from", "utc_to", "in", "out", "cache_read", "cache_write" } ] }` — UTC time-of-day pricing (half-open `[utc_from, utc_to)` windows; `utc_to <= utc_from` wraps past midnight; slots must partition the 24h day). Additive/backward-compatible: every flat map keeps validating. |
|
|
106
111
|
|
|
107
112
|
The `_updated` field inside a price-map instance tracks **price drift** (a data concern) and is
|
|
108
113
|
distinct from the schema's semver version (a **contract** concern). Adding a new price field (e.g. a
|
|
@@ -172,6 +172,40 @@
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
},
|
|
175
|
+
"change_size": {
|
|
176
|
+
"type": "object",
|
|
177
|
+
"additionalProperties": false,
|
|
178
|
+
"description": "Best-effort (issue #182): the change's added/removed line counts bucketed by ROLE. Fill this with a LOW-effort path heuristic, no file introspection: a file under a tests directory or matching *.test.* / *_test.* is `tests`; a *.md file, anything under docs/, or a license/config doc is `docs`; everything else is `code`. Sum the diff's added and removed lines per bucket. Omit a role that did not change, or omit the whole field if you cannot estimate it. Chrome only — never affects the verdict or the convergence score. (The per-language cloc table shown beside it is supplied deterministically by the pipeline, not by you.)",
|
|
179
|
+
"properties": {
|
|
180
|
+
"code": {
|
|
181
|
+
"type": "object",
|
|
182
|
+
"additionalProperties": false,
|
|
183
|
+
"required": ["added", "removed"],
|
|
184
|
+
"properties": {
|
|
185
|
+
"added": { "type": "integer", "minimum": 0 },
|
|
186
|
+
"removed": { "type": "integer", "minimum": 0 }
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
"tests": {
|
|
190
|
+
"type": "object",
|
|
191
|
+
"additionalProperties": false,
|
|
192
|
+
"required": ["added", "removed"],
|
|
193
|
+
"properties": {
|
|
194
|
+
"added": { "type": "integer", "minimum": 0 },
|
|
195
|
+
"removed": { "type": "integer", "minimum": 0 }
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
"docs": {
|
|
199
|
+
"type": "object",
|
|
200
|
+
"additionalProperties": false,
|
|
201
|
+
"required": ["added", "removed"],
|
|
202
|
+
"properties": {
|
|
203
|
+
"added": { "type": "integer", "minimum": 0 },
|
|
204
|
+
"removed": { "type": "integer", "minimum": 0 }
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
},
|
|
175
209
|
"findings": {
|
|
176
210
|
"type": "array",
|
|
177
211
|
"description": "Zero or more specific findings.",
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_comment": "USD per 1,000,000 tokens. PRICES DRIFT — keep _updated current. cost = sum over models of (input*in + output*out + cache_read*cache_read + cache_write*cache_write) / 1e6. The CLI's vendor_cost_usd is vendor-priced and will be wrong for non-Anthropic backends; recompute from this map using the `models` array in the abstract result envelope (SPEC §6.1). Fill the zeros from your provider's pricing page.",
|
|
2
|
+
"_comment": "USD per 1,000,000 tokens. PRICES DRIFT — keep _updated current. cost = sum over models of (input*in + output*out + cache_read*cache_read + cache_write*cache_write) / 1e6. A model's value is EITHER a flat all-day price OR a { \"slots\": [...] } set of UTC time-of-day slots for peak/off-peak pricing (issue #170) — see schema/prices.schema.json for the rules: each slot is a half-open [utc_from, utc_to) UTC window, a slot whose utc_to <= utc_from wraps past midnight, and a model's slots must partition the 24h day with no gap or overlap. The CLI's vendor_cost_usd is vendor-priced and will be wrong for non-Anthropic backends; recompute from this map using the `models` array in the abstract result envelope (SPEC §6.1). Fill the zeros from your provider's pricing page.",
|
|
3
3
|
"_updated": "2026-07-03",
|
|
4
4
|
"_unit": "USD per 1M tokens",
|
|
5
5
|
"models": {
|
|
6
6
|
"deepseek-v4-pro": { "in": 0.0, "out": 0.0, "cache_read": 0.0, "cache_write": 0.0 },
|
|
7
|
-
"deepseek-v4-flash": { "in": 0.0, "out": 0.0, "cache_read": 0.0, "cache_write": 0.0 }
|
|
7
|
+
"deepseek-v4-flash": { "in": 0.0, "out": 0.0, "cache_read": 0.0, "cache_write": 0.0 },
|
|
8
|
+
"example-time-slotted-model": {
|
|
9
|
+
"slots": [
|
|
10
|
+
{ "utc_from": "10:00", "utc_to": "01:00", "in": 0.0, "out": 0.0, "cache_read": 0.0, "cache_write": 0.0 },
|
|
11
|
+
{ "utc_from": "01:00", "utc_to": "10:00", "in": 0.0, "out": 0.0, "cache_read": 0.0, "cache_write": 0.0 }
|
|
12
|
+
]
|
|
13
|
+
}
|
|
8
14
|
}
|
|
9
15
|
}
|
|
@@ -21,33 +21,86 @@
|
|
|
21
21
|
},
|
|
22
22
|
"models": {
|
|
23
23
|
"type": "object",
|
|
24
|
-
"description": "Map of model identifier → per-token prices. Keys are the model identifiers as they appear in the result envelope's `models[].model`.",
|
|
24
|
+
"description": "Map of model identifier → per-token prices. Keys are the model identifiers as they appear in the result envelope's `models[].model`. A model's value is EITHER a flat all-day price (unchanged) OR a set of UTC time-of-day slots (issue #170), for a provider with peak/off-peak rates.",
|
|
25
25
|
"additionalProperties": {
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
"oneOf": [
|
|
27
|
+
{
|
|
28
|
+
"type": "object",
|
|
29
|
+
"additionalProperties": false,
|
|
30
|
+
"required": ["in", "out", "cache_read", "cache_write"],
|
|
31
|
+
"properties": {
|
|
32
|
+
"in": {
|
|
33
|
+
"type": "number",
|
|
34
|
+
"minimum": 0,
|
|
35
|
+
"description": "Price per 1M input tokens (cache-miss)."
|
|
36
|
+
},
|
|
37
|
+
"out": {
|
|
38
|
+
"type": "number",
|
|
39
|
+
"minimum": 0,
|
|
40
|
+
"description": "Price per 1M output tokens."
|
|
41
|
+
},
|
|
42
|
+
"cache_read": {
|
|
43
|
+
"type": "number",
|
|
44
|
+
"minimum": 0,
|
|
45
|
+
"description": "Price per 1M cache-read tokens (prompt-cache hits)."
|
|
46
|
+
},
|
|
47
|
+
"cache_write": {
|
|
48
|
+
"type": "number",
|
|
49
|
+
"minimum": 0,
|
|
50
|
+
"description": "Price per 1M cache-write tokens (prompt-cache population)."
|
|
51
|
+
}
|
|
52
|
+
}
|
|
34
53
|
},
|
|
35
|
-
|
|
36
|
-
"type": "
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
{
|
|
55
|
+
"type": "object",
|
|
56
|
+
"additionalProperties": false,
|
|
57
|
+
"required": ["slots"],
|
|
58
|
+
"description": "UTC time-of-day pricing (issue #170). `slots` MUST partition the full 24h UTC day with no gap and no overlap: each is a half-open [utc_from, utc_to) window, and a slot whose utc_to <= utc_from wraps past midnight. Everything is UTC — there is no timezone or DST field. Cost recomputation selects the one slot covering the run's UTC instant; a run's time-of-day matching zero or more than one slot is a misconfiguration that warns loudly and prices that model at $0 (never silently wrong).",
|
|
59
|
+
"properties": {
|
|
60
|
+
"slots": {
|
|
61
|
+
"type": "array",
|
|
62
|
+
"minItems": 1,
|
|
63
|
+
"items": {
|
|
64
|
+
"type": "object",
|
|
65
|
+
"additionalProperties": false,
|
|
66
|
+
"required": ["utc_from", "utc_to", "in", "out", "cache_read", "cache_write"],
|
|
67
|
+
"properties": {
|
|
68
|
+
"utc_from": {
|
|
69
|
+
"type": "string",
|
|
70
|
+
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
|
|
71
|
+
"description": "Slot start, HH:MM in UTC (inclusive)."
|
|
72
|
+
},
|
|
73
|
+
"utc_to": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
|
|
76
|
+
"description": "Slot end, HH:MM in UTC (exclusive); a value <= utc_from wraps past midnight."
|
|
77
|
+
},
|
|
78
|
+
"in": {
|
|
79
|
+
"type": "number",
|
|
80
|
+
"minimum": 0,
|
|
81
|
+
"description": "Price per 1M input tokens (cache-miss) in this slot."
|
|
82
|
+
},
|
|
83
|
+
"out": {
|
|
84
|
+
"type": "number",
|
|
85
|
+
"minimum": 0,
|
|
86
|
+
"description": "Price per 1M output tokens in this slot."
|
|
87
|
+
},
|
|
88
|
+
"cache_read": {
|
|
89
|
+
"type": "number",
|
|
90
|
+
"minimum": 0,
|
|
91
|
+
"description": "Price per 1M cache-read tokens (prompt-cache hits) in this slot."
|
|
92
|
+
},
|
|
93
|
+
"cache_write": {
|
|
94
|
+
"type": "number",
|
|
95
|
+
"minimum": 0,
|
|
96
|
+
"description": "Price per 1M cache-write tokens in this slot."
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
49
102
|
}
|
|
50
|
-
|
|
103
|
+
]
|
|
51
104
|
}
|
|
52
105
|
}
|
|
53
106
|
}
|
package/templates/comment.eta
CHANGED
|
@@ -9,9 +9,6 @@
|
|
|
9
9
|
<% if (it.findingsPointer) { -%>
|
|
10
10
|
<%~ it.findingsPointer %>
|
|
11
11
|
<% } -%>
|
|
12
|
-
<% if (it.roundsMarker) { -%>
|
|
13
|
-
<%~ it.roundsMarker %>
|
|
14
|
-
<% } -%>
|
|
15
12
|
|
|
16
13
|
### <%= it.verdictBadge(it.findings.verdict) %>
|
|
17
14
|
|
|
@@ -23,6 +20,18 @@
|
|
|
23
20
|
<% if (it.convergenceSummary) { -%>
|
|
24
21
|
<sub><%~ it.convergenceSummary %></sub>
|
|
25
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
|
+
<% } -%>
|
|
26
35
|
<% if (it.metastasisNote) { -%>
|
|
27
36
|
<%~ it.metastasisNote %>
|
|
28
37
|
<% } -%>
|