Skip to content

Commit 42f678a

Browse files
author
Shaurya Singh
committed
Remove Issue Triage feature - liability concerns
1 parent e532b5b commit 42f678a

File tree

5 files changed

+10
-296
lines changed

5 files changed

+10
-296
lines changed

src/ai/generator.ts

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ import {
44
buildContributorQuickstartPrompt,
55
buildReleaseSummaryPrompt,
66
buildGoodFirstIssuesPrompt,
7-
buildIssueTriagePrompt,
87
} from './prompts';
98
import { RepoSnapshot } from '../github/fetchers';
109

1110
export interface AnalysisOutput {
12-
type: 'maintainer_brief' | 'contributor_quickstart' | 'release_summary' | 'good_first_issues' | 'issue_triage';
11+
type: 'maintainer_brief' | 'contributor_quickstart' | 'release_summary' | 'good_first_issues';
1312
content: string;
1413
confidence: number;
1514
sources: {
@@ -20,7 +19,7 @@ export interface AnalysisOutput {
2019
}
2120

2221
/**
23-
* Generates all 5 analysis outputs for a repository
22+
* Generates all 4 analysis outputs for a repository
2423
*/
2524
export async function generateAllOutputs(
2625
snapshot: RepoSnapshot,
@@ -34,16 +33,15 @@ export async function generateAllOutputs(
3433
const sources = {
3534
commits: snapshot.commits.slice(0, 50).map(c => c.sha),
3635
prs: snapshot.prs.slice(0, 30).map(pr => pr.number),
37-
issues: [...snapshot.issues.map(i => i.number), ...(snapshot.allIssues || []).map(i => i.number)],
36+
issues: snapshot.issues.map(i => i.number),
3837
};
3938

4039
// Generate all outputs in parallel
41-
const [maintainerBrief, contributorQuickstart, releaseSummary, goodFirstIssues, issueTriage] = await Promise.all([
40+
const [maintainerBrief, contributorQuickstart, releaseSummary, goodFirstIssues] = await Promise.all([
4241
generateMaintainerBrief(snapshot, tone),
4342
generateContributorQuickstart(snapshot, tone),
4443
generateReleaseSummary(snapshot, tone),
4544
generateGoodFirstIssues(snapshot, tone),
46-
generateIssueTriage(snapshot, tone),
4745
]);
4846

4947
return [
@@ -71,12 +69,6 @@ export async function generateAllOutputs(
7169
confidence: calculateConfidence(snapshot, 'good_first_issues'),
7270
sources,
7371
},
74-
{
75-
type: 'issue_triage',
76-
content: issueTriage,
77-
confidence: calculateConfidence(snapshot, 'issue_triage'),
78-
sources,
79-
},
8072
];
8173
}
8274

@@ -112,14 +104,6 @@ async function generateGoodFirstIssues(
112104
return await generateText(prompt, { maxTokens: tone === 'detailed' ? 2500 : 1500 });
113105
}
114106

115-
async function generateIssueTriage(
116-
snapshot: RepoSnapshot,
117-
tone: 'concise' | 'detailed'
118-
): Promise<string> {
119-
const prompt = buildIssueTriagePrompt(snapshot, tone);
120-
return await generateText(prompt, { maxTokens: tone === 'detailed' ? 3500 : 2500 });
121-
}
122-
123107
/**
124108
* Calculates confidence score based on data quality
125109
*/
@@ -151,13 +135,6 @@ function calculateConfidence(
151135
if (snapshot.releases.length > 0) score += 0.05;
152136
}
153137

154-
if (outputType === 'issue_triage') {
155-
const allIssues = snapshot.allIssues || [];
156-
if (allIssues.length >= 20) score += 0.2;
157-
else if (allIssues.length >= 10) score += 0.1;
158-
else if (allIssues.length === 0) score -= 0.3;
159-
}
160-
161138
// Clamp to [0, 1]
162139
return Math.max(0, Math.min(1, score));
163140
}

src/ai/prompts.ts

Lines changed: 0 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -425,165 +425,6 @@ IMPORTANT RULES:
425425
7. Prefer stable areas over high-churn areas for safety`;
426426
}
427427

428-
/**
429-
* Builds prompt for Issue Triage Report
430-
*/
431-
export function buildIssueTriagePrompt(
432-
snapshot: RepoSnapshot,
433-
tone: 'concise' | 'detailed'
434-
): string {
435-
const allIssues = snapshot.allIssues || [];
436-
437-
if (allIssues.length === 0) {
438-
return `No open issues found in repository ${snapshot.repo.full_name}. Generate a brief message explaining that there are no issues to triage.`;
439-
}
440-
441-
// Calculate issue age
442-
const now = new Date();
443-
const issuesWithAge = allIssues.map(issue => {
444-
const created = new Date(issue.created_at);
445-
const ageInDays = Math.floor((now.getTime() - created.getTime()) / (1000 * 60 * 60 * 24));
446-
return { ...issue, ageInDays };
447-
});
448-
449-
// Sort by reactions + comments (engagement) for prioritization hints
450-
const sortedByEngagement = [...issuesWithAge].sort((a, b) =>
451-
((b.reactions || 0) + b.comments) - ((a.reactions || 0) + a.comments)
452-
);
453-
454-
// Find stale issues (>90 days with no recent activity)
455-
const staleIssues = issuesWithAge.filter(i => i.ageInDays > 90);
456-
457-
// Recent commit patterns to understand current focus
458-
const recentCommitMessages = snapshot.commits.slice(0, 20)
459-
.map(c => c.message.split('\n')[0])
460-
.join('\n');
461-
462-
return `You are an expert project manager analyzing GitHub issues to help maintainers prioritize their backlog.
463-
464-
Repository: ${snapshot.repo.full_name}
465-
Language: ${snapshot.repo.language || 'Multiple'}
466-
Total Open Issues: ${allIssues.length}
467-
Stale Issues (>90 days): ${staleIssues.length}
468-
469-
===== ALL OPEN ISSUES =====
470-
471-
${issuesWithAge.slice(0, 50).map(issue => `
472-
#${issue.number}: ${issue.title}
473-
- Labels: ${issue.labels.length > 0 ? issue.labels.join(', ') : 'none'}
474-
- Age: ${issue.ageInDays} days
475-
- Comments: ${issue.comments}
476-
- Reactions: ${issue.reactions || 0}
477-
- Author: @${issue.author || 'unknown'}
478-
${issue.body ? `- Description: ${issue.body.slice(0, 300)}${issue.body.length > 300 ? '...' : ''}` : '- No description'}
479-
`).join('\n---\n')}
480-
481-
===== RECENT DEVELOPMENT CONTEXT =====
482-
483-
Recent commits show the team is working on:
484-
${recentCommitMessages}
485-
486-
Recent PRs:
487-
${snapshot.prs.slice(0, 10).map(pr => `- #${pr.number}: ${pr.title}`).join('\n')}
488-
489-
===== HIGHEST ENGAGEMENT ISSUES =====
490-
491-
Top issues by community interest (reactions + comments):
492-
${sortedByEngagement.slice(0, 5).map(i => `- #${i.number}: ${i.title} (${(i.reactions || 0) + i.comments} engagement)`).join('\n')}
493-
494-
===== GENERATE THIS EXACT FORMAT =====
495-
496-
# Issue Triage Report
497-
498-
> **${allIssues.length} open issues analyzed** • Generated ${new Date().toLocaleDateString()}
499-
500-
---
501-
502-
## 🔴 Critical Priority
503-
[Issues that are blocking, security-related, or affecting many users]
504-
[For each issue, explain WHY it's critical]
505-
506-
${tone === 'detailed' ? 'Include 3-5 issues with full reasoning' : 'Include 2-3 issues'}
507-
508-
Format for each:
509-
### #[number]: [title]
510-
**Why Critical:** [1-2 sentences explaining impact]
511-
**Suggested Action:** [What maintainer should do]
512-
**Labels to Add:** [Suggest appropriate labels if missing]
513-
514-
---
515-
516-
## 🟠 High Priority
517-
[Important issues that should be addressed soon - feature requests with high demand, significant bugs]
518-
519-
${tone === 'detailed' ? 'Include 4-6 issues' : 'Include 2-4 issues'}
520-
521-
Format for each:
522-
### #[number]: [title]
523-
**Why Important:** [1 sentence]
524-
**Effort Estimate:** Low/Medium/High
525-
**Suggested Action:** [Brief action]
526-
527-
---
528-
529-
## 🟡 Medium Priority
530-
[Good to fix but not urgent - smaller bugs, enhancements, documentation]
531-
532-
${tone === 'detailed' ? 'Include 5-8 issues' : 'Include 3-5 issues'}
533-
534-
Format for each:
535-
- **#[number]**: [title] — [1 sentence summary] • Effort: [Low/Med/High]
536-
537-
---
538-
539-
## ⚪ Low Priority / Backlog
540-
[Nice to have, long-term ideas, minor improvements]
541-
542-
${tone === 'detailed' ? 'Include remaining issues' : 'Include 3-5 issues'}
543-
544-
Format: Brief list with issue numbers and titles
545-
546-
---
547-
548-
## 🗑️ Recommend Closing
549-
[Issues that should be closed - stale with no activity, duplicates, won't fix, already resolved]
550-
551-
${staleIssues.length > 0 ? `
552-
Found ${staleIssues.length} stale issues (>90 days old). Review these for closure:
553-
` : 'No obviously stale issues found.'}
554-
555-
For each:
556-
- **#[number]**: [title] — **Reason:** [duplicate of #X / stale / wont fix / resolved]
557-
558-
---
559-
560-
## 📊 Backlog Health Summary
561-
562-
| Metric | Value |
563-
|--------|-------|
564-
| Total Open | ${allIssues.length} |
565-
| Critical | [count] |
566-
| Stale (>90d) | ${staleIssues.length} |
567-
| Unlabeled | [count issues with no labels] |
568-
| Avg Age | [calculate] days |
569-
570-
**Recommendations:**
571-
1. [Top recommendation based on analysis]
572-
2. [Second recommendation]
573-
3. [Third recommendation]
574-
575-
---
576-
577-
IMPORTANT RULES:
578-
1. Every issue you mention MUST use the exact issue number from the data
579-
2. Base priority on: user impact, engagement (reactions+comments), alignment with recent development
580-
3. Be specific about WHY each issue has its priority level
581-
4. If an issue seems like a duplicate, mention it
582-
5. Consider issue age - very old issues with no activity may need closure
583-
6. Look at labels to understand existing categorization
584-
7. Suggest missing labels where appropriate`;
585-
}
586-
587428
/**
588429
* Helper: Analyze file churn
589430
*/

src/analysis/pipeline.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
extractTldr,
1212
extractRiskyChanges,
1313
extractSuggestedActions,
14-
extractCriticalIssues,
1514
WeeklyBriefData
1615
} from '../notifications/templates/weekly-brief';
1716
import db from '../db/client';
@@ -152,17 +151,15 @@ async function sendJobNotifications(
152151
if (settings.notify_email && userEmail) {
153152
console.log(`📧 Email notifications enabled, preparing to send to ${userEmail}...`);
154153

155-
// Fetch the maintainer_brief and issue_triage outputs for this job
156-
const outputsResult = await db.query(
157-
`SELECT type, content_markdown FROM analysis_outputs
158-
WHERE job_id = $1 AND type IN ('maintainer_brief', 'issue_triage')`,
154+
// Fetch the maintainer_brief output for this job
155+
const briefResult = await db.query(
156+
`SELECT content_markdown FROM analysis_outputs
157+
WHERE job_id = $1 AND type = 'maintainer_brief'`,
159158
[jobId]
160159
);
161160

162-
const maintainerBrief = outputsResult.rows.find(r => r.type === 'maintainer_brief')?.content_markdown || '';
163-
const issueTriage = outputsResult.rows.find(r => r.type === 'issue_triage')?.content_markdown || '';
161+
const maintainerBrief = briefResult.rows[0]?.content_markdown || '';
164162
console.log(`📧 Maintainer brief content length: ${maintainerBrief.length} chars`);
165-
console.log(`📧 Issue triage content length: ${issueTriage.length} chars`);
166163

167164
// Build rich email with extracted content
168165
const briefData: WeeklyBriefData = {
@@ -177,7 +174,6 @@ async function sendJobNotifications(
177174
tldr: extractTldr(maintainerBrief),
178175
riskyChanges: extractRiskyChanges(maintainerBrief),
179176
suggestedActions: extractSuggestedActions(maintainerBrief),
180-
criticalIssues: extractCriticalIssues(issueTriage),
181177
schedule: settings.schedule || 'weekly',
182178
};
183179

src/github/fetchers.ts

Lines changed: 1 addition & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ export interface GitHubIssue {
4646
labels: string[];
4747
created_at: string;
4848
comments: number;
49-
reactions?: number;
50-
author?: string;
5149
}
5250

5351
export interface GitHubRelease {
@@ -61,8 +59,7 @@ export interface RepoSnapshot {
6159
repo: GitHubRepo;
6260
commits: GitHubCommit[];
6361
prs: GitHubPR[];
64-
issues: GitHubIssue[]; // Good first issues (legacy)
65-
allIssues: GitHubIssue[]; // ALL open issues for triage
62+
issues: GitHubIssue[];
6663
releases: GitHubRelease[];
6764
readme: string | null;
6865
contributing: string | null;
@@ -231,48 +228,6 @@ export async function fetchGoodFirstIssues(
231228
});
232229
}
233230

234-
/**
235-
* Fetches ALL open issues for triage analysis
236-
*/
237-
export async function fetchAllOpenIssues(
238-
octokit: any,
239-
owner: string,
240-
repo: string,
241-
limit: number = 100
242-
): Promise<GitHubIssue[]> {
243-
const octo = normalizeOctokit(octokit);
244-
245-
try {
246-
const result = await githubApiCall(async () => {
247-
return await octo.issues.listForRepo({
248-
owner,
249-
repo,
250-
state: 'open',
251-
sort: 'updated',
252-
direction: 'desc',
253-
per_page: limit,
254-
});
255-
});
256-
257-
return result.data
258-
.filter((issue: any) => !issue.pull_request) // Exclude PRs
259-
.map((issue: any) => ({
260-
number: issue.number,
261-
title: issue.title,
262-
state: issue.state,
263-
body: issue.body || null,
264-
labels: issue.labels.map((l: any) => typeof l === 'string' ? l : l.name || ''),
265-
created_at: issue.created_at,
266-
comments: issue.comments,
267-
reactions: issue.reactions?.total_count || 0,
268-
author: issue.user?.login || 'Unknown',
269-
}));
270-
} catch (error) {
271-
console.warn('Failed to fetch all issues:', error);
272-
return [];
273-
}
274-
}
275-
276231
/**
277232
* Fetches recent releases
278233
*/
@@ -366,14 +321,12 @@ export async function fetchRepoSnapshot(
366321
ignorePaths: string[] = []
367322
): Promise<RepoSnapshot> {
368323
const commitLimit = depth === 'deep' ? 200 : 50;
369-
const issueLimit = depth === 'deep' ? 100 : 50;
370324

371325
const [
372326
repoData,
373327
commits,
374328
prs,
375329
issues,
376-
allIssues,
377330
releases,
378331
readme,
379332
contributing,
@@ -382,7 +335,6 @@ export async function fetchRepoSnapshot(
382335
fetchRecentCommits(octokit, owner, repo, branch, commitLimit, ignorePaths),
383336
fetchRecentPRs(octokit, owner, repo, depth === 'deep' ? 60 : 30),
384337
fetchGoodFirstIssues(octokit, owner, repo),
385-
fetchAllOpenIssues(octokit, owner, repo, issueLimit),
386338
fetchRecentReleases(octokit, owner, repo),
387339
fetchReadme(octokit, owner, repo),
388340
fetchContributing(octokit, owner, repo),
@@ -393,7 +345,6 @@ export async function fetchRepoSnapshot(
393345
commits,
394346
prs,
395347
issues,
396-
allIssues,
397348
releases,
398349
readme,
399350
contributing,

0 commit comments

Comments
 (0)