update auto-agents-system scripts
This commit is contained in:
@@ -81,8 +81,12 @@ export interface AugmentedPR extends RawPR {
|
||||
approvals_count: number;
|
||||
stale_state: StaleState;
|
||||
ci_status: CIStatus;
|
||||
priority_rank: number; // 0 = CI Blocker (highest), higher = lower; PRIORITY_NONE if unlabelled
|
||||
priority_rank: number; // 0=Overdue Milestone/CI Blocker (highest), higher = lower
|
||||
label_priority_rank: number; // rank from Priority/* label (0-5) or PRIORITY_NONE
|
||||
priority_label: string | null; // matched Priority/* label name, or null if none
|
||||
milestone_title: string | null;// milestone title, or null if no milestone set
|
||||
milestone_due: string | null; // ISO 8601 deadline string, or null if no milestone
|
||||
milestone_rank: number; // urgency rank from milestone (0-3), MILESTONE_LOW for none
|
||||
}
|
||||
|
||||
interface Review {
|
||||
@@ -122,8 +126,24 @@ const PRIORITY_ORDER = new Map<string, number>([
|
||||
]);
|
||||
const PRIORITY_NONE = 6; // rank for PRs with no recognised Priority/* label
|
||||
|
||||
// Milestone-urgency thresholds — lower rank number = more urgent milestone.
|
||||
// Derived from the due_on date (ISO 8601) relative to the current time.
|
||||
// Any PR without a milestone gets MILESTONE_LOW so it is sorted below
|
||||
// every labelled or deadline-driven PR.
|
||||
const MILESTONE_OVERDUE = 0; // already past due_on
|
||||
const MILESTONE_TODAY = 1; // due today (same calendar day)
|
||||
const MILESTONE_WEEK = 2; // due within the next 7 days
|
||||
const MILESTONE_MONTH = 3; // due beyond 7 days or no milestone at all
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// pLimit — run an array of async tasks with bounded concurrency
|
||||
// prMilestoneRank — compute urgency rank from a PR's milestone due_on date
|
||||
//
|
||||
// Inspects pr.milestone (a Forgejo Milestone object with title and due_on) and
|
||||
// returns the urgency-based rank:
|
||||
// 0 = overdue (past due_on), 1 = due today, 2 = due within 7 days,
|
||||
// 3 = due beyond 7 days or no milestone at all
|
||||
// ──
|
||||
|
||||
//
|
||||
// Spawns `limit` worker coroutines that each pull the next available task from
|
||||
// the shared queue. Results are returned in input order.
|
||||
@@ -240,6 +260,78 @@ function prPriority(pr: RawPR): { rank: number; label: string | null } {
|
||||
return { rank: bestRank, label: bestLabel };
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// prMilestoneRank — compute urgency-based PR rank from milestone due_on date
|
||||
//
|
||||
// Inspects pr.milestone (a Forgejo Milestone object with title and due_on) and
|
||||
// returns the urgency-based rank:
|
||||
// 0 = overdue (already past due_on), 1 = due today, 2 = due within 7 days,
|
||||
// 3 = due beyond 7 days or no milestone at all
|
||||
//
|
||||
// Also extracts the milestone title and due_on string for output. The caller
|
||||
// uses these to merge with label-based priority below.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
function prMilestoneRank(
|
||||
pr: RawPR,
|
||||
): { rank: number; title: string | null; due: string | null } {
|
||||
const milestone = pr.milestone as Record<string, unknown> | null | undefined;
|
||||
if (!milestone || typeof milestone !== 'object') return { rank: MILESTONE_MONTH, title: null, due: null };
|
||||
|
||||
const dueOn = (milestone.due_on as string | undefined) ?? null;
|
||||
const title = (milestone.title as string | undefined) ?? null;
|
||||
|
||||
if (!dueOn) return { rank: MILESTONE_MONTH, title, due: null };
|
||||
|
||||
const now = Date.now();
|
||||
const deadline = new Date(dueOn).getTime();
|
||||
const diffMs = deadline - now;
|
||||
const oneDay = 86_400_000;
|
||||
|
||||
// Deadline is today → high urgency (rank 1)
|
||||
if (diffMs <= oneDay) return { rank: MILESTONE_TODAY, title, due: dueOn };
|
||||
|
||||
// Deadline is within the next week → medium urgency (rank 2)
|
||||
const sevenDays = 7 * oneDay;
|
||||
if (diffMs <= sevenDays) return { rank: MILESTONE_WEEK, title, due: dueOn };
|
||||
|
||||
// Beyond a week or no deadline → low urgency (rank 3)
|
||||
return { rank: MILESTONE_MONTH, title, due: dueOn };
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// mergePriority — combine label-based and milestone-based priority into one rank
|
||||
//
|
||||
// Priority is based on whichever source has the stronger (lower) rank.
|
||||
// This gives urgent milestones a chance to climb above PRs that only have
|
||||
// low Priority/* labels and vice-versa. Label-based priority acts as a tie-
|
||||
// breaker when both ranks are equal, so that a labelled PR beats an unlabelled
|
||||
// one at the same milestone urgency level.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
function mergePriority(
|
||||
labelRank: number,
|
||||
labelLabel: string | null,
|
||||
milestoneRank: number,
|
||||
): { final_rank: number; label_priority_rank: number; priority_label: string | null } {
|
||||
if (labelRank < milestoneRank) {
|
||||
// Label is stronger → use label rank
|
||||
return { final_rank: labelRank, label_priority_rank: labelRank, priority_label: labelLabel };
|
||||
}
|
||||
|
||||
if (milestoneRank < labelRank) {
|
||||
// Milestone is stronger → use milestone rank with a bump based on label strength
|
||||
// to break ties within the same milestone urgency level.
|
||||
// The base milestone rank starts at 0-3; we add label_priority_rank as an
|
||||
// offset starting from PRIORITY_NONE so that labelled PRs sort ahead of
|
||||
// unlabelled ones at equal milestone urgency.
|
||||
const finalRank = milestoneRank + Math.max(PRIORITY_NONE - 4, 0);
|
||||
return { final_rank: finalRank, label_priority_rank: labelRank, priority_label: labelLabel };
|
||||
}
|
||||
|
||||
// Equal ranks → labelled PR wins (lower offset from MILESTONE_MONTH baseline)
|
||||
const combinedRank = milestoneRank + Math.max(PRIORITY_NONE - 4, 0);
|
||||
return { final_rank: combinedRank, label_priority_rank: labelRank, priority_label: labelLabel };
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// countApprovals — distinct non-dismissed APPROVED review count for a PR
|
||||
//
|
||||
@@ -494,14 +586,26 @@ export async function listPRs(
|
||||
if (filters.hasUnaddressedRequestChanges !== undefined &&
|
||||
hasUnaddressedRequestChangesCheck(allReviews[i], pr.head.sha) !== filters.hasUnaddressedRequestChanges) continue;
|
||||
|
||||
const { rank: priorityRank, label: priorityLabel } = prPriority(pr);
|
||||
// ── Compute label priority ────────────────────────────────────────────────
|
||||
const { rank: labelPriorityRank, label: priorityLabel } = prPriority(pr);
|
||||
|
||||
// ── Compute milestone urgency ─────────────────────────────────────────────
|
||||
const { rank: milestoneRank, title:milestoneTitle, due:milestoneDue } = prMilestoneRank(pr);
|
||||
|
||||
// ── Merge into combined priority_rank ─────────────────────────────────────
|
||||
const { final_rank } = mergePriority(labelPriorityRank, priorityLabel, milestoneRank);
|
||||
|
||||
results.push({
|
||||
...pr,
|
||||
approvals_count: approvalsCount,
|
||||
stale_state: staleState,
|
||||
ci_status: ciStatus,
|
||||
priority_rank: priorityRank,
|
||||
priority_label: priorityLabel,
|
||||
approvals_count: approvalsCount,
|
||||
stale_state: staleState,
|
||||
ci_status: ciStatus,
|
||||
priority_rank: final_rank,
|
||||
label_priority_rank: labelPriorityRank,
|
||||
priority_label: priorityLabel,
|
||||
milestone_title: milestoneTitle,
|
||||
milestone_due: milestoneDue,
|
||||
milestone_rank: milestoneRank,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -648,9 +752,17 @@ the full Forgejo PR plus:
|
||||
.approvals_count integer distinct non-dismissed APPROVED review count
|
||||
.stale_state string one of the stale states listed above
|
||||
.ci_status string passing|failing|pending|unknown (see --ci-status above)
|
||||
.priority_rank integer 0=CI Blocker, 1=Critical, 2=High, 3=Medium,
|
||||
4=Low, 5=Backlog, 6=none (unlabelled)
|
||||
.priority_label string|null matched Priority/* label name, or null
|
||||
.priority_rank integer priority rank — the lower the number, the higher
|
||||
the urgency; ranges from 0 (overdue milestone /
|
||||
CI Blocker label) to ~7+ (low-unlabelled PR).
|
||||
See merged priority computation in file header.
|
||||
.label_priority_rank integer rank derived solely from a Priority/* label
|
||||
(0-5), or PRIORITY_NONE if no such label exists
|
||||
.priority_label string|null matched Priority/* label name, or null
|
||||
.milestone_title string|null milestone title assigned to the PR, or null
|
||||
.milestone_due string|null ISO 8601 deadline of the milestone, or null
|
||||
.milestone_rank integer urgency derived from deadline:
|
||||
0=overdue, 1=today, 2=within 7 days, 3=beyond / none
|
||||
`);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user