@reneturcios/greenlight 0.3.9 → 0.3.11

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.
@@ -0,0 +1,212 @@
1
+ import { type GuardClaim } from "./guard.js";
2
+ import type { CommentSignal, LinkedPR } from "./types.js";
3
+ export declare const DIGEST_VERSION = "0.3.11";
4
+ /** Default cap for list fetches; --limit overrides. The true total is always reported. */
5
+ export declare const DEFAULT_DIGEST_LIMIT = 50;
6
+ /** A claim on an open issue with no open PR after this many days is stale. */
7
+ export declare const STALE_CLAIM_DAYS = 14;
8
+ /** At this age the suggested action flips from "nudge" to "release". */
9
+ export declare const RELEASE_CLAIM_DAYS = 30;
10
+ export interface DigestPR {
11
+ number: number;
12
+ title: string;
13
+ body: string;
14
+ author: string;
15
+ headRef: string;
16
+ createdAt: string;
17
+ url: string;
18
+ }
19
+ /** An issue this digest cares about, with its repo (cross-repo links supported). */
20
+ export interface DigestIssueKey {
21
+ owner: string;
22
+ repo: string;
23
+ number: number;
24
+ /** "#4668" for same-repo, "acme/widgets#123" for cross-repo. */
25
+ label: string;
26
+ }
27
+ export interface DigestRace {
28
+ issue: DigestIssueKey;
29
+ issueTitle: string;
30
+ issueUrl: string;
31
+ prs: DigestPR[];
32
+ /** The earliest claim on the issue, if any. */
33
+ earliestClaim: {
34
+ author: string;
35
+ createdAt: string;
36
+ strength: string;
37
+ phrase: string;
38
+ } | null;
39
+ /** "first claim: @x on DATE; first PR opened: #N by @y on DATE; the other PR(s) duplicate effort". */
40
+ arbitration: string;
41
+ }
42
+ export interface DigestClaimConflict {
43
+ pr: DigestPR;
44
+ issue: DigestIssueKey;
45
+ issueTitle: string;
46
+ issueUrl: string;
47
+ foreignClaims: GuardClaim[];
48
+ }
49
+ export interface DigestStaleClaim {
50
+ issue: DigestIssueKey;
51
+ issueTitle: string;
52
+ issueUrl: string;
53
+ claimant: string;
54
+ claimDate: string;
55
+ ageDays: number;
56
+ /** "nudge @x" under 30 days, "release the claim" at 30+. */
57
+ action: string;
58
+ }
59
+ export interface DigestAssignmentConflict {
60
+ pr: DigestPR;
61
+ issue: DigestIssueKey;
62
+ issueTitle: string;
63
+ issueUrl: string;
64
+ /** Current assignees, or [] when the issue is assigned to nobody. */
65
+ assignees: string[];
66
+ }
67
+ export interface DigestSectionNote {
68
+ section: string;
69
+ note: string;
70
+ }
71
+ export interface DigestResult {
72
+ repo: string;
73
+ races: DigestRace[];
74
+ claimConflicts: DigestClaimConflict[];
75
+ staleClaims: DigestStaleClaim[];
76
+ assignmentConflicts: DigestAssignmentConflict[];
77
+ /** Sections that could not be computed, with the reason why. */
78
+ degraded: DigestSectionNote[];
79
+ /** "# of sections zero" friendly summary header. */
80
+ summary: string;
81
+ prCap: number;
82
+ trueOpenPRs: number | null;
83
+ issueCap: number;
84
+ trueOpenIssues: number | null;
85
+ /** True when at least one race exists (--fail-on-race maps this to exit code 3). */
86
+ hasRaces: boolean;
87
+ markdown: string;
88
+ }
89
+ export interface DigestIssueMeta {
90
+ number: number;
91
+ title: string;
92
+ state: string;
93
+ author: string;
94
+ url: string;
95
+ commentsCount: number;
96
+ assignees: string[];
97
+ /** Full comments, fetched only when the candidate needs claims (see budget notes). */
98
+ comments?: CommentSignal[];
99
+ }
100
+ /**
101
+ * Issue keys a PR links to: same-repo closing links plus cross-repo
102
+ * closing references (guard's extractors, reused exactly).
103
+ */
104
+ export declare function extractPRIssueKeys(pull: DigestPR, prOwner: string, prRepo: string): DigestIssueKey[];
105
+ /** Group open PRs by issue key; groups of 2+ are races. */
106
+ export declare function groupPRsByIssue(prs: DigestPR[], prOwner: string, prRepo: string): Map<string, {
107
+ key: DigestIssueKey;
108
+ prs: DigestPR[];
109
+ }>;
110
+ /**
111
+ * One race: earliest claim (author + date) and earliest PR opened, with a
112
+ * one-line arbitration summary. Pure: issue comments and PR groups are
113
+ * injected.
114
+ */
115
+ export declare function buildRace(group: {
116
+ key: DigestIssueKey;
117
+ prs: DigestPR[];
118
+ }, issueTitle: string, issueUrl: string, comments: CommentSignal[], now?: Date): DigestRace;
119
+ /**
120
+ * Claimed-by-other conflicts: open PRs whose linked issue carries a claim
121
+ * by someone other than the PR author that predates the PR. Pure: per-issue
122
+ * comments and author are injected; splitIssueClaims (guard) does the
123
+ * actual matching.
124
+ */
125
+ export declare function buildClaimConflicts(args: {
126
+ prs: DigestPR[];
127
+ prOwner: string;
128
+ prRepo: string;
129
+ issueData: Map<string, {
130
+ key: DigestIssueKey;
131
+ title: string;
132
+ url: string;
133
+ author: string;
134
+ comments: CommentSignal[];
135
+ }>;
136
+ }): DigestClaimConflict[];
137
+ /**
138
+ * Stale claims: open issues with a claim older than STALE_CLAIM_DAYS and
139
+ * NO open PR linked in the issue's timeline. Pure: claims come from
140
+ * injected comments; the timeline result is injected as LinkedPR[].
141
+ */
142
+ export declare function buildStaleClaims(candidates: Array<{
143
+ key: DigestIssueKey;
144
+ title: string;
145
+ url: string;
146
+ comments: CommentSignal[];
147
+ linkedPRs: LinkedPR[];
148
+ }>, now?: Date): DigestStaleClaim[];
149
+ /**
150
+ * Assignment-gate conflicts: only runs when the repo's gates say
151
+ * assignment is required. A PR whose author is not among the issue's
152
+ * assignees is flagged; "assigned to nobody" is its own flavor.
153
+ */
154
+ export declare function buildAssignmentConflicts(args: {
155
+ prs: DigestPR[];
156
+ prOwner: string;
157
+ prRepo: string;
158
+ assignmentRequired: boolean;
159
+ assigneesByIssue: Map<string, {
160
+ key: DigestIssueKey;
161
+ title: string;
162
+ url: string;
163
+ assignees: string[];
164
+ }>;
165
+ }): DigestAssignmentConflict[];
166
+ export declare function buildDigestSummary(args: {
167
+ repo: string;
168
+ races: number;
169
+ claimConflicts: number;
170
+ staleClaims: number;
171
+ assignmentConflicts: number;
172
+ prCap: number;
173
+ trueOpenPRs: number | null;
174
+ }): string;
175
+ export declare function renderDigestMarkdown(result: DigestResult): string;
176
+ interface IssueListItem {
177
+ number?: unknown;
178
+ title?: unknown;
179
+ user?: {
180
+ login?: unknown;
181
+ };
182
+ state?: unknown;
183
+ comments?: unknown;
184
+ html_url?: unknown;
185
+ assignees?: Array<{
186
+ login?: unknown;
187
+ }>;
188
+ pull_request?: unknown;
189
+ }
190
+ export interface DigestDeps {
191
+ listOpenPRs?: (owner: string, repo: string, limit: number) => Promise<{
192
+ prs: DigestPR[];
193
+ total: number | null;
194
+ }>;
195
+ listOpenIssues?: (owner: string, repo: string, limit: number) => Promise<{
196
+ issues: IssueListItem[];
197
+ total: number | null;
198
+ }>;
199
+ fetchIssueMeta?: (owner: string, repo: string, number: number) => Promise<DigestIssueMeta>;
200
+ fetchIssueComments?: (owner: string, repo: string, number: number) => Promise<CommentSignal[]>;
201
+ fetchLinkedPRs?: (owner: string, repo: string, issueNumber: number) => Promise<LinkedPR[]>;
202
+ fetchContributing?: (owner: string, repo: string) => Promise<string | undefined>;
203
+ }
204
+ /**
205
+ * Full digest for owner/repo. Best-effort throughout: a section whose
206
+ * data cannot be read is recorded in `degraded` with the reason, never
207
+ * presented as a clean zero.
208
+ */
209
+ export declare function digestRepo(owner: string, repo: string, limit: number, deps?: DigestDeps, opts?: {
210
+ now?: Date;
211
+ }): Promise<DigestResult>;
212
+ export {};