-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathanalysis_service.py
More file actions
200 lines (183 loc) · 7.72 KB
/
Copy pathanalysis_service.py
File metadata and controls
200 lines (183 loc) · 7.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
import radar
from evidence_service import build_evidence_engine, unavailable_evidence
from radar import (
decision,
estimate_difficulty as estimate_issue_difficulty,
estimate_time as estimate_issue_time,
get_analysis,
merge_probability as estimate_issue_merge_probability,
recommendation,
recommend_angle,
score_repo_signal_report,
)
from repository_intelligence import build_repository_intelligence
def contract_potential(score: int) -> str:
if score >= 85:
return "High"
if score >= 60:
return "Medium"
return "Low"
def _select_issue(issue_rankings, issue_number=None):
if not issue_rankings:
return None
if issue_number is not None:
try:
requested_number = int(issue_number)
except (TypeError, ValueError):
requested_number = None
if requested_number is not None:
for score, issue_type, issue in issue_rankings:
if issue.get("number") == requested_number:
return score, issue_type, issue
return issue_rankings[0]
def build_analysis_result(repo_url: str, issue_number=None) -> dict:
owner, repo_name, repo, languages, issue_rankings, repo_score, language_badge = get_analysis(repo_url)
selected_issue = _select_issue(issue_rankings, issue_number)
best_issue = None
difficulty = "Unavailable"
estimated_time = "Unavailable"
merge_probability = "Unavailable"
if selected_issue:
score, issue_type, issue = selected_issue
best_issue = {
"number": issue.get("number"),
"title": issue.get("title"),
"url": issue.get("html_url"),
"score": score,
"type": issue_type,
}
difficulty = estimate_issue_difficulty(issue_type, score)
estimated_time = estimate_issue_time(issue_type)
merge_probability = estimate_issue_merge_probability(score, repo_score)
angle = recommend_angle(languages)
score_transparency = score_repo_signal_report(
repo,
[issue for _score, _issue_type, issue in issue_rankings],
languages,
)
# Keep the displayed score and its component explanation on one source of
# truth even when callers provide precomputed analysis data.
repo_score = score_transparency["score"]
if selected_issue:
merge_probability = estimate_issue_merge_probability(selected_issue[0], repo_score)
repository_intelligence = build_repository_intelligence(
repo,
[issue for _score, _issue_type, issue in issue_rankings],
)
repository_full_name = f"{owner}/{repo_name}"
selected_issue_data = selected_issue[2] if selected_issue else None
selected_issue_type = selected_issue[1] if selected_issue else None
try:
evidence = build_evidence_engine(
repository_full_name,
repo,
selected_issue_data,
selected_issue_type,
fetcher=radar.github_get,
)
except Exception:
evidence = unavailable_evidence(
repository_full_name,
"Historical GitHub evidence could not be calculated for this report.",
)
recommendation_result = recommendation(
repo_score,
best_issue=best_issue,
confidence=score_transparency["confidence"],
)
if recommendation_result["decision"] == "Contribute Now":
recommended_action = f"Start with #{best_issue['number']} - {best_issue['title']}"
elif best_issue and recommendation_result["decision"] == "Inspect Carefully":
recommended_action = f"Review the scope of #{best_issue['number']} before starting work"
elif recommendation_result["decision"] == "Inspect Repository":
recommended_action = "Inspect the repository issue queue before choosing work"
else:
recommended_action = "Prioritize a repository with stronger public evidence"
outcome_by_recommendation = {
"Contribute Now": "Use one focused contribution to test maintainer fit before considering outreach.",
"Inspect Carefully": "Verify issue scope and maintainer activity before deciding whether to contribute.",
"Inspect Repository": "Find a current, scoped issue before deciding whether to contribute.",
"Skip": "Spend time on a repository with stronger and more complete public evidence.",
}
return {
"repo": f"{owner}/{repo_name}",
"repo_url": repo_url,
"owner": owner,
"repo_name": repo_name,
"repo_data": repo,
"language": language_badge,
"website": repo.get("homepage") or "Not found",
"github": repo.get("html_url"),
"description": repo.get("description"),
"stars": repo.get("stargazers_count"),
"forks": repo.get("forks_count"),
"open_issues": repo.get("open_issues_count"),
"last_push": repo.get("pushed_at"),
"score": repo_score,
"score_label": (
"Exceptional"
if repo_score >= 98
else "Excellent"
if repo_score >= 90
else "Strong"
if repo_score >= 80
else "Moderate"
if repo_score >= 60
else "Weak"
),
"score_action": recommendation_result["label"],
"recommendation_explanation": recommendation_result["explanation"],
"contract_potential": contract_potential(repo_score),
"merge_probability": merge_probability,
"estimated_time": estimated_time,
"difficulty": difficulty,
"decision": decision(
repo_score,
best_issue=best_issue,
confidence=score_transparency["confidence"],
),
"angle": angle,
"best_issue": best_issue,
"recommended_action": recommended_action,
"recommended_outcome": outcome_by_recommendation[recommendation_result["decision"]],
"issues": issue_rankings[:8],
"languages": languages,
"score_transparency": score_transparency,
"repository_intelligence": repository_intelligence,
"evidence": evidence,
}
def to_public_api_payload(result: dict, site_url: str) -> dict:
best_issue = result.get("best_issue")
best_issue_text = None
if best_issue:
best_issue_text = f"#{best_issue.get('number')} - {best_issue.get('title')}"
score_transparency = result.get("score_transparency") or {}
evidence = result.get("evidence") or unavailable_evidence(
result.get("repo", ""),
"Historical GitHub evidence was not included in this analysis.",
)
return {
"repository": result.get("repo", ""),
"opportunity_score": result.get("score", 0),
"decision": result.get("decision", ""),
"chance_of_getting_noticed": "Unavailable - maintainer attention is not measured",
"contract_potential": contract_potential(int(result.get("score") or 0)),
"merge_probability": result.get("merge_probability", ""),
"estimated_time": result.get("estimated_time", ""),
"difficulty": result.get("difficulty", ""),
"best_issue": best_issue_text,
"best_issue_url": best_issue.get("url") if best_issue else None,
"proof_of_work_angle": result.get("angle", ""),
"recommended_next_action": result.get("recommended_action", ""),
"upgrade_url": f"{site_url.rstrip('/')}/pricing",
"confidence": {
"level": score_transparency.get("confidence", "Unknown"),
"reasons": score_transparency.get("confidence_reasons", []),
"unknowns": score_transparency.get("confidence_unknowns", []),
},
"evidence": evidence,
"ai_interpretation": {
"status": "not_included",
"detail": "The public API response contains deterministic evidence only.",
},
}