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

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 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 spec's abstract
29
- envelope ([SPEC §6.1](SPEC.md#61-result-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
@@ -36,13 +37,17 @@ npx @jphutchins/code-review <subcommand>
36
37
 
37
38
  | Subcommand | What it does |
38
39
  | --- | --- |
39
- | `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 |
40
+ | `post` | Post a complete review from findings + envelope + diff — the one-call path. The findings are listed in the sticky summary; `--inline` renders the in-diff ones as comments on the diff instead. Also renders the review into `$GITHUB_STEP_SUMMARY`: the sticky is overwritten each round, the run summary keeps each round as it stood |
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 directory named by `--out-dir` (default: the current directory; the shipped workflows use `$RUNNER_TEMP/gather`) |
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 SPEC §6.1 envelope |
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 |
45
- | `lower-suggestions` | Validate each finding's `patch` against the real PR-head file and lower it to an exact `suggestion` + line range, or drop it |
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 |
46
51
  | `cost` | Recompute USD cost from the envelope's per-model token counts + a price map |
47
52
  | `validate` | Validate findings JSON against the published schema |
48
53
  | `print-schema` | Print a bundled schema (findings, triage, prices) |
@@ -63,16 +68,24 @@ in [templates/](templates/). See [docs/adapters.md](docs/adapters.md) for the ad
63
68
  letting the CLI pick where your key gets sent.
64
69
  3. Commit `.github/prices.json` (fork [schema/prices.example.json](schema/prices.example.json) and
65
70
  fill in your provider's per-token rates) — without it the cost footer renders **$0**
66
- ([SPEC §6.2](SPEC.md#62-price-map)).
71
+ ([SPEC §4.4](SPEC.md#44-required-controls-conformance)).
67
72
  4. Merge to your default branch first — `workflow_run` only fires from the default branch, so the
68
73
  introducing PR won't review itself — then open a test PR.
69
74
  5. First run: consider `egress-policy: audit` to discover the real allowlist, then switch to `block`
70
- ([SPEC §8.4](SPEC.md#84-egress-allowlist)).
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.
71
83
 
72
84
  Every model knob is committed step `env` on the workflow's triage and review steps — models,
73
85
  efforts, the subagent model, and the tier aliases, right where each is consumed — edited and
74
- PR-reviewed like the rest of the file ([SPEC §8.5](SPEC.md#85-model-backend-env)). Only the backend
75
- endpoint is a per-repo **Actions variable** (`API_BASE_URL`, required, no default); pointing it at
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
76
89
  another provider requires adding that provider's API host to the workflow's egress allowlist in the
77
90
  same reviewed PR.
78
91
 
@@ -83,12 +96,67 @@ links to:
83
96
 
84
97
  - **`code-review-findings`** — the findings JSON + result envelope the comment job renders. The
85
98
  sticky comment embeds this same JSON directly, base64-encoded, in an
86
- `<!-- code-review:findings-json;base64 <base64> -->` HTML comment — a reviewing agent (or any
87
- downstream tool) SHOULD base64-decode and parse that marker rather than parse the comment's prose.
99
+ `<!-- code-review:findings-json;base64 <base64> -->` HTML comment. The comment usually renders that
100
+ same review as prose, which is the cheaper read; decode the marker where the prose is not the
101
+ review, where the prose carries only part of it, or where the prose omits a field you need. The directive that rides ahead of the
102
+ marker states that rule.
88
103
  Embedding in the comment (rather than only linking the artifact) keeps the pointer from expiring
89
104
  with artifact retention; when the encoded findings are too large to embed, the sticky falls back to
90
- a `<!-- code-review:findings-json <url> -->` link marker instead
91
- ([SPEC §5.1 item 7](SPEC.md#51-sticky-summary-comment)).
105
+ a `<!-- code-review:findings-json <url> -->` link marker instead. The shared serializer is
106
+ [`src/surface.ts`](src/surface.ts).
107
+
108
+ The embedded document is the agent's **complete** findings document — the same `schema_version`
109
+ 0.10.0 contract the review agent is held to and
110
+ [`schema/findings.schema.json`](schema/findings.schema.json) validates, and the same object the
111
+ comment is rendered from. The agent's fields are embedded verbatim; the pipeline stamps one field the
112
+ agent never writes — `convergence` (below) — so the whole review, findings and convergence signal
113
+ alike, travels as one JSON document with no side marker to drift from.
114
+
115
+ ```json
116
+ {
117
+ "schema_version": "0.10.0",
118
+ "verdict": "comment",
119
+ "summary": "...",
120
+ "findings": [],
121
+ "convergence": {
122
+ "score": 0.42,
123
+ "threshold": 1,
124
+ "converged": true,
125
+ "rounds": [
126
+ { "round": 1, "score": 2.4 },
127
+ { "round": 2, "score": 1.1 },
128
+ { "round": 3, "score": 0.42 }
129
+ ]
130
+ }
131
+ }
132
+ ```
133
+
134
+ The **`convergence`** field is the deterministic stop signal AND the per-round trajectory for an
135
+ iterating author-agent, carried in the JSON document itself so a decoder reads one object.
136
+ `convergence.score` sums each finding and systemic problem's
137
+ `floor(severity) + max(0, ceiling − floor) × confidence × likelihood` (ceilings critical 4 · major 2
138
+ · minor 1 · nit 0; floors critical `threshold + 0.01` · major 0.5 · minor 0.1 · nit 0), rounded to 2
139
+ decimals. A **systemic problem is scored with `likelihood` = 1** — a structural observation has no
140
+ single triggering input, so it is never discounted by likelihood. `threshold` defaults to 1, and
141
+ `converged` = score ≤ threshold as a literal boolean — `converged: true` means the last completed
142
+ round is at or below the tolerance, so another iteration is not warranted. `score` and `threshold`
143
+ are both carried so the number is interpretable on its own. `convergence.rounds` is the trajectory,
144
+ oldest first: each entry's `score` is a historical snapshot carried **verbatim**, so changing
145
+ `convergence_threshold` mid-PR never rewrites a past round's number. The commenter computes
146
+ `convergence` from the review's own severities (the agent never writes it) and stamps it, overwriting
147
+ any value the agent echoed; it appears once at least one full-review round has completed and is carried
148
+ forward afterward — a mechanic (CI-fix) pass or an envelope-loss notice carries the last completed
149
+ round's convergence unchanged rather than re-deriving it, and a notice never fabricates a signal for a
150
+ run that produced no review. The convergence survives the "review in progress" banner, which replaces
151
+ only the sticky's prose and carries the blob forward verbatim.
152
+
153
+ Cross-round recurrence (the sticky's "Scope metastasis" warning) is derived from the per-round
154
+ mechanism frequencies carried in `convergence.rounds` (each entry's `codes` map), from which the
155
+ re-review seed re-derives the advisory `scope_metastasis` entry it hands the next-round agent. Each
156
+ inline review comment embeds only its own finding (a `schema_version` + one-finding fragment), and the
157
+ review-object body links the sticky and the workflow run — so the **sticky is the sole documented decode surface** for
158
+ the whole-document marker; a decoding agent reads it there. The review body is written only after the
159
+ sticky exists (a failed sticky write aborts the run first), so it never carries the blob itself.
92
160
  - **`code-review-transcript`** — the full Claude Code session transcripts for the triage and review
93
161
  phases. This is advisory/auditability only: it is never read by the comment job and never affects
94
162
  what gets posted.