@weareikko/code-review 0.0.1 → 0.8.1
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/LICENSE +105 -0
- package/README.md +221 -0
- package/bin/code-review.js +7 -0
- package/dist/cli-7RGxyNy6.js +6375 -0
- package/dist/cli-7RGxyNy6.js.map +1 -0
- package/dist/cli.d.ts +56 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +2 -0
- package/dist/config.d.ts +205 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/diagnostics.d.ts +118 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diff-lines.d.ts +48 -0
- package/dist/diff-lines.d.ts.map +1 -0
- package/dist/errors.d.ts +69 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/fingerprints.d.ts +22 -0
- package/dist/fingerprints.d.ts.map +1 -0
- package/dist/git.d.ts +50 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/github.d.ts +119 -0
- package/dist/github.d.ts.map +1 -0
- package/dist/gitlab-review.d.ts +210 -0
- package/dist/gitlab-review.d.ts.map +1 -0
- package/dist/gitlab.d.ts +98 -0
- package/dist/gitlab.d.ts.map +1 -0
- package/dist/logger.d.ts +10 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/otel.d.ts +111 -0
- package/dist/otel.d.ts.map +1 -0
- package/dist/parser.d.ts +27 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/payloads.d.ts +30 -0
- package/dist/payloads.d.ts.map +1 -0
- package/dist/platform.d.ts +71 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platforms/github.d.ts +115 -0
- package/dist/platforms/github.d.ts.map +1 -0
- package/dist/platforms/gitlab.d.ts +26 -0
- package/dist/platforms/gitlab.d.ts.map +1 -0
- package/dist/posting.d.ts +108 -0
- package/dist/posting.d.ts.map +1 -0
- package/dist/prior-threads.d.ts +40 -0
- package/dist/prior-threads.d.ts.map +1 -0
- package/dist/product.d.ts +17 -0
- package/dist/product.d.ts.map +1 -0
- package/dist/review.d.ts +18 -0
- package/dist/review.d.ts.map +1 -0
- package/dist/review.js +2 -0
- package/dist/skills.d.ts +92 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skipped-retrieval.d.ts +26 -0
- package/dist/skipped-retrieval.d.ts.map +1 -0
- package/dist/summary-carryover.d.ts +48 -0
- package/dist/summary-carryover.d.ts.map +1 -0
- package/dist/triage.d.ts +37 -0
- package/dist/triage.d.ts.map +1 -0
- package/dist/types.d.ts +95 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/verify.d.ts +74 -0
- package/dist/verify.d.ts.map +1 -0
- package/package.json +90 -2
- package/skills/code-review/SKILL.md +112 -0
- package/skills/code-review/references/javascript-typescript.md +50 -0
- package/skills/code-review/references/php.md +46 -0
- package/skills/test-integrity/SKILL.md +76 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Config } from './config.js';
|
|
2
|
+
import type { Discussion } from './gitlab.js';
|
|
3
|
+
import type { PostingMode, PostResult, SummaryResult, UpsertSummaryOptions } from './posting.js';
|
|
4
|
+
import type { DiffRefs, GeneratedComment, ReviewComment } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* The change under review, normalized across source-control platforms. Mirrors
|
|
7
|
+
* the subset of a GitLab merge request (and a GitHub pull request) that the
|
|
8
|
+
* review engine consumes: the branch pair plus the author's declared intent.
|
|
9
|
+
*/
|
|
10
|
+
export interface MergeRequestMeta {
|
|
11
|
+
source_branch: string;
|
|
12
|
+
target_branch: string;
|
|
13
|
+
/** One-line declared intent of the change. May be empty. */
|
|
14
|
+
title?: string;
|
|
15
|
+
/** The author's full reasoning / decision log. May be empty or null. */
|
|
16
|
+
description?: string | null;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Minimal, telemetry-agnostic view of the most recent HTTP response a platform
|
|
20
|
+
* issued. The diagnostics/OTel layer maps these onto HTTP semantic-convention
|
|
21
|
+
* span attributes without coupling the seam to any observability SDK. Carries no
|
|
22
|
+
* secrets — the auth token travels in a request header, never the URL.
|
|
23
|
+
*/
|
|
24
|
+
export interface ScmResponseInfo {
|
|
25
|
+
method: string;
|
|
26
|
+
url: string;
|
|
27
|
+
status: number;
|
|
28
|
+
/** Parsed Content-Length header in bytes, when the response provided one. */
|
|
29
|
+
responseContentLength?: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The seam every source-control backend implements so `run()` can drive a review
|
|
33
|
+
* without knowing whether it is talking to GitLab or GitHub. The review core
|
|
34
|
+
* (local-git diff, agent, prompt, skills, parser, fingerprints, dedup, summary
|
|
35
|
+
* carryover) stays platform-agnostic; only target identification, reading
|
|
36
|
+
* existing comments, and posting differ per platform and live behind this
|
|
37
|
+
* interface.
|
|
38
|
+
*/
|
|
39
|
+
export interface ReviewPlatform {
|
|
40
|
+
/** Fetch the change's branch pair and declared intent. */
|
|
41
|
+
getMergeRequest(): Promise<MergeRequestMeta>;
|
|
42
|
+
/**
|
|
43
|
+
* Resolve the diff refs. On GitLab these are the MR version base/start/head
|
|
44
|
+
* SHAs; `head_sha` is the reviewed commit used for the reviewed-commit skip
|
|
45
|
+
* marker and the comment/summary footers.
|
|
46
|
+
*/
|
|
47
|
+
getRefs(): Promise<DiffRefs>;
|
|
48
|
+
/** Existing comments, normalized so the shared dedup/summary helpers work unchanged. */
|
|
49
|
+
getDiscussions(): Promise<Discussion[]>;
|
|
50
|
+
/** Turn parsed reviewer findings into platform-specific posting payloads. */
|
|
51
|
+
buildComments(comments: ReviewComment[], diff: string, refs: DiffRefs, existingFingerprints: Set<string>): GeneratedComment[];
|
|
52
|
+
/** Post (or draft-then-publish) the non-duplicate generated comments. */
|
|
53
|
+
postComments(generated: GeneratedComment[], mode: PostingMode): Promise<PostResult>;
|
|
54
|
+
/** Create or update the single MR-level summary note. */
|
|
55
|
+
upsertSummary(summary: string, discussions: Discussion[], options: UpsertSummaryOptions): Promise<SummaryResult>;
|
|
56
|
+
/**
|
|
57
|
+
* The most recent HTTP response this platform issued, for telemetry stamping.
|
|
58
|
+
* Returns `undefined` until the first request completes. Each request reports
|
|
59
|
+
* a fresh object so a phase can compare identity and stamp only its own call.
|
|
60
|
+
*/
|
|
61
|
+
lastResponse(): ScmResponseInfo | undefined;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Build the {@link ReviewPlatform} for this run from the resolved config. The
|
|
65
|
+
* platform was already selected (auto-detected from the environment or forced by
|
|
66
|
+
* `--platform`/`CODE_REVIEW_PLATFORM`) during config resolution; this only
|
|
67
|
+
* constructs the matching backend. GitHub target identifiers are parsed here so a
|
|
68
|
+
* malformed `owner/repo` or pull number fails fast with an actionable hint.
|
|
69
|
+
*/
|
|
70
|
+
export declare function createPlatform(config: Config): ReviewPlatform;
|
|
71
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAO9C,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACjG,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE5E;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,eAAe,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC7C;;;;OAIG;IACH,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7B,wFAAwF;IACxF,cAAc,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACxC,6EAA6E;IAC7E,aAAa,CACX,QAAQ,EAAE,aAAa,EAAE,EACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,QAAQ,EACd,oBAAoB,EAAE,GAAG,CAAC,MAAM,CAAC,GAChC,gBAAgB,EAAE,CAAC;IACtB,yEAAyE;IACzE,YAAY,CAAC,SAAS,EAAE,gBAAgB,EAAE,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACpF,yDAAyD;IACzD,aAAa,CACX,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,UAAU,EAAE,EACzB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,aAAa,CAAC,CAAC;IAC1B;;;;OAIG;IACH,YAAY,IAAI,eAAe,GAAG,SAAS,CAAC;CAC7C;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAY7D"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { type IssueComment, type PullRequestReviewComment } from '../github.js';
|
|
2
|
+
import type { Discussion } from '../gitlab.js';
|
|
3
|
+
import type { MergeRequestMeta, ReviewPlatform, ScmResponseInfo } from '../platform.js';
|
|
4
|
+
import { type PostingMode, type PostResult, type SummaryResult, type UpsertSummaryOptions } from '../posting.js';
|
|
5
|
+
import type { DiffRefs, GeneratedComment, ReviewComment, Side } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* A single inline comment in a batched GitHub review, positioned against the
|
|
8
|
+
* diff. GitHub takes one `line` plus a `side` (unlike GitLab's two-sided
|
|
9
|
+
* position). Built by {@link buildGitHubReviewPayload}; `null` when the finding
|
|
10
|
+
* cannot be anchored to the diff (see {@link buildGitHubComments}).
|
|
11
|
+
*/
|
|
12
|
+
export interface GitHubReviewCommentPayload {
|
|
13
|
+
path: string;
|
|
14
|
+
body: string;
|
|
15
|
+
line: number;
|
|
16
|
+
side: Side;
|
|
17
|
+
}
|
|
18
|
+
/** The `owner` and `repo` halves of a GitHub `owner/repo` slug. */
|
|
19
|
+
export interface GitHubRepository {
|
|
20
|
+
owner: string;
|
|
21
|
+
repo: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Split a `GITHUB_REPOSITORY` slug into its `owner` and `repo` halves. GitHub
|
|
25
|
+
* repository slugs contain exactly one `/` (neither owner nor repo may be empty
|
|
26
|
+
* or contain a slash), so anything else is a configuration error surfaced with an
|
|
27
|
+
* actionable hint rather than a confusing 404 from the API.
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseGitHubRepository(slug: string): GitHubRepository;
|
|
30
|
+
/**
|
|
31
|
+
* Parse a pull-request number from its string form. Rejects non-integer or
|
|
32
|
+
* non-positive values so a malformed `--pr`/`GITHUB_REF` fails fast with a hint
|
|
33
|
+
* instead of hitting `/pulls/NaN`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseGitHubPullNumber(value: string): number;
|
|
36
|
+
/** What a {@link GitHubPlatform} needs to talk to one pull request. */
|
|
37
|
+
export interface GitHubPlatformOptions {
|
|
38
|
+
/** REST API base (default `https://api.github.com`; GHE sets an `/api/v3` base). */
|
|
39
|
+
apiUrl?: string;
|
|
40
|
+
token: string;
|
|
41
|
+
owner: string;
|
|
42
|
+
repo: string;
|
|
43
|
+
/** Pull-request number. */
|
|
44
|
+
pull: number;
|
|
45
|
+
fetchImpl?: typeof fetch;
|
|
46
|
+
requestTimeout?: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolve one reviewer finding to a GitHub review-comment payload, or `null`
|
|
50
|
+
* when it cannot be anchored to GitHub's diff. GitHub uses a single `line` +
|
|
51
|
+
* `side`:
|
|
52
|
+
* - a pure added line takes the new-file line with `side: 'RIGHT'`,
|
|
53
|
+
* - a pure removed line takes the old-file line with `side: 'LEFT'`,
|
|
54
|
+
* - an unchanged (context) line takes the new-file line with `side: 'RIGHT'`,
|
|
55
|
+
* regardless of the finding's side — GitHub's API prescribes RIGHT for
|
|
56
|
+
* "unchanged lines ... shown for context", so a LEFT context comment is
|
|
57
|
+
* doc-noncompliant and risks a 422.
|
|
58
|
+
*
|
|
59
|
+
* Returning `null` for an off-diff line is deliberate: GitHub answers 422 when a
|
|
60
|
+
* review comment points at a line outside the diff, and one such comment fails
|
|
61
|
+
* the whole batched review, so the poster drops these rather than post them. A
|
|
62
|
+
* context line is only kept when it lies within GitHub's default 3-line hunk
|
|
63
|
+
* context of a change — our local diff carries far more context (`--unified=20`)
|
|
64
|
+
* than GitHub's PR diff, so a distant context line is inside our diff but off
|
|
65
|
+
* GitHub's.
|
|
66
|
+
*/
|
|
67
|
+
export declare function buildGitHubReviewPayload(comment: ReviewComment, body: string, diff: string): GitHubReviewCommentPayload | null;
|
|
68
|
+
/**
|
|
69
|
+
* Turn parsed reviewer findings into GitHub review-comment payloads, mirroring
|
|
70
|
+
* the GitLab `buildGeneratedComments` contract: same hunk-context fingerprints,
|
|
71
|
+
* same dedup semantics, same comment body/footer. The payload is
|
|
72
|
+
* `GitHubReviewCommentPayload | null` — `null` for a finding that cannot be
|
|
73
|
+
* placed on the diff, which the poster skips.
|
|
74
|
+
*/
|
|
75
|
+
export declare function buildGitHubComments(comments: ReviewComment[], diff: string, refs: DiffRefs, existingFingerprints: Set<string>): GeneratedComment<GitHubReviewCommentPayload | null>[];
|
|
76
|
+
/**
|
|
77
|
+
* Normalize GitHub's two comment streams into the {@link Discussion}[] shape the
|
|
78
|
+
* platform-agnostic helpers consume unchanged:
|
|
79
|
+
* - Inline **review comments** are threaded by `in_reply_to_id` (a reply joins
|
|
80
|
+
* its root comment's discussion, in arrival order) so `extractPriorThreads`
|
|
81
|
+
* sees a bot note followed by human replies, exactly like GitLab.
|
|
82
|
+
* - Non-positional **issue comments** each become a single-note discussion;
|
|
83
|
+
* the MR-level summary note lives here and is found via its summary marker.
|
|
84
|
+
*
|
|
85
|
+
* The fingerprint markers, summary marker, and reviewed-commit footer are HTML
|
|
86
|
+
* comments that render identically on GitHub, so `extractExistingFingerprints`,
|
|
87
|
+
* `findExistingSummaryNote`, and the reviewed-commit scan all work as-is.
|
|
88
|
+
*/
|
|
89
|
+
export declare function normalizeGitHubDiscussions(reviewComments: PullRequestReviewComment[], issueComments: IssueComment[]): Discussion[];
|
|
90
|
+
/**
|
|
91
|
+
* {@link ReviewPlatform} backed by the GitHub pull-request API. Positioned
|
|
92
|
+
* findings post as ONE batched review (`event: 'COMMENT'`) — atomic and free of
|
|
93
|
+
* per-comment secondary rate limits — and the MR-level summary is upserted as a
|
|
94
|
+
* single issue comment. The review core is unchanged; only target
|
|
95
|
+
* identification, reading existing comments, and posting differ from GitLab.
|
|
96
|
+
*/
|
|
97
|
+
export declare class GitHubPlatform implements ReviewPlatform {
|
|
98
|
+
private readonly client;
|
|
99
|
+
private readonly owner;
|
|
100
|
+
private readonly repo;
|
|
101
|
+
private readonly pull;
|
|
102
|
+
private last;
|
|
103
|
+
private pullRequestPromise;
|
|
104
|
+
private commitId;
|
|
105
|
+
constructor(options: GitHubPlatformOptions);
|
|
106
|
+
lastResponse(): ScmResponseInfo | undefined;
|
|
107
|
+
private pullRequest;
|
|
108
|
+
getMergeRequest(): Promise<MergeRequestMeta>;
|
|
109
|
+
getRefs(): Promise<DiffRefs>;
|
|
110
|
+
getDiscussions(): Promise<Discussion[]>;
|
|
111
|
+
buildComments(comments: ReviewComment[], diff: string, refs: DiffRefs, existingFingerprints: Set<string>): GeneratedComment[];
|
|
112
|
+
postComments(generated: GeneratedComment[], _mode: PostingMode): Promise<PostResult>;
|
|
113
|
+
upsertSummary(summary: string, discussions: Discussion[], options: UpsertSummaryOptions): Promise<SummaryResult>;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/platforms/github.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Config } from '../config.js';
|
|
2
|
+
import { type Discussion } from '../gitlab.js';
|
|
3
|
+
import type { MergeRequestMeta, ReviewPlatform, ScmResponseInfo } from '../platform.js';
|
|
4
|
+
import { type PostingMode, type PostResult, type SummaryResult, type UpsertSummaryOptions } from '../posting.js';
|
|
5
|
+
import type { DiffRefs, GeneratedComment, ReviewComment } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* {@link ReviewPlatform} backed by the GitLab merge-request API. A thin wrapper
|
|
8
|
+
* over the existing {@link GitLabClient}, `payloads.ts`, and `posting.ts`; it
|
|
9
|
+
* carries no review logic of its own so GitLab behavior is byte-for-byte
|
|
10
|
+
* identical to the pre-seam code path.
|
|
11
|
+
*/
|
|
12
|
+
export declare class GitLabPlatform implements ReviewPlatform {
|
|
13
|
+
private readonly client;
|
|
14
|
+
private readonly project;
|
|
15
|
+
private readonly mr;
|
|
16
|
+
private last;
|
|
17
|
+
constructor(config: Config);
|
|
18
|
+
lastResponse(): ScmResponseInfo | undefined;
|
|
19
|
+
getMergeRequest(): Promise<MergeRequestMeta>;
|
|
20
|
+
getRefs(): Promise<DiffRefs>;
|
|
21
|
+
getDiscussions(): Promise<Discussion[]>;
|
|
22
|
+
buildComments(comments: ReviewComment[], diff: string, refs: DiffRefs, existingFingerprints: Set<string>): GeneratedComment[];
|
|
23
|
+
postComments(generated: GeneratedComment[], mode: PostingMode): Promise<PostResult>;
|
|
24
|
+
upsertSummary(summary: string, discussions: Discussion[], options: UpsertSummaryOptions): Promise<SummaryResult>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=gitlab.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitlab.d.ts","sourceRoot":"","sources":["../../src/platforms/gitlab.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,KAAK,UAAU,EAAgB,MAAM,cAAc,CAAC;AAE7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACxF,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,aAAa,EAElB,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE7E;;;;;GAKG;AACH,qBAAa,cAAe,YAAW,cAAc;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAS;IAG5B,OAAO,CAAC,IAAI,CAA8B;IAE1C,YAAY,MAAM,EAAE,MAAM,EAWzB;IAED,YAAY,IAAI,eAAe,GAAG,SAAS,CAE1C;IAED,eAAe,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAE3C;IAEK,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,CAOjC;IAED,cAAc,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAEtC;IAED,aAAa,CACX,QAAQ,EAAE,aAAa,EAAE,EACzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,QAAQ,EACd,oBAAoB,EAAE,GAAG,CAAC,MAAM,CAAC,GAChC,gBAAgB,EAAE,CAEpB;IAED,YAAY,CAAC,SAAS,EAAE,gBAAgB,EAAE,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAElF;IAED,aAAa,CACX,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,UAAU,EAAE,EACzB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,aAAa,CAAC,CAExB;CACF"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { Discussion, GitLabClient } from './gitlab.js';
|
|
2
|
+
import type { GeneratedComment, SizeSkippedFile } from './types.js';
|
|
3
|
+
export declare const SUMMARY_MARKER = "<!-- code-review:summary -->";
|
|
4
|
+
export declare const SUMMARY_HISTORY_START = "<!-- code-review:summary-history:start -->";
|
|
5
|
+
export declare const SUMMARY_HISTORY_END = "<!-- code-review:summary-history:end -->";
|
|
6
|
+
export declare const SUMMARY_HISTORY_ENTRY_START = "<!-- code-review:summary-history-entry:start -->";
|
|
7
|
+
export declare const SUMMARY_HISTORY_ENTRY_END = "<!-- code-review:summary-history-entry:end -->";
|
|
8
|
+
export declare const SUMMARY_HISTORY_LIMIT = 10;
|
|
9
|
+
/**
|
|
10
|
+
* Matches the reviewed-commit footer on read. Both the scope and the repo URL
|
|
11
|
+
* host path accept the current `weareikko` org and the legacy `ikko-dev` org,
|
|
12
|
+
* and both the name segment and the repo name accept the current `code-review`
|
|
13
|
+
* and the legacy `gitlab-review`. The GitHub repo was renamed
|
|
14
|
+
* `weareikko/gitlab-review` → `weareikko/code-review`, so writers now emit the
|
|
15
|
+
* `code-review` URL; matching both keeps the reviewed-commit skip working on
|
|
16
|
+
* MRs/PRs already reviewed under any prior identity.
|
|
17
|
+
*/
|
|
18
|
+
export declare const REVIEWED_COMMIT_FOOTER_PATTERN: RegExp;
|
|
19
|
+
export type SummaryAction = 'created' | 'updated';
|
|
20
|
+
export interface SummaryResult {
|
|
21
|
+
action: SummaryAction;
|
|
22
|
+
noteId?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface SummaryNote {
|
|
25
|
+
id: number;
|
|
26
|
+
body: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* MR-level "this change is too big" signal. Surfaced as a prominent callout at
|
|
30
|
+
* the top of the summary so a reviewer cannot miss that part of the change went
|
|
31
|
+
* unreviewed or that the MR is past a human's reviewability threshold.
|
|
32
|
+
*/
|
|
33
|
+
export interface SizeNotice {
|
|
34
|
+
/** Files dropped for exceeding the char budget. */
|
|
35
|
+
sizeSkippedFiles: SizeSkippedFile[];
|
|
36
|
+
/** Set when the reviewed diff's changed-line count crossed the configured threshold. */
|
|
37
|
+
decomposeHint?: {
|
|
38
|
+
lines: number;
|
|
39
|
+
threshold: number;
|
|
40
|
+
};
|
|
41
|
+
/** Diff coverage when files were dropped: reviewed vs total changed lines. */
|
|
42
|
+
coverage?: {
|
|
43
|
+
reviewedLines: number;
|
|
44
|
+
totalLines: number;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export interface SummaryBodyOptions {
|
|
48
|
+
historyEntries?: string[];
|
|
49
|
+
reviewedCommitSha?: string;
|
|
50
|
+
skillsFooter?: string;
|
|
51
|
+
runId?: string;
|
|
52
|
+
/** Prominent size/decompose callout rendered above the reviewer's summary. */
|
|
53
|
+
sizeNotice?: SizeNotice;
|
|
54
|
+
}
|
|
55
|
+
export interface UpsertSummaryOptions extends SummaryBodyOptions {
|
|
56
|
+
archivedAt?: Date;
|
|
57
|
+
costFooter?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Render the prominent size/decompose callout that sits directly under the
|
|
61
|
+
* "### Code Review" heading. Returns an empty string when there is nothing to
|
|
62
|
+
* surface, so the summary body is byte-for-byte unchanged in the common case.
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildSizeNoticeBlock(notice?: SizeNotice): string;
|
|
65
|
+
export declare function buildSummaryBody(summary: string, costFooter?: string, options?: SummaryBodyOptions): string;
|
|
66
|
+
export declare function buildReviewedCommitFooter(commitSha: string): string;
|
|
67
|
+
export declare function extractReviewedCommitSha(body: string): string | null;
|
|
68
|
+
export declare function findExistingReviewedCommitSha(discussions: Discussion[]): string | null;
|
|
69
|
+
export declare function findExistingSummaryNote(discussions: Discussion[]): SummaryNote | null;
|
|
70
|
+
export declare function findExistingSummaryNoteId(discussions: Discussion[]): number | null;
|
|
71
|
+
export declare function buildArchivedSummaryEntry(body: string, archivedAt?: Date): string;
|
|
72
|
+
export declare function extractSummaryHistoryEntries(body: string): string[];
|
|
73
|
+
export declare function stripSummaryHistory(body: string): string;
|
|
74
|
+
export declare function stripSummaryMarker(body: string): string;
|
|
75
|
+
export declare function buildSummaryHistoryEntries(existingBody: string, archivedAt?: Date): string[];
|
|
76
|
+
/**
|
|
77
|
+
* Resolve the summary upsert into the note body to write plus the existing note
|
|
78
|
+
* to update (or `null` to create). Platform-agnostic — it operates on the
|
|
79
|
+
* normalized {@link Discussion}[] and returns strings/ids — so both the GitLab
|
|
80
|
+
* and GitHub platforms share the exact same body-building and history-carryover
|
|
81
|
+
* logic and only differ in which API call posts the result.
|
|
82
|
+
*/
|
|
83
|
+
export declare function buildUpsertSummary(summary: string, discussions: Discussion[], options: UpsertSummaryOptions): {
|
|
84
|
+
body: string;
|
|
85
|
+
existing: SummaryNote | null;
|
|
86
|
+
};
|
|
87
|
+
export declare function upsertSummaryNote(gitlab: GitLabClient, project: string, mr: string, summary: string, discussions: Discussion[], costFooterOrOptions?: string | UpsertSummaryOptions): Promise<SummaryResult>;
|
|
88
|
+
export type PostingMode = 'direct' | 'draft';
|
|
89
|
+
export declare const POSTING_MODES: readonly PostingMode[];
|
|
90
|
+
export declare const DRAFT_CONCURRENCY = 10;
|
|
91
|
+
export interface PostResult {
|
|
92
|
+
posted: number;
|
|
93
|
+
drafts?: {
|
|
94
|
+
abandoned: number;
|
|
95
|
+
created: number;
|
|
96
|
+
deletedPrePublish: number;
|
|
97
|
+
published: number;
|
|
98
|
+
/**
|
|
99
|
+
* Drafts that survived the pre-publish race check but could not be
|
|
100
|
+
* published, counted only on the per-draft fallback path (a `bulk_publish`
|
|
101
|
+
* 500 forced individual publishes and some still failed). 0 on the normal
|
|
102
|
+
* path. A non-zero value means inline comments were silently dropped.
|
|
103
|
+
*/
|
|
104
|
+
publishFailed: number;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
export declare function postGeneratedComments(gitlab: GitLabClient, project: string, mr: string, generated: GeneratedComment[], mode?: PostingMode): Promise<PostResult>;
|
|
108
|
+
//# sourceMappingURL=posting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"posting.d.ts","sourceRoot":"","sources":["../src/posting.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Discussion, DiscussionNote } from './gitlab.js';
|
|
2
|
+
export interface PriorThread {
|
|
3
|
+
file: string;
|
|
4
|
+
line: number | null;
|
|
5
|
+
resolved: boolean;
|
|
6
|
+
/** Bot comment body with fingerprint markers and emoji prefixes stripped. */
|
|
7
|
+
botComment: string;
|
|
8
|
+
/** Human (non-system) reply bodies, in order. */
|
|
9
|
+
replies: string[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Returns true when the note body contains a code-review fingerprint marker
|
|
13
|
+
* (current or legacy prefix).
|
|
14
|
+
* Used to identify notes posted by the bot without needing a getCurrentUser() call.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isBotNote(note: DiscussionNote): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Parses the `+++ b/<path>` lines from a unified diff and returns the set of
|
|
19
|
+
* new file paths. `/dev/null` (deleted files) is excluded.
|
|
20
|
+
*/
|
|
21
|
+
export declare function extractChangedFiles(diff: string): Set<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Extracts prior review threads from existing MR discussions that are relevant
|
|
24
|
+
* to the current diff.
|
|
25
|
+
*
|
|
26
|
+
* A thread is included when:
|
|
27
|
+
* - It contains at least one bot note (identified by fingerprint marker).
|
|
28
|
+
* - It contains at least one non-system human reply after the bot note.
|
|
29
|
+
* - The thread's file appears in `changedFiles`.
|
|
30
|
+
*
|
|
31
|
+
* Resolved threads are included but marked with `resolved: true` so the
|
|
32
|
+
* reviewer can reference them without re-raising the concern.
|
|
33
|
+
*/
|
|
34
|
+
export declare function extractPriorThreads(discussions: Discussion[], changedFiles: Set<string>): PriorThread[];
|
|
35
|
+
/**
|
|
36
|
+
* Renders a `<prior_review_feedback>` XML block from a list of prior threads.
|
|
37
|
+
* Returns an empty string when `threads` is empty.
|
|
38
|
+
*/
|
|
39
|
+
export declare function renderPriorThreadsBlock(threads: PriorThread[]): string;
|
|
40
|
+
//# sourceMappingURL=prior-threads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prior-threads.d.ts","sourceRoot":"","sources":["../src/prior-threads.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAI9D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAEvD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAS7D;AAkBD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,UAAU,EAAE,EACzB,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,GACxB,WAAW,EAAE,CAsCf;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAmBtE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The published package name, shown in review footers. Independent of the review
|
|
3
|
+
* platform: the same tool posts to GitLab and GitHub, so the footer identifies
|
|
4
|
+
* the tool, not the backend. Kept as a single source of truth so the inline and
|
|
5
|
+
* summary footers can never drift apart.
|
|
6
|
+
*/
|
|
7
|
+
export declare const PRODUCT_NAME = "@weareikko/code-review";
|
|
8
|
+
/** Canonical project URL used in the footer's markdown link. */
|
|
9
|
+
export declare const PRODUCT_URL = "https://github.com/weareikko/code-review";
|
|
10
|
+
/**
|
|
11
|
+
* The `[name](url)` markdown link used verbatim in both the inline comment footer
|
|
12
|
+
* ({@link buildCommentBody}) and the reviewed-commit summary footer
|
|
13
|
+
* ({@link buildReviewedCommitFooter}). Changing this changes the reviewed-commit
|
|
14
|
+
* footer format, which is guarded by a migration test.
|
|
15
|
+
*/
|
|
16
|
+
export declare const PRODUCT_LINK = "[@weareikko/code-review](https://github.com/weareikko/code-review)";
|
|
17
|
+
//# sourceMappingURL=product.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product.d.ts","sourceRoot":"","sources":["../src/product.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,YAAY,2BAA2B,CAAC;AAErD,gEAAgE;AAChE,eAAO,MAAM,WAAW,6CAA6C,CAAC;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,YAAY,uEAAsC,CAAC"}
|
package/dist/review.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type { DiagnosticContext, DiagnosticError, DiagnosticPhase, DiagnosticUsage, DiagnosticUsageBreakdown, } from './diagnostics.js';
|
|
2
|
+
export { DIAGNOSTIC_CHANNEL_NAMES, DIAGNOSTIC_CHANNEL_PREFIX, createDiagnosticContext, createDiagnosticRunId, diagnosticChannels, traceDiagnostic, traceDiagnosticPhase, } from './diagnostics.js';
|
|
3
|
+
export type { OtelBridge, OtelBridgeOptions, OtelRuntime } from './otel.js';
|
|
4
|
+
export { isOtelEnabled, startOtelBridge } from './otel.js';
|
|
5
|
+
export type { RunBridges, RunResult } from './cli.js';
|
|
6
|
+
export { run } from './cli.js';
|
|
7
|
+
export type { AgentLike, CreateAgent, CreateAgentParams, FilteredDiff, ModelUsage, ReviewIntent, ReviewSizeNotice, ReviewUsage, RunReviewOptions, UsageBreakdown, } from './gitlab-review.js';
|
|
8
|
+
export { filterDiff } from './gitlab-review.js';
|
|
9
|
+
export { runReview } from './gitlab-review.js';
|
|
10
|
+
export type { DiffRefs, Fingerprints, GeneratedComment, GitLabDiscussionPayload, ReviewComment, Side, SizeSkippedFile, } from './types.js';
|
|
11
|
+
export { normalizeSeverity, toGitLabReviewSeverity } from './types.js';
|
|
12
|
+
export { parseReviewMarkdown, parseReviewMarkdownWithWarnings, type ParseFailure, type ParseFailureReason, type ParseResult, } from './parser.js';
|
|
13
|
+
export { appendFingerprintMarkers, extractDiffHunkContext, extractExistingFingerprints, fingerprints, normalizeBody, sha256, } from './fingerprints.js';
|
|
14
|
+
export { buildGeneratedComments, buildPayload } from './payloads.js';
|
|
15
|
+
export type { LoadNamedSkillOptions, Skill, SkillSpec } from './skills.js';
|
|
16
|
+
export { gitSkillCacheKey, loadNamedSkill, parseSkillSpec, resolveNpmSkillDir, resolveSkillCacheDir, } from './skills.js';
|
|
17
|
+
export { SUMMARY_HISTORY_END, SUMMARY_HISTORY_ENTRY_END, SUMMARY_HISTORY_ENTRY_START, SUMMARY_HISTORY_LIMIT, SUMMARY_HISTORY_START, SUMMARY_MARKER, buildArchivedSummaryEntry, buildSizeNoticeBlock, buildSummaryBody, buildReviewedCommitFooter, buildSummaryHistoryEntries, extractReviewedCommitSha, extractSummaryHistoryEntries, findExistingReviewedCommitSha, findExistingSummaryNote, findExistingSummaryNoteId, stripSummaryHistory, stripSummaryMarker, upsertSummaryNote, type SizeNotice, type SummaryAction, type SummaryBodyOptions, type SummaryNote, type SummaryResult, type UpsertSummaryOptions, } from './posting.js';
|
|
18
|
+
//# sourceMappingURL=review.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../src/review.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC3D,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,YAAY,EACV,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,uBAAuB,EACvB,aAAa,EACb,IAAI,EACJ,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EACL,mBAAmB,EACnB,+BAA+B,EAC/B,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,2BAA2B,EAC3B,YAAY,EACZ,aAAa,EACb,MAAM,GACP,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACrE,YAAY,EAAE,qBAAqB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,2BAA2B,EAC3B,qBAAqB,EACrB,qBAAqB,EACrB,cAAc,EACd,yBAAyB,EACzB,oBAAoB,EACpB,gBAAgB,EAChB,yBAAyB,EACzB,0BAA0B,EAC1B,wBAAwB,EACxB,4BAA4B,EAC5B,6BAA6B,EAC7B,uBAAuB,EACvB,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,oBAAoB,GAC1B,MAAM,cAAc,CAAC"}
|
package/dist/review.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { $ as normalizeBody, A as SUMMARY_HISTORY_END, B as buildSummaryHistoryEntries, C as createDiagnosticContext, D as traceDiagnosticPhase, E as traceDiagnostic, F as SUMMARY_MARKER, G as findExistingSummaryNoteId, H as extractSummaryHistoryEntries, I as buildArchivedSummaryEntry, J as upsertSummaryNote, K as stripSummaryHistory, L as buildReviewedCommitFooter, M as SUMMARY_HISTORY_ENTRY_START, N as SUMMARY_HISTORY_LIMIT, O as normalizeSeverity, P as SUMMARY_HISTORY_START, Q as fingerprints, R as buildSizeNoticeBlock, S as DIAGNOSTIC_CHANNEL_PREFIX, T as diagnosticChannels, U as findExistingReviewedCommitSha, V as extractReviewedCommitSha, W as findExistingSummaryNote, X as extractDiffHunkContext, Y as appendFingerprintMarkers, Z as extractExistingFingerprints, _ as resolveNpmSkillDir, b as parseReviewMarkdownWithWarnings, c as buildGeneratedComments, d as startOtelBridge, et as sha256, f as filterDiff, g as parseSkillSpec, h as loadNamedSkill, j as SUMMARY_HISTORY_ENTRY_END, k as toGitLabReviewSeverity, l as buildPayload, m as gitSkillCacheKey, o as run, p as runReview, q as stripSummaryMarker, u as isOtelEnabled, v as resolveSkillCacheDir, w as createDiagnosticRunId, x as DIAGNOSTIC_CHANNEL_NAMES, y as parseReviewMarkdown, z as buildSummaryBody } from "./cli-7RGxyNy6.js";
|
|
2
|
+
export { DIAGNOSTIC_CHANNEL_NAMES, DIAGNOSTIC_CHANNEL_PREFIX, SUMMARY_HISTORY_END, SUMMARY_HISTORY_ENTRY_END, SUMMARY_HISTORY_ENTRY_START, SUMMARY_HISTORY_LIMIT, SUMMARY_HISTORY_START, SUMMARY_MARKER, appendFingerprintMarkers, buildArchivedSummaryEntry, buildGeneratedComments, buildPayload, buildReviewedCommitFooter, buildSizeNoticeBlock, buildSummaryBody, buildSummaryHistoryEntries, createDiagnosticContext, createDiagnosticRunId, diagnosticChannels, extractDiffHunkContext, extractExistingFingerprints, extractReviewedCommitSha, extractSummaryHistoryEntries, filterDiff, findExistingReviewedCommitSha, findExistingSummaryNote, findExistingSummaryNoteId, fingerprints, gitSkillCacheKey, isOtelEnabled, loadNamedSkill, normalizeBody, normalizeSeverity, parseReviewMarkdown, parseReviewMarkdownWithWarnings, parseSkillSpec, resolveNpmSkillDir, resolveSkillCacheDir, run, runReview, sha256, startOtelBridge, stripSummaryHistory, stripSummaryMarker, toGitLabReviewSeverity, traceDiagnostic, traceDiagnosticPhase, upsertSummaryNote };
|
package/dist/skills.d.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export interface Skill {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
/** Absolute path to the SKILL.md file. Used to reference skill content in prompts. */
|
|
5
|
+
filePath: string;
|
|
6
|
+
rootDir: string;
|
|
7
|
+
resourceDirs: string[];
|
|
8
|
+
source: 'builtin' | 'project' | 'npm' | 'file' | 'git';
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A parsed skill spec descriptor. Produced by `parseSkillSpec`.
|
|
12
|
+
*
|
|
13
|
+
* - `builtin` — bare name resolved from the package's bundled `skills/` dir
|
|
14
|
+
* - `npm` — package in `node_modules`, optionally with a sub-directory
|
|
15
|
+
* - `file` — explicit filesystem path (relative or absolute)
|
|
16
|
+
* - `git` — shallow git clone at a pinned ref, optionally with a sub-directory
|
|
17
|
+
*/
|
|
18
|
+
export type SkillSpec = {
|
|
19
|
+
protocol: 'builtin';
|
|
20
|
+
name: string;
|
|
21
|
+
} | {
|
|
22
|
+
protocol: 'npm';
|
|
23
|
+
packageName: string;
|
|
24
|
+
subpath: string;
|
|
25
|
+
} | {
|
|
26
|
+
protocol: 'file';
|
|
27
|
+
path: string;
|
|
28
|
+
} | {
|
|
29
|
+
protocol: 'git';
|
|
30
|
+
url: string;
|
|
31
|
+
ref: string;
|
|
32
|
+
subpath: string;
|
|
33
|
+
};
|
|
34
|
+
export declare function loadSkillFromDir(dirPath: string, source: Skill['source']): Promise<Skill | null>;
|
|
35
|
+
export declare function resolveBuiltinSkillsDir(): string;
|
|
36
|
+
export declare function loadBuiltinSkill(name: string): Promise<Skill | null>;
|
|
37
|
+
export declare function loadAutoDiscoveredSkills(cwd: string, gitRoot: string, warn?: (msg: string) => void): Promise<Skill[]>;
|
|
38
|
+
/**
|
|
39
|
+
* Parse a skill spec string into a typed `SkillSpec` descriptor.
|
|
40
|
+
*
|
|
41
|
+
* Supported spec formats:
|
|
42
|
+
*
|
|
43
|
+
* | Input | Result |
|
|
44
|
+
* |------------------------------------|---------------------------------------------------|
|
|
45
|
+
* | `code-review` | `{ protocol: 'builtin', name: 'code-review' }` |
|
|
46
|
+
* | `npm:my-skill` | `{ protocol: 'npm', packageName: 'my-skill', ... }`|
|
|
47
|
+
* | `npm:@scope/pkg` | `{ protocol: 'npm', packageName: '@scope/pkg', ... }`|
|
|
48
|
+
* | `npm:@scope/bundle/security` | `{ protocol: 'npm', packageName: '@scope/bundle', subpath: 'security' }`|
|
|
49
|
+
* | `npm:bundle/security` | `{ protocol: 'npm', packageName: 'bundle', subpath: 'security' }`|
|
|
50
|
+
* | `file:./path/to/skill` | `{ protocol: 'file', path: './path/to/skill' }` |
|
|
51
|
+
* | `file:/absolute/path` | `{ protocol: 'file', path: '/absolute/path' }` |
|
|
52
|
+
* | `git:https://host/org/s.git` | `{ protocol: 'git', url: 'https://host/org/s.git', ref: '', subpath: '' }` |
|
|
53
|
+
* | `git:https://host/org/b.git#v1/sec`| `{ protocol: 'git', url: 'https://host/org/b.git', ref: 'v1', subpath: 'sec' }` |
|
|
54
|
+
* | `git+ssh://git@host/org/s.git` | `{ protocol: 'git', url: 'ssh://git@host/org/s.git', ref: '', subpath: '' }` |
|
|
55
|
+
*/
|
|
56
|
+
export declare function parseSkillSpec(spec: string): SkillSpec;
|
|
57
|
+
/**
|
|
58
|
+
* Resolve the directory for an npm-installed skill by walking `node_modules`
|
|
59
|
+
* upward from `cwd` (supports monorepo hoisting). Returns the resolved path
|
|
60
|
+
* or `null` if the package / subpath cannot be found.
|
|
61
|
+
*/
|
|
62
|
+
export declare function resolveNpmSkillDir(packageName: string, subpath: string, cwd: string): Promise<string | null>;
|
|
63
|
+
/** Base directory for cached git-skill clones (honours `XDG_CACHE_HOME`). */
|
|
64
|
+
export declare function resolveSkillCacheDir(): string;
|
|
65
|
+
/**
|
|
66
|
+
* Stable cache-directory name for a git skill. Keyed on the clone URL plus the
|
|
67
|
+
* pinned ref so that two refs of the same repo never share a cache entry.
|
|
68
|
+
*/
|
|
69
|
+
export declare function gitSkillCacheKey(url: string, ref: string): string;
|
|
70
|
+
/** Options controlling how external skills are resolved. */
|
|
71
|
+
export interface LoadNamedSkillOptions {
|
|
72
|
+
/** Override the git-skill clone cache directory (defaults to the XDG cache). */
|
|
73
|
+
cacheDir?: string;
|
|
74
|
+
/** Re-clone git skills even when a cached copy exists. */
|
|
75
|
+
refresh?: boolean;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Load a skill by its spec string (`code-review`, `npm:@scope/pkg`, `file:./path`,
|
|
79
|
+
* `git:https://…`, …).
|
|
80
|
+
*
|
|
81
|
+
* Resolution order:
|
|
82
|
+
* 1. `builtin` — package-bundled `skills/<name>/`
|
|
83
|
+
* 2. `npm:` — `node_modules/<packageName>[/subpath]` walked up from `cwd`
|
|
84
|
+
* 3. `file:` — direct filesystem path (relative paths resolved from `cwd`)
|
|
85
|
+
* 4. `git:` / `git+ssh:` — shallow clone at the pinned ref, cached on disk,
|
|
86
|
+
* loading `SKILL.md` from the repo root or the `#<ref>/<subpath>` directory
|
|
87
|
+
*
|
|
88
|
+
* Throws a `ConfigError` if the spec cannot be resolved or the resolved
|
|
89
|
+
* directory does not contain a valid `SKILL.md`.
|
|
90
|
+
*/
|
|
91
|
+
export declare function loadNamedSkill(spec: string, cwd: string, options?: LoadNamedSkillOptions): Promise<Skill>;
|
|
92
|
+
//# sourceMappingURL=skills.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;CACxD;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GACjB;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AA0BnE,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,GACtB,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAmBvB;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAE1E;AAED,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC3B,OAAO,CAAC,KAAK,EAAE,CAAC,CAqClB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAqCtD;AA4CD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAYxB;AAED,6EAA6E;AAC7E,wBAAgB,oBAAoB,IAAI,MAAM,CAG7C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjE;AA2DD,4DAA4D;AAC5D,MAAM,WAAW,qBAAqB;IACpC,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,KAAK,CAAC,CAoEhB"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Directory (relative to cwd) where dropped-file diffs are staged for retrieval. */
|
|
2
|
+
export declare const SKIPPED_DIFF_DIR = ".code-review-skipped";
|
|
3
|
+
export interface SkippedDiffFile {
|
|
4
|
+
/** Original repository path of the dropped file. */
|
|
5
|
+
path: string;
|
|
6
|
+
/** Path to the staged diff, relative to cwd — what the agent passes to its read tool. */
|
|
7
|
+
diskPath: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Write each size-dropped file's diff to `<cwd>/.code-review-skipped/` so an
|
|
11
|
+
* agentic reviewer can read the diffs it deems highest-risk on demand, instead
|
|
12
|
+
* of the diffs being lost to the char budget. Returns the on-disk manifest.
|
|
13
|
+
* Paths are staged under cwd because the reviewer's read tool is cwd-scoped.
|
|
14
|
+
*/
|
|
15
|
+
export declare function writeSkippedDiffs(cwd: string, sections: Array<{
|
|
16
|
+
path: string;
|
|
17
|
+
section: string;
|
|
18
|
+
}>): Promise<SkippedDiffFile[]>;
|
|
19
|
+
/** Remove the staged-diff directory. Safe to call when it was never created. */
|
|
20
|
+
export declare function cleanupSkippedDiffs(cwd: string): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Render the `<skipped_files>` block for the retrieval mode: each dropped file
|
|
23
|
+
* with its on-disk diff path and an instruction to read the highest-risk ones.
|
|
24
|
+
*/
|
|
25
|
+
export declare function renderRetrievableSkippedBlock(files: SkippedDiffFile[]): string;
|
|
26
|
+
//# sourceMappingURL=skipped-retrieval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skipped-retrieval.d.ts","sourceRoot":"","sources":["../src/skipped-retrieval.ts"],"names":[],"mappings":"AAGA,qFAAqF;AACrF,eAAO,MAAM,gBAAgB,yBAAyB,CAAC;AAEvD,MAAM,WAAW,eAAe;IAC9B,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GACjD,OAAO,CAAC,eAAe,EAAE,CAAC,CAW5B;AAED,gFAAgF;AAChF,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEpE;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,MAAM,CAG9E"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Discussion } from './gitlab.js';
|
|
2
|
+
import type { Severity } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* A bot-posted inline finding from a previous review run whose thread is still
|
|
5
|
+
* open (unresolved). Carried into the current summary so an unresolved thread
|
|
6
|
+
* never silently disappears from the issue list when a later run doesn't
|
|
7
|
+
* re-emit it (#92).
|
|
8
|
+
*/
|
|
9
|
+
export interface CarryOverFinding {
|
|
10
|
+
file: string;
|
|
11
|
+
line: number | null;
|
|
12
|
+
severity: Severity;
|
|
13
|
+
/** Conventional Comment label incl. decoration, e.g. `issue (blocking)`. */
|
|
14
|
+
header: string;
|
|
15
|
+
subject: string;
|
|
16
|
+
/** All fingerprint hashes found in the bot note (primary + secondary). */
|
|
17
|
+
hashes: string[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Extract still-open (unresolved) bot-posted inline findings from prior MR
|
|
21
|
+
* discussions. A discussion qualifies when its first bot note carries fingerprint
|
|
22
|
+
* markers, sits on a file position, and no note in it is resolved.
|
|
23
|
+
*/
|
|
24
|
+
export declare function extractOpenBotFindings(discussions: Discussion[]): CarryOverFinding[];
|
|
25
|
+
/**
|
|
26
|
+
* From the still-open prior findings, keep only those the current run did NOT
|
|
27
|
+
* re-emit — i.e. none of their fingerprints appear in `currentFingerprints`.
|
|
28
|
+
* A re-emitted finding is already represented (posted or deduplicated), so it
|
|
29
|
+
* must not be double-listed.
|
|
30
|
+
*/
|
|
31
|
+
export declare function selectCarryOver(openFindings: CarryOverFinding[], currentFingerprints: Set<string>): CarryOverFinding[];
|
|
32
|
+
/**
|
|
33
|
+
* Fold carried-over findings into a summary so unresolved prior threads stay
|
|
34
|
+
* visible and the risk line never drops below a still-open finding's level:
|
|
35
|
+
*
|
|
36
|
+
* 1. Bump the `**Risk: …**` line up (never down) if a carry-over outranks it.
|
|
37
|
+
* 2. Append a `**Still open from earlier reviews (N):**` block listing them.
|
|
38
|
+
*
|
|
39
|
+
* Returns the summary unchanged when there is nothing to carry over, so
|
|
40
|
+
* single-run / first-run output is byte-identical.
|
|
41
|
+
*/
|
|
42
|
+
export declare function applyCarryOverToSummary(summary: string, carryOvers: CarryOverFinding[]): string;
|
|
43
|
+
/**
|
|
44
|
+
* Convenience wrapper: extract still-open prior findings, drop the ones the
|
|
45
|
+
* current run re-emitted, and fold the rest into the summary.
|
|
46
|
+
*/
|
|
47
|
+
export declare function withCarriedOverFindings(summary: string, discussions: Discussion[], currentFingerprints: Set<string>): string;
|
|
48
|
+
//# sourceMappingURL=summary-carryover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary-carryover.d.ts","sourceRoot":"","sources":["../src/summary-carryover.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAkB,MAAM,aAAa,CAAC;AAE9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAK3C;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AA2CD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,UAAU,EAAE,GAAG,gBAAgB,EAAE,CAwBpF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,gBAAgB,EAAE,EAChC,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,GAC/B,gBAAgB,EAAE,CAEpB;AASD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAsB/F;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,UAAU,EAAE,EACzB,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,GAC/B,MAAM,CAGR"}
|