@jphutchins/code-review 0.1.0-alpha.4 → 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 +92 -8
- package/dist/index.js +4008 -446
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/schema/VERSIONING.md +25 -1
- package/schema/findings.schema.json +127 -14
- package/schema/v0.2/findings.schema.json +88 -0
- package/templates/comment.eta +124 -45
- package/templates/inline.eta +36 -5
package/README.md
CHANGED
|
@@ -25,8 +25,9 @@ the security boundary, and the cost.
|
|
|
25
25
|
## The CLI
|
|
26
26
|
|
|
27
27
|
The npm package is the **deterministic commenter** — the presentation and posting layer that no
|
|
28
|
-
model should do, plus the adapter glue between an agent CLI's native output and the
|
|
29
|
-
envelope
|
|
28
|
+
model should do, plus the adapter glue between an agent CLI's native output and the abstract result
|
|
29
|
+
envelope defined in [`src/schema.ts`](src/schema.ts) (the deliverable of
|
|
30
|
+
[SPEC §3.2](SPEC.md#32-the-deliverable)).
|
|
30
31
|
|
|
31
32
|
```sh
|
|
32
33
|
npm install -g @jphutchins/code-review
|
|
@@ -37,11 +38,16 @@ npx @jphutchins/code-review <subcommand>
|
|
|
37
38
|
| Subcommand | What it does |
|
|
38
39
|
| --- | --- |
|
|
39
40
|
| `post` | Post a complete review (inline comments + sticky summary) from findings + envelope + diff — the one-call path |
|
|
40
|
-
| `gather` | Resolve the PR from the CI head SHA and gather the review inputs (diff with git-diff fallback, PR context, prior bot review, failing-job logs) into the workspace for the agent |
|
|
41
|
+
| `gather` | Resolve the PR from the CI head SHA and gather the review inputs (diff with git-diff fallback, PR context, prior bot review, the prior review's answered-findings registry, failing-job logs) into the workspace for the agent |
|
|
42
|
+
| `parse-command` | Resolve a PR's head from its number and parse a ChatOps trigger comment (`/code-review [24m] [$1.00] <instructions>`) into review overrides — the on-demand comment trigger |
|
|
43
|
+
| `react` | Add/remove a GitHub comment reaction — the ChatOps acknowledgement (👀 on receipt, 🚀 on completion) |
|
|
44
|
+
| `await-ci` | Wait for a PR head's CI run to conclude and emit its real conclusion + run id — so an on-demand comment review routes on the CI result (success → full, failure → mechanic) instead of reviewing blind |
|
|
45
|
+
| `check-scope` | Validate + normalize the workflow's `scope` input (the languages/inputs the project accepts) and print the normalized list for the review prompt, or nothing when empty (the reviewer then infers scope from the README's first paragraph); a structurally malformed value is rejected rather than spliced in as-is |
|
|
41
46
|
| `render` | Render the sticky-comment markdown from findings + usage + prices |
|
|
42
47
|
| `inline` | Build the GitHub reviews `comments[]` payload from findings + diff (in-diff validation; strays demote to the summary) |
|
|
43
|
-
| `adapt` | Map a native agent-CLI result envelope onto the abstract
|
|
48
|
+
| `adapt` | Map a native agent-CLI result envelope onto the abstract result envelope (`src/schema.ts`) |
|
|
44
49
|
| `extract` | Recover findings/triage JSON from a native envelope via the deterministic extraction ladder |
|
|
50
|
+
| `validate-patches` | Validate each finding's `patch` against the real PR-head file, aligning the finding's line range to it and keeping the patch (projected into a suggestion at render time), or dropping the patch |
|
|
45
51
|
| `cost` | Recompute USD cost from the envelope's per-model token counts + a price map |
|
|
46
52
|
| `validate` | Validate findings JSON against the published schema |
|
|
47
53
|
| `print-schema` | Print a bundled schema (findings, triage, prices) |
|
|
@@ -62,19 +68,97 @@ in [templates/](templates/). See [docs/adapters.md](docs/adapters.md) for the ad
|
|
|
62
68
|
letting the CLI pick where your key gets sent.
|
|
63
69
|
3. Commit `.github/prices.json` (fork [schema/prices.example.json](schema/prices.example.json) and
|
|
64
70
|
fill in your provider's per-token rates) — without it the cost footer renders **$0**
|
|
65
|
-
([SPEC §
|
|
71
|
+
([SPEC §4.4](SPEC.md#44-required-controls-conformance)).
|
|
66
72
|
4. Merge to your default branch first — `workflow_run` only fires from the default branch, so the
|
|
67
73
|
introducing PR won't review itself — then open a test PR.
|
|
68
74
|
5. First run: consider `egress-policy: audit` to discover the real allowlist, then switch to `block`
|
|
69
|
-
([SPEC
|
|
75
|
+
([SPEC Appendix A](SPEC.md#appendix-a--reference-realization-github-actions-non-normative)).
|
|
76
|
+
6. Optional — add on-demand reviews too: copy
|
|
77
|
+
[examples/workflows/review-on-comment.yaml](examples/workflows/review-on-comment.yaml) so a
|
|
78
|
+
write-access user can comment `/code-review [24m] [$1.00] <instructions>` on a PR to review it
|
|
79
|
+
now, with an optional per-run budget and focus. Comment before CI finishes and it waits for CI and
|
|
80
|
+
routes on the real result (success → full review, failure → mechanic), same as the CI trigger. See the
|
|
81
|
+
[ChatOps section](examples/workflows/README.md#comment--chatops-trigger-on-demand-reviews) for the
|
|
82
|
+
security model.
|
|
70
83
|
|
|
71
84
|
Every model knob is committed step `env` on the workflow's triage and review steps — models,
|
|
72
85
|
efforts, the subagent model, and the tier aliases, right where each is consumed — edited and
|
|
73
|
-
PR-reviewed like the rest of the file (
|
|
74
|
-
|
|
86
|
+
PR-reviewed like the rest of the file (implementation detail the spec deliberately leaves to this
|
|
87
|
+
repo — see [SPEC Appendix A](SPEC.md#appendix-a--reference-realization-github-actions-non-normative)).
|
|
88
|
+
Only the backend endpoint is a per-repo **Actions variable** (`API_BASE_URL`, required, no default); pointing it at
|
|
75
89
|
another provider requires adding that provider's API host to the workflow's egress allowlist in the
|
|
76
90
|
same reviewed PR.
|
|
77
91
|
|
|
92
|
+
## Artifacts
|
|
93
|
+
|
|
94
|
+
The review job uploads two artifacts, each visible from the workflow run the sticky's disclosure
|
|
95
|
+
links to:
|
|
96
|
+
|
|
97
|
+
- **`code-review-findings`** — the findings JSON + result envelope the comment job renders. The
|
|
98
|
+
sticky comment embeds this same JSON directly, base64-encoded, in an
|
|
99
|
+
`<!-- code-review:findings-json;base64 <base64> -->` HTML comment — a reviewing agent (or any
|
|
100
|
+
downstream tool) SHOULD base64-decode and parse that marker rather than parse the comment's prose.
|
|
101
|
+
Embedding in the comment (rather than only linking the artifact) keeps the pointer from expiring
|
|
102
|
+
with artifact retention; when the encoded findings are too large to embed, the sticky falls back to
|
|
103
|
+
a `<!-- code-review:findings-json <url> -->` link marker instead (the linked `findings.json` is the
|
|
104
|
+
agent's draft and lacks the surfaced fields below) — the shared serializer is
|
|
105
|
+
[`src/surface.ts`](src/surface.ts).
|
|
106
|
+
|
|
107
|
+
The embedded document is the **surfaced** findings document: the agent's findings
|
|
108
|
+
(`schema_version` 0.6.0 contract, which is what the review agent is held to and what
|
|
109
|
+
[`schema/findings.schema.json`](schema/findings.schema.json) validates) stamped with the
|
|
110
|
+
`0.8.0` surface version, the pipeline-computed convergence state of the **last completed
|
|
111
|
+
full-review round**, and the advisory `scope_metastasis` entry (issue #150):
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"schema_version": "0.8.0",
|
|
116
|
+
"verdict": "comment",
|
|
117
|
+
"summary": "...",
|
|
118
|
+
"convergence": { "score": 1, "threshold": 1, "converged": true },
|
|
119
|
+
"round": 4,
|
|
120
|
+
"scope_metastasis": {
|
|
121
|
+
"decision_prompt": "Findings keep recurring in the same mechanism across consecutive rounds — each fix keeps enabling the next finding in that machinery. This is a decision, not a directive: state in your summary whether you are committing to the expanding scope (plan the remaining facets of the recurring mechanism(s) above as one unit) or narrowing the scope so the recurrence stops.",
|
|
122
|
+
"recurring": [
|
|
123
|
+
{ "code": "mixin-field-guard-gap", "consecutive_rounds": 4, "start_round": 1 }
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
"findings": []
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`convergence` (`score` = critical·4 + major·2 + minor·1 + nit·0, `threshold` default 1, `converged`
|
|
131
|
+
= score ≤ threshold, as a literal boolean) and `round` (the count of completed full-review rounds)
|
|
132
|
+
are the deterministic **stop signal** for an iterating author-agent: `converged: true` means the
|
|
133
|
+
last completed round is at or below the convergence tolerance, so another iteration round is not
|
|
134
|
+
warranted. The agent never writes these fields — the commenter computes them from the review's own
|
|
135
|
+
severities at render time — and they are omitted until at least one full-review round has
|
|
136
|
+
completed. They survive the "review in progress" banner: the banner replaces only the sticky's
|
|
137
|
+
prose and carries the embedded marker forward verbatim. `scope_metastasis` is the structured
|
|
138
|
+
counterpart of the sticky's "Scope metastasis" warning — per-code consecutive-round counts plus a
|
|
139
|
+
decision prompt — computed from the same rounds history and omitted when no mechanism recurred. It
|
|
140
|
+
is deliberately NOT stripped when a surfaced blob feeds the re-review seed: a decoding agent — and
|
|
141
|
+
the next-round reviewer — must see the recurrence data to answer the scope decision. The 0.8.0
|
|
142
|
+
surfaced contract applies to the **whole-document** marker only; each inline comment embeds a
|
|
143
|
+
per-finding fragment (`schema_version` + one finding) at the draft's own version, since the
|
|
144
|
+
fragment carries no stop signal.
|
|
145
|
+
|
|
146
|
+
Semantics on non-round posts: a mechanic (CI-fix) pass or an envelope-loss post embeds the
|
|
147
|
+
**last completed round's stored signal** (round + its own threshold — never re-derived, so an
|
|
148
|
+
operator changing `convergence_threshold` mid-PR cannot flip a stored `converged`) beside its own
|
|
149
|
+
findings, so the signal always describes the last completed full-review round, not the findings
|
|
150
|
+
that happen to sit beside it. A notice — a post whose verdict is `error` or whose run did not
|
|
151
|
+
complete (empty diff, corrupt output, did-not-complete) — embeds **no** signal in its own blob:
|
|
152
|
+
its document already says no review was produced this run, and a carried `converged` beside that
|
|
153
|
+
would read as a stop signal for a run that produced none; the last completed round's signal still
|
|
154
|
+
survives on the sticky in the compact `<!-- code-review:signal;base64 <base64> -->` marker, so
|
|
155
|
+
the next post reads it back. The same compact marker is emitted when the embedded payload is too
|
|
156
|
+
large and the whole-document marker falls back to the artifact link — an oversized review's stop
|
|
157
|
+
signal stays readable and can be carried forward.
|
|
158
|
+
- **`code-review-transcript`** — the full Claude Code session transcripts for the triage and review
|
|
159
|
+
phases. This is advisory/auditability only: it is never read by the comment job and never affects
|
|
160
|
+
what gets posted.
|
|
161
|
+
|
|
78
162
|
## What's here
|
|
79
163
|
|
|
80
164
|
- **[SPEC.md](SPEC.md)** — the normative, provider-agnostic specification.
|