secondpair 0.1.0
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 +119 -0
- package/dist/bitbucket/comments.d.ts +49 -0
- package/dist/bitbucket/comments.js +198 -0
- package/dist/bitbucket/comments.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +208 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.js +87 -0
- package/dist/config.js.map +1 -0
- package/dist/diff/github.d.ts +14 -0
- package/dist/diff/github.js +27 -0
- package/dist/diff/github.js.map +1 -0
- package/dist/diff/local.d.ts +10 -0
- package/dist/diff/local.js +39 -0
- package/dist/diff/local.js.map +1 -0
- package/dist/diff/parse.d.ts +9 -0
- package/dist/diff/parse.js +141 -0
- package/dist/diff/parse.js.map +1 -0
- package/dist/finding-id.d.ts +28 -0
- package/dist/finding-id.js +96 -0
- package/dist/finding-id.js.map +1 -0
- package/dist/github/comments.d.ts +25 -0
- package/dist/github/comments.js +193 -0
- package/dist/github/comments.js.map +1 -0
- package/dist/gitlab/comments.d.ts +46 -0
- package/dist/gitlab/comments.js +213 -0
- package/dist/gitlab/comments.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/prompt.d.ts +23 -0
- package/dist/llm/prompt.js +53 -0
- package/dist/llm/prompt.js.map +1 -0
- package/dist/llm/schema.d.ts +61 -0
- package/dist/llm/schema.js +73 -0
- package/dist/llm/schema.js.map +1 -0
- package/dist/reconcile.d.ts +20 -0
- package/dist/reconcile.js +70 -0
- package/dist/reconcile.js.map +1 -0
- package/dist/redact.d.ts +3 -0
- package/dist/redact.js +25 -0
- package/dist/redact.js.map +1 -0
- package/dist/report/cli.d.ts +5 -0
- package/dist/report/cli.js +63 -0
- package/dist/report/cli.js.map +1 -0
- package/dist/report/json.d.ts +27 -0
- package/dist/report/json.js +53 -0
- package/dist/report/json.js.map +1 -0
- package/dist/review.d.ts +41 -0
- package/dist/review.js +274 -0
- package/dist/review.js.map +1 -0
- package/dist/suppress-signals.d.ts +7 -0
- package/dist/suppress-signals.js +19 -0
- package/dist/suppress-signals.js.map +1 -0
- package/dist/suppressions.d.ts +6 -0
- package/dist/suppressions.js +48 -0
- package/dist/suppressions.js.map +1 -0
- package/dist/types.d.ts +92 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# secondpair — the second pair of eyes
|
|
2
|
+
|
|
3
|
+
LLM-powered PR reviewer with whole-repo context. Reviews a diff (local,
|
|
4
|
+
staged, or a GitHub/GitLab/Bitbucket PR), posts inline comments, gates CI
|
|
5
|
+
on severity. Uses sibling package [`codengram`](../codengram/README.md) as
|
|
6
|
+
its repo memory so review isn't diff-blind — it sees callers, related
|
|
7
|
+
files, and project context, not just the patch.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install --save-dev secondpair
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Needs an LLM API key (same resolution as `codengram` — set one):
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
export ANTHROPIC_API_KEY=sk-ant-... # default, recommended
|
|
19
|
+
# or: OPENAI_API_KEY / OPENROUTER_API_KEY / CODENGRAM_API_KEY+CODENGRAM_BASE_URL+CODENGRAM_MODEL
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick start
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
cd your-repo
|
|
26
|
+
npx codengram init # one-time: builds repo memory, installs git hooks
|
|
27
|
+
npx secondpair review --staged # review staged changes, print report
|
|
28
|
+
npx secondpair review --base main # review branch vs main
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Nothing to configure to get useful output — defaults are sane
|
|
32
|
+
(`fail_on: high`, `min_confidence: 0.5`). Add `.pr-review.yml` only when you
|
|
33
|
+
want to change them (see [Config](#config)).
|
|
34
|
+
|
|
35
|
+
## Reviewing a real PR (posting comments + CI gate)
|
|
36
|
+
|
|
37
|
+
Pick your platform, set its token, run with `--post`:
|
|
38
|
+
|
|
39
|
+
**GitHub** (GitHub Actions: `GITHUB_TOKEN` is provided automatically)
|
|
40
|
+
```bash
|
|
41
|
+
export GITHUB_TOKEN=ghp_...
|
|
42
|
+
npx secondpair review --pr 123 --repo owner/name --post --fail-on high
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**GitLab** (in GitLab CI, `CI_SERVER_URL`/`CI_PROJECT_ID`/`CI_MERGE_REQUEST_IID`
|
|
46
|
+
are auto-detected; set a token as `GITLAB_TOKEN` or `GL_TOKEN`)
|
|
47
|
+
```bash
|
|
48
|
+
export GITLAB_TOKEN=glpat-...
|
|
49
|
+
npx secondpair review --post --fail-on high # host auto-detected via GITLAB_CI env
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Bitbucket** (`BITBUCKET_WORKSPACE`/`BITBUCKET_PR_ID` auto-detected in
|
|
53
|
+
Bitbucket Pipelines; auth via token or app password)
|
|
54
|
+
```bash
|
|
55
|
+
export BITBUCKET_TOKEN=... # or BITBUCKET_USERNAME + BITBUCKET_APP_PASSWORD
|
|
56
|
+
npx secondpair review --post --fail-on high
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`--host` overrides auto-detection if you're running somewhere the CI env
|
|
60
|
+
vars aren't set. Exit code is 1 when any active finding is at/above
|
|
61
|
+
`fail_on` — wire that into your pipeline as the merge gate.
|
|
62
|
+
|
|
63
|
+
### Example: GitHub Actions
|
|
64
|
+
|
|
65
|
+
```yaml
|
|
66
|
+
- run: npx secondpair review --pr ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --post
|
|
67
|
+
env:
|
|
68
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
69
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Re-running on the same PR (new commit, or CI re-triggered) never
|
|
73
|
+
double-posts — each platform re-checks live existing comment ids right
|
|
74
|
+
before posting, on top of run-to-run fingerprint reconciliation.
|
|
75
|
+
|
|
76
|
+
## Config (`.pr-review.yml`, optional)
|
|
77
|
+
|
|
78
|
+
```yaml
|
|
79
|
+
fail_on: high # critical|high|medium|low|info — CI exit-1 threshold
|
|
80
|
+
min_confidence: 0.5
|
|
81
|
+
ignore: ["**/*.generated.ts", "vendor/**"]
|
|
82
|
+
context_token_budget: 8000 # codengram context injected per chunk
|
|
83
|
+
context_snippets: 3
|
|
84
|
+
categories: # turn any off
|
|
85
|
+
bug: true
|
|
86
|
+
security: true
|
|
87
|
+
missing-tests: true
|
|
88
|
+
naming: true
|
|
89
|
+
complexity: true
|
|
90
|
+
custom: true
|
|
91
|
+
limits:
|
|
92
|
+
max_findings_per_file: 5
|
|
93
|
+
max_total: 30
|
|
94
|
+
self_critique: false # extra LLM pass that only drops findings, never adds
|
|
95
|
+
redact_secrets: true # strip secrets from diff/context before they reach the LLM
|
|
96
|
+
redact_patterns: [] # extra regexes, on top of built-in AWS/GitHub-token/PEM/etc
|
|
97
|
+
write_suppressions: false # persist "won't fix" replies to .pr-review-suppressions.yml
|
|
98
|
+
custom_instructions: ""
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Suppress a finding permanently: reply "won't fix" (or react 👎) on its PR
|
|
102
|
+
comment, or hand-edit `.pr-review-suppressions.yml` with the finding id
|
|
103
|
+
from the report.
|
|
104
|
+
|
|
105
|
+
## `secondpair index`
|
|
106
|
+
|
|
107
|
+
Alias for `codengram index` — kept so a repo can adopt `secondpair` without
|
|
108
|
+
also depending on `codengram` directly for this one command. Same
|
|
109
|
+
incremental behavior; see [codengram's README](../codengram/README.md#staying-in-sync-after-code-changes)
|
|
110
|
+
for exactly when/how re-indexing happens and why it's cheap on repeated
|
|
111
|
+
runs — short version: git-hook-triggered, hash-incremental, never a full
|
|
112
|
+
rebuild unless you pass `--full`.
|
|
113
|
+
|
|
114
|
+
## More detail
|
|
115
|
+
|
|
116
|
+
- Agent-oriented internals reference (pipeline, invariants to preserve when
|
|
117
|
+
editing): [`AGENTS.md`](./AGENTS.md)
|
|
118
|
+
- Architecture review, requirements scorecard, known gaps:
|
|
119
|
+
[`docs/architecture-review.md`](./docs/architecture-review.md)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Finding, ReviewResult } from "../types.js";
|
|
2
|
+
export interface BbRef {
|
|
3
|
+
workspace: string;
|
|
4
|
+
repoSlug: string;
|
|
5
|
+
prId: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Resolve Bitbucket Cloud auth from the environment:
|
|
9
|
+
* BITBUCKET_TOKEN / BITBUCKET_ACCESS_TOKEN -> Bearer (repository access token)
|
|
10
|
+
* BITBUCKET_USERNAME + BITBUCKET_APP_PASSWORD -> Basic (app password)
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveBbAuthHeader(): string;
|
|
13
|
+
/** Resolve workspace/repo/PR id from flags or Bitbucket Pipelines env vars. */
|
|
14
|
+
export declare function resolveBbRef(repoSlug: string | undefined, pr: number | undefined): BbRef;
|
|
15
|
+
/** Fetch the unified diff of a Bitbucket Cloud pull request. */
|
|
16
|
+
export declare function getBbPrDiff(ref: BbRef): Promise<string>;
|
|
17
|
+
interface BbComment {
|
|
18
|
+
id?: number;
|
|
19
|
+
content?: {
|
|
20
|
+
raw?: string;
|
|
21
|
+
};
|
|
22
|
+
inline?: {
|
|
23
|
+
path?: string;
|
|
24
|
+
to?: number;
|
|
25
|
+
};
|
|
26
|
+
parent?: {
|
|
27
|
+
id?: number;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export declare function listBbComments(ref: BbRef): Promise<BbComment[]>;
|
|
31
|
+
export declare function listBbFindingIds(ref: BbRef): Promise<Set<string>>;
|
|
32
|
+
export declare function listBbWontFixFindingIds(ref: BbRef): Promise<Set<string>>;
|
|
33
|
+
/** Bitbucket Cloud exposes no API for resolving pull-request comment threads. */
|
|
34
|
+
export declare function resolveBbCommentsForIds(_ref: BbRef, _ids: Iterable<string>, log?: (msg: string) => void): Promise<number>;
|
|
35
|
+
/** Bitbucket markdown has no GitHub suggestion blocks — render fixes as code fences. */
|
|
36
|
+
export declare function formatBbCommentBody(f: Finding): string;
|
|
37
|
+
export declare function formatBbSummaryBody(result: ReviewResult, failed: boolean): string;
|
|
38
|
+
export interface PostBbReviewOptions {
|
|
39
|
+
ref: BbRef;
|
|
40
|
+
result: ReviewResult;
|
|
41
|
+
failed: boolean;
|
|
42
|
+
log?: (msg: string) => void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Post findings to a Bitbucket Cloud PR: one summary comment plus one inline
|
|
46
|
+
* comment per *new* finding. Persistent findings (same pr-review-id) are skipped.
|
|
47
|
+
*/
|
|
48
|
+
export declare function postBbReview(opts: PostBbReviewOptions): Promise<void>;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { collectIdsFromBodies, embedFindingId, parseFindingId } from "../finding-id.js";
|
|
2
|
+
import { AGENT_MARKER, SEVERITY_EMOJI } from "../github/comments.js";
|
|
3
|
+
import { collectWontFixIds } from "../suppress-signals.js";
|
|
4
|
+
const API = "https://api.bitbucket.org/2.0";
|
|
5
|
+
/**
|
|
6
|
+
* Resolve Bitbucket Cloud auth from the environment:
|
|
7
|
+
* BITBUCKET_TOKEN / BITBUCKET_ACCESS_TOKEN -> Bearer (repository access token)
|
|
8
|
+
* BITBUCKET_USERNAME + BITBUCKET_APP_PASSWORD -> Basic (app password)
|
|
9
|
+
*/
|
|
10
|
+
export function resolveBbAuthHeader() {
|
|
11
|
+
const env = process.env;
|
|
12
|
+
const token = env.BITBUCKET_TOKEN || env.BITBUCKET_ACCESS_TOKEN;
|
|
13
|
+
if (token)
|
|
14
|
+
return `Bearer ${token}`;
|
|
15
|
+
if (env.BITBUCKET_USERNAME && env.BITBUCKET_APP_PASSWORD) {
|
|
16
|
+
const basic = Buffer.from(`${env.BITBUCKET_USERNAME}:${env.BITBUCKET_APP_PASSWORD}`).toString("base64");
|
|
17
|
+
return `Basic ${basic}`;
|
|
18
|
+
}
|
|
19
|
+
throw new Error("Bitbucket auth required: set BITBUCKET_TOKEN (repository access token with pullrequest:write) " +
|
|
20
|
+
"or BITBUCKET_USERNAME + BITBUCKET_APP_PASSWORD.");
|
|
21
|
+
}
|
|
22
|
+
/** Resolve workspace/repo/PR id from flags or Bitbucket Pipelines env vars. */
|
|
23
|
+
export function resolveBbRef(repoSlug, pr) {
|
|
24
|
+
const env = process.env;
|
|
25
|
+
let workspace;
|
|
26
|
+
let slug;
|
|
27
|
+
if (repoSlug) {
|
|
28
|
+
[workspace, slug] = repoSlug.split("/");
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
workspace = env.BITBUCKET_WORKSPACE;
|
|
32
|
+
slug = env.BITBUCKET_REPO_SLUG;
|
|
33
|
+
}
|
|
34
|
+
const prId = pr ?? (env.BITBUCKET_PR_ID ? parseInt(env.BITBUCKET_PR_ID, 10) : undefined);
|
|
35
|
+
if (!workspace || !slug || prId == null || Number.isNaN(prId)) {
|
|
36
|
+
throw new Error("Bitbucket PR not identified. Pass --repo workspace/repo_slug and --pr <id>, " +
|
|
37
|
+
"or run inside Bitbucket Pipelines (BITBUCKET_WORKSPACE / BITBUCKET_REPO_SLUG / BITBUCKET_PR_ID).");
|
|
38
|
+
}
|
|
39
|
+
return { workspace, repoSlug: slug, prId };
|
|
40
|
+
}
|
|
41
|
+
async function bbFetch(url, init = {}) {
|
|
42
|
+
const res = await fetch(url, {
|
|
43
|
+
...init,
|
|
44
|
+
headers: {
|
|
45
|
+
authorization: resolveBbAuthHeader(),
|
|
46
|
+
accept: "application/json",
|
|
47
|
+
...(init.body ? { "content-type": "application/json" } : {}),
|
|
48
|
+
...(init.headers ?? {}),
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
if (!res.ok) {
|
|
52
|
+
const text = await res.text();
|
|
53
|
+
throw new Error(`Bitbucket API ${init.method ?? "GET"} ${url} failed (${res.status}): ${text.slice(0, 400)}`);
|
|
54
|
+
}
|
|
55
|
+
return res;
|
|
56
|
+
}
|
|
57
|
+
/** Fetch the unified diff of a Bitbucket Cloud pull request. */
|
|
58
|
+
export async function getBbPrDiff(ref) {
|
|
59
|
+
const res = await bbFetch(`${API}/repositories/${ref.workspace}/${ref.repoSlug}/pullrequests/${ref.prId}/diff`, { headers: { accept: "text/plain" } });
|
|
60
|
+
return res.text();
|
|
61
|
+
}
|
|
62
|
+
export async function listBbComments(ref) {
|
|
63
|
+
const comments = [];
|
|
64
|
+
let url = `${API}/repositories/${ref.workspace}/${ref.repoSlug}/pullrequests/${ref.prId}/comments?pagelen=100`;
|
|
65
|
+
while (url) {
|
|
66
|
+
const res = await bbFetch(url);
|
|
67
|
+
const page = (await res.json());
|
|
68
|
+
comments.push(...(page.values ?? []));
|
|
69
|
+
url = page.next ?? null;
|
|
70
|
+
}
|
|
71
|
+
return comments;
|
|
72
|
+
}
|
|
73
|
+
export async function listBbFindingIds(ref) {
|
|
74
|
+
const existing = await listBbComments(ref);
|
|
75
|
+
return collectIdsFromBodies(existing.filter((c) => c.content?.raw?.includes(AGENT_MARKER)).map((c) => c.content?.raw ?? ""));
|
|
76
|
+
}
|
|
77
|
+
export async function listBbWontFixFindingIds(ref) {
|
|
78
|
+
const comments = await listBbComments(ref);
|
|
79
|
+
const byId = new Map(comments.flatMap((comment) => (comment.id == null ? [] : [[comment.id, comment]])));
|
|
80
|
+
return collectWontFixIds(comments.map((comment) => {
|
|
81
|
+
let parent = comment.parent?.id == null ? undefined : byId.get(comment.parent.id);
|
|
82
|
+
while (parent) {
|
|
83
|
+
const body = parent.content?.raw ?? "";
|
|
84
|
+
if (body.includes(AGENT_MARKER)) {
|
|
85
|
+
return { body: comment.content?.raw ?? "", parentAgentId: parseFindingId(body) };
|
|
86
|
+
}
|
|
87
|
+
parent = parent.parent?.id == null ? undefined : byId.get(parent.parent.id);
|
|
88
|
+
}
|
|
89
|
+
const body = comment.content?.raw ?? "";
|
|
90
|
+
return { body, isAgent: body.includes(AGENT_MARKER), parentAgentId: null };
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
/** Bitbucket Cloud exposes no API for resolving pull-request comment threads. */
|
|
94
|
+
export async function resolveBbCommentsForIds(_ref, _ids, log = () => { }) {
|
|
95
|
+
log("Bitbucket: soft-resolve not supported; skipping");
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
/** Bitbucket markdown has no GitHub suggestion blocks — render fixes as code fences. */
|
|
99
|
+
export function formatBbCommentBody(f) {
|
|
100
|
+
const parts = [
|
|
101
|
+
`${SEVERITY_EMOJI[f.severity]} **${f.severity.toUpperCase()}** · \`${f.category}\` · confidence ${Math.round(f.confidence * 100)}%`,
|
|
102
|
+
"",
|
|
103
|
+
`**${f.title}**`,
|
|
104
|
+
"",
|
|
105
|
+
f.body.trim(),
|
|
106
|
+
];
|
|
107
|
+
if (f.suggestion) {
|
|
108
|
+
parts.push("", "Suggested fix:", "```", f.suggestion.replace(/\n$/, ""), "```");
|
|
109
|
+
}
|
|
110
|
+
parts.push("", AGENT_MARKER);
|
|
111
|
+
let body = parts.join("\n");
|
|
112
|
+
if (f.id)
|
|
113
|
+
body = embedFindingId(body, f.id);
|
|
114
|
+
return body;
|
|
115
|
+
}
|
|
116
|
+
export function formatBbSummaryBody(result, failed) {
|
|
117
|
+
const counts = {};
|
|
118
|
+
for (const f of result.findings)
|
|
119
|
+
counts[f.severity] = (counts[f.severity] ?? 0) + 1;
|
|
120
|
+
const countLine = result.findings.length === 0
|
|
121
|
+
? "No findings."
|
|
122
|
+
: Object.entries(counts)
|
|
123
|
+
.map(([sev, n]) => `${SEVERITY_EMOJI[sev]} ${n} ${sev}`)
|
|
124
|
+
.join(" · ");
|
|
125
|
+
const recon = result.reconciliation;
|
|
126
|
+
const reconLine = recon
|
|
127
|
+
? `\n_Lifecycle:_ ${recon.new.length} new · ${recon.persistent.length} persistent · ${recon.resolved.length} resolved · ${recon.suppressed.length} suppressed`
|
|
128
|
+
: "";
|
|
129
|
+
return [
|
|
130
|
+
"## PR Review Agent",
|
|
131
|
+
"",
|
|
132
|
+
result.summary.trim(),
|
|
133
|
+
"",
|
|
134
|
+
countLine,
|
|
135
|
+
reconLine,
|
|
136
|
+
failed ? "\n❌ **Check failed**: findings at or above the configured severity threshold." : "",
|
|
137
|
+
AGENT_MARKER,
|
|
138
|
+
].join("\n");
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Post findings to a Bitbucket Cloud PR: one summary comment plus one inline
|
|
142
|
+
* comment per *new* finding. Persistent findings (same pr-review-id) are skipped.
|
|
143
|
+
*/
|
|
144
|
+
export async function postBbReview(opts) {
|
|
145
|
+
const { ref, result, log = () => { } } = opts;
|
|
146
|
+
const commentsUrl = `${API}/repositories/${ref.workspace}/${ref.repoSlug}/pullrequests/${ref.prId}/comments`;
|
|
147
|
+
const existing = await listBbComments(ref);
|
|
148
|
+
const mine = existing.filter((c) => c.content?.raw?.includes(AGENT_MARKER));
|
|
149
|
+
const existingIds = collectIdsFromBodies(mine.map((c) => c.content?.raw ?? ""));
|
|
150
|
+
const alreadySummarized = mine.some((c) => c.inline == null);
|
|
151
|
+
if (!alreadySummarized || result.findings.length === 0) {
|
|
152
|
+
await bbFetch(commentsUrl, {
|
|
153
|
+
method: "POST",
|
|
154
|
+
body: JSON.stringify({ content: { raw: formatBbSummaryBody(result, opts.failed) } }),
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
const toPost = result.findingsToPost ?? result.findings;
|
|
158
|
+
let posted = 0;
|
|
159
|
+
let skipped = 0;
|
|
160
|
+
const failedInline = [];
|
|
161
|
+
for (const f of toPost) {
|
|
162
|
+
if (f.id && existingIds.has(f.id)) {
|
|
163
|
+
skipped++;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
await bbFetch(commentsUrl, {
|
|
168
|
+
method: "POST",
|
|
169
|
+
body: JSON.stringify({
|
|
170
|
+
content: { raw: formatBbCommentBody(f) },
|
|
171
|
+
inline: { path: f.file, to: f.end_line },
|
|
172
|
+
}),
|
|
173
|
+
});
|
|
174
|
+
posted++;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
failedInline.push(f);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (failedInline.length > 0) {
|
|
181
|
+
const body = [
|
|
182
|
+
"### Findings that could not be placed inline",
|
|
183
|
+
...failedInline.map((f) => `- ${SEVERITY_EMOJI[f.severity]} **${f.severity}** \`${f.file}:${f.start_line}-${f.end_line}\` — ${f.title}\n\n ${f.body.split("\n").join("\n ")}`),
|
|
184
|
+
"",
|
|
185
|
+
AGENT_MARKER,
|
|
186
|
+
].join("\n");
|
|
187
|
+
await bbFetch(commentsUrl, { method: "POST", body: JSON.stringify({ content: { raw: body } }) });
|
|
188
|
+
}
|
|
189
|
+
log(`Bitbucket: posted ${posted} inline comment(s)` +
|
|
190
|
+
(skipped ? `, skipped ${skipped} duplicate(s)` : "") +
|
|
191
|
+
(failedInline.length ? `, ${failedInline.length} moved to a summary comment` : "") +
|
|
192
|
+
".");
|
|
193
|
+
const resolvedIds = result.reconciliation?.resolved ?? [];
|
|
194
|
+
if (resolvedIds.length > 0) {
|
|
195
|
+
await resolveBbCommentsForIds(ref, resolvedIds, log);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=comments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/bitbucket/comments.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import pc from "picocolors";
|
|
5
|
+
import { getModel, runIndex } from "codengram";
|
|
6
|
+
import { getBbPrDiff, listBbFindingIds, listBbWontFixFindingIds, postBbReview, resolveBbRef, } from "./bitbucket/comments.js";
|
|
7
|
+
import { getGlMrDiff, listGlFindingIds, listGlWontFixFindingIds, postGlReview, resolveGlRef, } from "./gitlab/comments.js";
|
|
8
|
+
import { loadConfig } from "./config.js";
|
|
9
|
+
import { getPrDiff, getPrHeadSha, makeOctokit, parseRepoSlug } from "./diff/github.js";
|
|
10
|
+
import { getLocalDiff } from "./diff/local.js";
|
|
11
|
+
import { listPostedFindingIds, listWontFixFindingIds, postReview } from "./github/comments.js";
|
|
12
|
+
import { formatReport, shouldFail } from "./report/cli.js";
|
|
13
|
+
import { buildJsonReport, formatRunSummaryLine, loadPreviousFindings, loadPreviousIds, writeJsonReport, } from "./report/json.js";
|
|
14
|
+
import { runReview } from "./review.js";
|
|
15
|
+
import { appendSuppressionIds, loadSuppressions } from "./suppressions.js";
|
|
16
|
+
import { SEVERITIES } from "./types.js";
|
|
17
|
+
const program = new Command();
|
|
18
|
+
const log = (msg) => console.error(pc.dim(msg));
|
|
19
|
+
program
|
|
20
|
+
.name("secondpair")
|
|
21
|
+
.description("secondpair — the second pair of eyes: LLM PR reviewer with a persistent repo memory (codengram) for whole-project context")
|
|
22
|
+
.version("0.1.0");
|
|
23
|
+
program
|
|
24
|
+
.command("index")
|
|
25
|
+
.description("Build or incrementally update the repo memory (.codengram/index.json)")
|
|
26
|
+
.option("--full", "re-index every file regardless of content hash", false)
|
|
27
|
+
.option("--no-llm", "skip LLM summaries (symbols + import graph only; no API key needed)")
|
|
28
|
+
.option("--dir <path>", "repository root", process.cwd())
|
|
29
|
+
.option("--config <path>", "path to .pr-review.yml")
|
|
30
|
+
.action(async (opts) => {
|
|
31
|
+
const cwd = path.resolve(opts.dir);
|
|
32
|
+
const config = await loadConfig(cwd, opts.config);
|
|
33
|
+
const stats = await runIndex({
|
|
34
|
+
cwd,
|
|
35
|
+
full: opts.full,
|
|
36
|
+
llm: opts.llm,
|
|
37
|
+
ignore: config.ignore,
|
|
38
|
+
log,
|
|
39
|
+
});
|
|
40
|
+
console.log(pc.green(`Codemap updated: ${stats.indexed} indexed, ${stats.unchanged} unchanged, ${stats.removed} removed (${stats.total} files).`));
|
|
41
|
+
});
|
|
42
|
+
program
|
|
43
|
+
.command("review")
|
|
44
|
+
.description("Review a diff (local branch, staged changes, or a GitHub/Bitbucket/GitLab PR)")
|
|
45
|
+
.option("--staged", "review staged changes instead of branch vs base", false)
|
|
46
|
+
.option("--base <ref>", "base ref for the local diff (default: auto-detected origin/main)")
|
|
47
|
+
.option("--pr <number>", "pull request number/id to review", (v) => parseInt(v, 10))
|
|
48
|
+
.option("--repo <owner/name>", "repository (GitHub owner/name, Bitbucket workspace/repo_slug, or GitLab group/project; default from CI env vars)")
|
|
49
|
+
.option("--host <host>", "github | bitbucket | gitlab (default: detected from CI env vars, else github)")
|
|
50
|
+
.option("--json <path>", "write findings JSON to this path", "pr-review-report.json")
|
|
51
|
+
.option("--post", "post findings as inline PR review comments", false)
|
|
52
|
+
.option("--fail-on <severity>", `exit 1 at/above this severity (${SEVERITIES.join("|")}); overrides config`)
|
|
53
|
+
.option("--no-context", "review the diff without codemap context")
|
|
54
|
+
.option("--dir <path>", "repository root", process.cwd())
|
|
55
|
+
.option("--config <path>", "path to .pr-review.yml")
|
|
56
|
+
.option("--suppressions <path>", "path to .pr-review-suppressions.yml")
|
|
57
|
+
.option("--write-suppressions", "append won’t-fix finding ids to .pr-review-suppressions.yml", false)
|
|
58
|
+
.action(async (opts) => {
|
|
59
|
+
const cwd = path.resolve(opts.dir);
|
|
60
|
+
const config = await loadConfig(cwd, opts.config);
|
|
61
|
+
if (opts.writeSuppressions)
|
|
62
|
+
config.write_suppressions = true;
|
|
63
|
+
if (opts.failOn) {
|
|
64
|
+
if (!SEVERITIES.includes(opts.failOn)) {
|
|
65
|
+
throw new Error(`--fail-on must be one of: ${SEVERITIES.join(", ")}`);
|
|
66
|
+
}
|
|
67
|
+
config.fail_on = opts.failOn;
|
|
68
|
+
}
|
|
69
|
+
const env = process.env;
|
|
70
|
+
const host = opts.host ??
|
|
71
|
+
(env.BITBUCKET_WORKSPACE || env.BITBUCKET_PR_ID
|
|
72
|
+
? "bitbucket"
|
|
73
|
+
: env.GITLAB_CI
|
|
74
|
+
? "gitlab"
|
|
75
|
+
: "github");
|
|
76
|
+
if (host !== "github" && host !== "bitbucket" && host !== "gitlab") {
|
|
77
|
+
throw new Error(`--host must be github, bitbucket, or gitlab, got "${opts.host}".`);
|
|
78
|
+
}
|
|
79
|
+
const bbPrAvailable = host === "bitbucket" && (opts.pr != null || env.BITBUCKET_PR_ID);
|
|
80
|
+
const glMrAvailable = host === "gitlab" && (opts.pr != null || env.CI_MERGE_REQUEST_IID);
|
|
81
|
+
let diffText;
|
|
82
|
+
let changeDescription;
|
|
83
|
+
let prRef = null;
|
|
84
|
+
let octokit = null;
|
|
85
|
+
let bbRef = null;
|
|
86
|
+
let glRef = null;
|
|
87
|
+
let glDiffRefs = null;
|
|
88
|
+
if (glMrAvailable) {
|
|
89
|
+
glRef = resolveGlRef(opts.repo, opts.pr);
|
|
90
|
+
log(`Fetching diff for project ${decodeURIComponent(glRef.projectId)} MR !${glRef.mrIid} (GitLab)…`);
|
|
91
|
+
const mr = await getGlMrDiff(glRef);
|
|
92
|
+
diffText = mr.diffText;
|
|
93
|
+
glDiffRefs = mr.diffRefs;
|
|
94
|
+
changeDescription = `MR !${glRef.mrIid} in ${decodeURIComponent(glRef.projectId)}`;
|
|
95
|
+
}
|
|
96
|
+
else if (bbPrAvailable) {
|
|
97
|
+
bbRef = resolveBbRef(opts.repo, opts.pr);
|
|
98
|
+
log(`Fetching diff for ${bbRef.workspace}/${bbRef.repoSlug} PR #${bbRef.prId} (Bitbucket)…`);
|
|
99
|
+
diffText = await getBbPrDiff(bbRef);
|
|
100
|
+
changeDescription = `PR #${bbRef.prId} in ${bbRef.workspace}/${bbRef.repoSlug}`;
|
|
101
|
+
}
|
|
102
|
+
else if (opts.pr != null) {
|
|
103
|
+
const slug = opts.repo ?? process.env.GITHUB_REPOSITORY;
|
|
104
|
+
if (!slug)
|
|
105
|
+
throw new Error("Pass --repo owner/name or set GITHUB_REPOSITORY when using --pr.");
|
|
106
|
+
octokit = makeOctokit(process.env.GITHUB_TOKEN);
|
|
107
|
+
prRef = { ...parseRepoSlug(slug), pull_number: opts.pr };
|
|
108
|
+
log(`Fetching diff for ${slug}#${opts.pr}…`);
|
|
109
|
+
diffText = await getPrDiff(octokit, prRef);
|
|
110
|
+
changeDescription = `PR #${opts.pr} in ${slug}`;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
diffText = await getLocalDiff({ cwd, staged: opts.staged, base: opts.base });
|
|
114
|
+
changeDescription = opts.staged
|
|
115
|
+
? "staged changes"
|
|
116
|
+
: `local diff vs ${opts.base ?? "auto-detected base"}`;
|
|
117
|
+
}
|
|
118
|
+
if (diffText.trim() === "") {
|
|
119
|
+
console.log(pc.yellow("Nothing to review — the diff is empty."));
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const jsonPath = path.resolve(cwd, opts.json);
|
|
123
|
+
const previousIds = await loadPreviousIds(jsonPath);
|
|
124
|
+
const previousFindings = await loadPreviousFindings(jsonPath);
|
|
125
|
+
const suppressions = await loadSuppressions(cwd, opts.suppressions);
|
|
126
|
+
const ephemeral = new Set();
|
|
127
|
+
try {
|
|
128
|
+
if (glRef) {
|
|
129
|
+
for (const id of await listGlWontFixFindingIds(glRef))
|
|
130
|
+
ephemeral.add(id);
|
|
131
|
+
}
|
|
132
|
+
else if (bbRef) {
|
|
133
|
+
for (const id of await listBbWontFixFindingIds(bbRef))
|
|
134
|
+
ephemeral.add(id);
|
|
135
|
+
}
|
|
136
|
+
else if (prRef && octokit) {
|
|
137
|
+
for (const id of await listWontFixFindingIds(octokit, prRef))
|
|
138
|
+
ephemeral.add(id);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
log(`Warning: could not scan won’t-fix replies: ${e instanceof Error ? e.message : e}`);
|
|
143
|
+
}
|
|
144
|
+
const suppressedIds = new Set([...suppressions.ids, ...ephemeral]);
|
|
145
|
+
if (opts.post) {
|
|
146
|
+
if (glRef) {
|
|
147
|
+
for (const id of await listGlFindingIds(glRef))
|
|
148
|
+
previousIds.add(id);
|
|
149
|
+
}
|
|
150
|
+
else if (bbRef) {
|
|
151
|
+
for (const id of await listBbFindingIds(bbRef))
|
|
152
|
+
previousIds.add(id);
|
|
153
|
+
}
|
|
154
|
+
else if (prRef && octokit) {
|
|
155
|
+
for (const id of await listPostedFindingIds(octokit, prRef))
|
|
156
|
+
previousIds.add(id);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const result = await runReview({
|
|
160
|
+
cwd,
|
|
161
|
+
diffText,
|
|
162
|
+
config,
|
|
163
|
+
changeDescription,
|
|
164
|
+
useContext: opts.context,
|
|
165
|
+
previousIds,
|
|
166
|
+
previousFindings,
|
|
167
|
+
suppressedIds,
|
|
168
|
+
log,
|
|
169
|
+
});
|
|
170
|
+
if (config.write_suppressions && ephemeral.size) {
|
|
171
|
+
const n = await appendSuppressionIds(cwd, ephemeral, opts.suppressions);
|
|
172
|
+
if (n)
|
|
173
|
+
log(`Wrote ${n} new id(s) to suppressions file.`);
|
|
174
|
+
}
|
|
175
|
+
console.log("\n" + formatReport(result) + "\n");
|
|
176
|
+
await writeJsonReport(jsonPath, buildJsonReport(result, {
|
|
177
|
+
model: getModel(),
|
|
178
|
+
changeDescription,
|
|
179
|
+
usedContext: result.usedContext,
|
|
180
|
+
}));
|
|
181
|
+
log(`Wrote ${jsonPath}`);
|
|
182
|
+
console.error(formatRunSummaryLine(result.stats));
|
|
183
|
+
const failed = shouldFail(result.findings, config.fail_on);
|
|
184
|
+
if (opts.post) {
|
|
185
|
+
if (glRef && glDiffRefs) {
|
|
186
|
+
await postGlReview({ ref: glRef, diffRefs: glDiffRefs, result, failed, log });
|
|
187
|
+
}
|
|
188
|
+
else if (bbRef) {
|
|
189
|
+
await postBbReview({ ref: bbRef, result, failed, log });
|
|
190
|
+
}
|
|
191
|
+
else if (prRef && octokit) {
|
|
192
|
+
const headSha = await getPrHeadSha(octokit, prRef);
|
|
193
|
+
await postReview({ octokit, pr: prRef, headSha, result, failed, log });
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
throw new Error("--post requires a PR (--pr, or Bitbucket/GitLab CI env vars).");
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (failed) {
|
|
200
|
+
console.error(pc.red(`✖ Failing: findings at or above "${config.fail_on}" severity.`));
|
|
201
|
+
process.exitCode = 1;
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
program.parseAsync().catch((err) => {
|
|
205
|
+
console.error(pc.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
206
|
+
process.exit(2);
|
|
207
|
+
});
|
|
208
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { matchesGlob } from "codengram";
|
|
3
|
+
import { type ReviewConfig } from "./types.js";
|
|
4
|
+
export { matchesGlob };
|
|
5
|
+
export declare const DEFAULT_CONFIG: ReviewConfig;
|
|
6
|
+
declare const configSchema: z.ZodObject<{
|
|
7
|
+
fail_on: z.ZodOptional<z.ZodEnum<{
|
|
8
|
+
[x: string]: string;
|
|
9
|
+
}>>;
|
|
10
|
+
min_confidence: z.ZodOptional<z.ZodNumber>;
|
|
11
|
+
ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
12
|
+
context_token_budget: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
context_snippets: z.ZodOptional<z.ZodNumber>;
|
|
14
|
+
custom_instructions: z.ZodOptional<z.ZodString>;
|
|
15
|
+
categories: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
|
|
16
|
+
[x: string]: string;
|
|
17
|
+
}> & z.core.$partial, z.ZodBoolean>>;
|
|
18
|
+
temperature: z.ZodOptional<z.ZodNumber>;
|
|
19
|
+
limits: z.ZodOptional<z.ZodObject<{
|
|
20
|
+
max_findings_per_file: z.ZodOptional<z.ZodNumber>;
|
|
21
|
+
max_total: z.ZodOptional<z.ZodNumber>;
|
|
22
|
+
}, z.core.$strict>>;
|
|
23
|
+
self_critique: z.ZodOptional<z.ZodBoolean>;
|
|
24
|
+
redact_secrets: z.ZodOptional<z.ZodBoolean>;
|
|
25
|
+
redact_patterns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
26
|
+
write_suppressions: z.ZodOptional<z.ZodBoolean>;
|
|
27
|
+
}, z.core.$strict>;
|
|
28
|
+
export declare const CONFIG_FILENAME = ".pr-review.yml";
|
|
29
|
+
/** Load .pr-review.yml from the repo root, merged over defaults. */
|
|
30
|
+
export declare function loadConfig(cwd: string, configPath?: string): Promise<ReviewConfig>;
|
|
31
|
+
export declare function mergeConfig(partial: z.infer<typeof configSchema>): ReviewConfig;
|
|
32
|
+
/** True when the path matches codengram's built-in ignores or this config's patterns. */
|
|
33
|
+
export declare function isIgnored(filePath: string, config: ReviewConfig): boolean;
|