@oss-autopilot/core 0.58.0 → 0.59.0
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/dist/cli-registry.js +54 -0
- package/dist/cli.bundle.cjs +49 -45
- package/dist/commands/comments.d.ts +28 -0
- package/dist/commands/comments.js +28 -0
- package/dist/commands/config.d.ts +11 -0
- package/dist/commands/config.js +11 -0
- package/dist/commands/daily.d.ts +26 -2
- package/dist/commands/daily.js +26 -2
- package/dist/commands/detect-formatters.d.ts +11 -0
- package/dist/commands/detect-formatters.js +24 -0
- package/dist/commands/dismiss.d.ts +17 -0
- package/dist/commands/dismiss.js +17 -0
- package/dist/commands/index.d.ts +3 -1
- package/dist/commands/index.js +2 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.js +8 -0
- package/dist/commands/move.d.ts +10 -0
- package/dist/commands/move.js +10 -0
- package/dist/commands/search.d.ts +18 -0
- package/dist/commands/search.js +18 -0
- package/dist/commands/setup.d.ts +17 -0
- package/dist/commands/setup.js +17 -0
- package/dist/commands/shelve.d.ts +16 -0
- package/dist/commands/shelve.js +16 -0
- package/dist/commands/startup.d.ts +16 -7
- package/dist/commands/startup.js +16 -7
- package/dist/commands/status.d.ts +8 -0
- package/dist/commands/status.js +8 -0
- package/dist/commands/track.d.ts +16 -0
- package/dist/commands/track.js +16 -0
- package/dist/commands/vet.d.ts +8 -0
- package/dist/commands/vet.js +8 -0
- package/dist/core/daily-logic.d.ts +60 -7
- package/dist/core/daily-logic.js +52 -7
- package/dist/core/formatter-detection.d.ts +61 -0
- package/dist/core/formatter-detection.js +360 -0
- package/dist/core/github.d.ts +25 -2
- package/dist/core/github.js +25 -2
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +1 -0
- package/dist/core/issue-discovery.d.ts +46 -6
- package/dist/core/issue-discovery.js +46 -6
- package/dist/core/logger.d.ts +13 -0
- package/dist/core/logger.js +13 -0
- package/dist/core/pr-monitor.d.ts +43 -8
- package/dist/core/pr-monitor.js +43 -8
- package/dist/core/state.d.ts +167 -0
- package/dist/core/state.js +167 -0
- package/dist/core/types.d.ts +2 -8
- package/dist/formatters/json.d.ts +5 -0
- package/package.json +6 -3
package/dist/commands/startup.js
CHANGED
|
@@ -15,7 +15,8 @@ import { executeDailyCheck } from './daily.js';
|
|
|
15
15
|
import { launchDashboardServer } from './dashboard-lifecycle.js';
|
|
16
16
|
/**
|
|
17
17
|
* Parse issueListPath from a config file's YAML frontmatter.
|
|
18
|
-
*
|
|
18
|
+
* @param configContent - Raw content of the config.md file
|
|
19
|
+
* @returns The path string or undefined if not found
|
|
19
20
|
*/
|
|
20
21
|
export function parseIssueListPathFromConfig(configContent) {
|
|
21
22
|
const match = configContent.match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -27,8 +28,11 @@ export function parseIssueListPathFromConfig(configContent) {
|
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
30
|
* Count available and completed items in an issue list file.
|
|
30
|
-
* Available: list items (
|
|
31
|
+
* Available: list items (`- [`) NOT struck through or marked Done.
|
|
31
32
|
* Completed: list items that ARE struck through or marked Done.
|
|
33
|
+
*
|
|
34
|
+
* @param content - Raw markdown content of the issue list
|
|
35
|
+
* @returns Counts of available and completed items
|
|
32
36
|
*/
|
|
33
37
|
export function countIssueListItems(content) {
|
|
34
38
|
let availableCount = 0;
|
|
@@ -49,7 +53,7 @@ export function countIssueListItems(content) {
|
|
|
49
53
|
}
|
|
50
54
|
/**
|
|
51
55
|
* Detect an issue list file from config or known paths.
|
|
52
|
-
*
|
|
56
|
+
* @returns Issue list info with path and item counts, or undefined if not found
|
|
53
57
|
*/
|
|
54
58
|
export function detectIssueList() {
|
|
55
59
|
let issueListPath = '';
|
|
@@ -108,6 +112,10 @@ export function detectIssueList() {
|
|
|
108
112
|
return { path: issueListPath, source, availableCount: 0, completedCount: 0 };
|
|
109
113
|
}
|
|
110
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Open a URL in the default system browser.
|
|
117
|
+
* @param url - URL to open
|
|
118
|
+
*/
|
|
111
119
|
export function openInBrowser(url) {
|
|
112
120
|
let openCmd;
|
|
113
121
|
let args;
|
|
@@ -134,11 +142,12 @@ export function openInBrowser(url) {
|
|
|
134
142
|
/**
|
|
135
143
|
* Run startup checks and return structured output.
|
|
136
144
|
* Returns StartupOutput with one of three shapes:
|
|
137
|
-
* 1. Setup incomplete: { version, setupComplete: false }
|
|
138
|
-
* 2. Auth failure: { version, setupComplete: true, authError: "..." }
|
|
139
|
-
* 3. Success: { version, setupComplete: true, daily, dashboardUrl?, issueList? }
|
|
145
|
+
* 1. Setup incomplete: `{ version, setupComplete: false }`
|
|
146
|
+
* 2. Auth failure: `{ version, setupComplete: true, authError: "..." }`
|
|
147
|
+
* 3. Success: `{ version, setupComplete: true, daily, dashboardUrl?, issueList? }`
|
|
140
148
|
*
|
|
141
|
-
*
|
|
149
|
+
* @returns Startup output with auth/setup status and daily digest
|
|
150
|
+
* @throws {Error} If the daily check fails (auth or network errors propagate)
|
|
142
151
|
*/
|
|
143
152
|
export async function runStartup() {
|
|
144
153
|
const version = getCLIVersion();
|
|
@@ -7,4 +7,12 @@ interface StatusOptions {
|
|
|
7
7
|
offline?: boolean;
|
|
8
8
|
}
|
|
9
9
|
export type { StatusOutput };
|
|
10
|
+
/**
|
|
11
|
+
* Return contribution statistics from local state.
|
|
12
|
+
* No API calls — reads from ~/.oss-autopilot/state.json.
|
|
13
|
+
*
|
|
14
|
+
* @param options - Status options
|
|
15
|
+
* @param options.offline - When true, adds cache freshness metadata
|
|
16
|
+
* @returns Contribution stats (merge rate, PR counts, repo breakdown)
|
|
17
|
+
*/
|
|
10
18
|
export declare function runStatus(options: StatusOptions): Promise<StatusOutput>;
|
package/dist/commands/status.js
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
* Shows current status and stats
|
|
4
4
|
*/
|
|
5
5
|
import { getStateManager } from '../core/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Return contribution statistics from local state.
|
|
8
|
+
* No API calls — reads from ~/.oss-autopilot/state.json.
|
|
9
|
+
*
|
|
10
|
+
* @param options - Status options
|
|
11
|
+
* @param options.offline - When true, adds cache freshness metadata
|
|
12
|
+
* @returns Contribution stats (merge rate, PR counts, repo breakdown)
|
|
13
|
+
*/
|
|
6
14
|
export async function runStatus(options) {
|
|
7
15
|
const stateManager = getStateManager();
|
|
8
16
|
const stats = stateManager.getStats();
|
package/dist/commands/track.d.ts
CHANGED
|
@@ -9,9 +9,25 @@ export interface UntrackOutput {
|
|
|
9
9
|
url: string;
|
|
10
10
|
message: string;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Validate and fetch metadata for a PR URL.
|
|
14
|
+
*
|
|
15
|
+
* @param options - Track options
|
|
16
|
+
* @param options.prUrl - Full GitHub PR URL
|
|
17
|
+
* @returns PR metadata (repo, number, title, url)
|
|
18
|
+
* @throws {ValidationError} If the URL is not a valid GitHub PR URL
|
|
19
|
+
*/
|
|
12
20
|
export declare function runTrack(options: {
|
|
13
21
|
prUrl: string;
|
|
14
22
|
}): Promise<TrackOutput>;
|
|
23
|
+
/**
|
|
24
|
+
* No-op in v2 — PRs are fetched fresh on each daily run.
|
|
25
|
+
*
|
|
26
|
+
* @param options - Untrack options
|
|
27
|
+
* @param options.prUrl - Full GitHub PR URL
|
|
28
|
+
* @returns Message explaining v2 behavior
|
|
29
|
+
* @throws {ValidationError} If the URL is not a valid GitHub PR URL
|
|
30
|
+
*/
|
|
15
31
|
export declare function runUntrack(options: {
|
|
16
32
|
prUrl: string;
|
|
17
33
|
}): Promise<UntrackOutput>;
|
package/dist/commands/track.js
CHANGED
|
@@ -6,6 +6,14 @@
|
|
|
6
6
|
import { getOctokit, requireGitHubToken } from '../core/index.js';
|
|
7
7
|
import { validateUrl, PR_URL_PATTERN, validateGitHubUrl } from './validation.js';
|
|
8
8
|
import { parseGitHubUrl } from '../core/utils.js';
|
|
9
|
+
/**
|
|
10
|
+
* Validate and fetch metadata for a PR URL.
|
|
11
|
+
*
|
|
12
|
+
* @param options - Track options
|
|
13
|
+
* @param options.prUrl - Full GitHub PR URL
|
|
14
|
+
* @returns PR metadata (repo, number, title, url)
|
|
15
|
+
* @throws {ValidationError} If the URL is not a valid GitHub PR URL
|
|
16
|
+
*/
|
|
9
17
|
export async function runTrack(options) {
|
|
10
18
|
validateUrl(options.prUrl);
|
|
11
19
|
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, 'PR');
|
|
@@ -26,6 +34,14 @@ export async function runTrack(options) {
|
|
|
26
34
|
},
|
|
27
35
|
};
|
|
28
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* No-op in v2 — PRs are fetched fresh on each daily run.
|
|
39
|
+
*
|
|
40
|
+
* @param options - Untrack options
|
|
41
|
+
* @param options.prUrl - Full GitHub PR URL
|
|
42
|
+
* @returns Message explaining v2 behavior
|
|
43
|
+
* @throws {ValidationError} If the URL is not a valid GitHub PR URL
|
|
44
|
+
*/
|
|
29
45
|
export async function runUntrack(options) {
|
|
30
46
|
validateUrl(options.prUrl);
|
|
31
47
|
validateGitHubUrl(options.prUrl, PR_URL_PATTERN, 'PR');
|
package/dist/commands/vet.d.ts
CHANGED
|
@@ -7,4 +7,12 @@ export { type VetOutput } from '../formatters/json.js';
|
|
|
7
7
|
interface VetOptions {
|
|
8
8
|
issueUrl: string;
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Vet a specific GitHub issue for claimability and project health.
|
|
12
|
+
*
|
|
13
|
+
* @param options - Vet options
|
|
14
|
+
* @param options.issueUrl - Full GitHub issue URL
|
|
15
|
+
* @returns Vetting result with recommendation, health data, and check outcomes
|
|
16
|
+
* @throws {ValidationError} If the URL is not a valid GitHub issue URL
|
|
17
|
+
*/
|
|
10
18
|
export declare function runVet(options: VetOptions): Promise<VetOutput>;
|
package/dist/commands/vet.js
CHANGED
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { IssueDiscovery, requireGitHubToken } from '../core/index.js';
|
|
6
6
|
import { ISSUE_URL_PATTERN, validateGitHubUrl, validateUrl } from './validation.js';
|
|
7
|
+
/**
|
|
8
|
+
* Vet a specific GitHub issue for claimability and project health.
|
|
9
|
+
*
|
|
10
|
+
* @param options - Vet options
|
|
11
|
+
* @param options.issueUrl - Full GitHub issue URL
|
|
12
|
+
* @returns Vetting result with recommendation, health data, and check outcomes
|
|
13
|
+
* @throws {ValidationError} If the URL is not a valid GitHub issue URL
|
|
14
|
+
*/
|
|
7
15
|
export async function runVet(options) {
|
|
8
16
|
validateUrl(options.issueUrl);
|
|
9
17
|
validateGitHubUrl(options.issueUrl, ISSUE_URL_PATTERN, 'issue');
|
|
@@ -25,26 +25,52 @@ export declare const CRITICAL_STATUSES: ReadonlySet<FetchedPRStatus>;
|
|
|
25
25
|
export declare const CRITICAL_ACTION_REASONS: ReadonlySet<ActionReason>;
|
|
26
26
|
/** Staleness tiers indicating staleness — maintainer comments during these tiers don't count as responsive. */
|
|
27
27
|
export declare const STALE_STATUSES: ReadonlySet<StalenessTier>;
|
|
28
|
+
/**
|
|
29
|
+
* Apply status overrides from state to the PR list.
|
|
30
|
+
* Overrides are auto-cleared if the PR has new activity since the override was set.
|
|
31
|
+
*
|
|
32
|
+
* When an override changes the status, the contradictory reason field is cleared
|
|
33
|
+
* and an appropriate default is set so downstream logic (assessCapacity, collectActionableIssues)
|
|
34
|
+
* works correctly.
|
|
35
|
+
*
|
|
36
|
+
* @param prs - The fetched PR list to apply overrides to
|
|
37
|
+
* @param state - Current agent state containing status overrides
|
|
38
|
+
* @returns New PR array with overrides applied (original array is not mutated)
|
|
39
|
+
*/
|
|
28
40
|
export declare function applyStatusOverrides(prs: FetchedPR[], state: Readonly<AgentState>): FetchedPR[];
|
|
29
41
|
/**
|
|
30
|
-
*
|
|
42
|
+
* Project a PR to a lightweight ShelvedPRRef for digest output.
|
|
31
43
|
* Only the fields needed for display are retained, reducing JSON payload size.
|
|
44
|
+
*
|
|
45
|
+
* @param pr - Any object with at least the ShelvedPRRef fields
|
|
46
|
+
* @returns Lightweight reference for display
|
|
32
47
|
*/
|
|
33
|
-
export declare function toShelvedPRRef(pr:
|
|
48
|
+
export declare function toShelvedPRRef(pr: ShelvedPRRef): ShelvedPRRef;
|
|
34
49
|
/**
|
|
35
50
|
* Group PRs by repository (#80).
|
|
36
51
|
* Ensures one agent per repo during parallel dispatch, preventing branch checkout conflicts.
|
|
52
|
+
*
|
|
53
|
+
* @param prs - PRs to group
|
|
54
|
+
* @returns Array of repo groups, each with the repo name and its PRs
|
|
37
55
|
*/
|
|
38
56
|
export declare function groupPRsByRepo(prs: FetchedPR[]): RepoGroup[];
|
|
39
57
|
/**
|
|
40
58
|
* Compute per-repo maintainer signals from observed open PR data.
|
|
41
59
|
* - isResponsive: true if any PR in the repo has a maintainer comment and stalenessTier is active
|
|
42
60
|
* - hasActiveMaintainers: true if any non-stale PR exists in the repo (stalenessTier is 'active')
|
|
61
|
+
*
|
|
62
|
+
* @param prs - Open PRs to compute signals from
|
|
63
|
+
* @returns Map of repo names to maintainer responsiveness signals
|
|
43
64
|
*/
|
|
44
65
|
export declare function computeRepoSignals(prs: FetchedPR[]): Map<string, ComputedRepoSignals>;
|
|
45
66
|
/**
|
|
46
67
|
* Assess whether user has capacity for new issues.
|
|
47
68
|
* Only active (non-shelved) PRs count against the limit.
|
|
69
|
+
*
|
|
70
|
+
* @param activePRs - Non-shelved open PRs
|
|
71
|
+
* @param maxActivePRs - User's configured PR limit
|
|
72
|
+
* @param shelvedPRCount - Number of shelved PRs (for display)
|
|
73
|
+
* @returns Capacity assessment with reason string
|
|
48
74
|
*/
|
|
49
75
|
export declare function assessCapacity(activePRs: FetchedPR[], maxActivePRs: number, shelvedPRCount: number): CapacityAssessment;
|
|
50
76
|
/**
|
|
@@ -53,29 +79,56 @@ export declare function assessCapacity(activePRs: FetchedPR[], maxActivePRs: num
|
|
|
53
79
|
*
|
|
54
80
|
* Note: Recently closed PRs are informational only and excluded from this list.
|
|
55
81
|
* They are available separately in digest.recentlyClosedPRs (#156).
|
|
82
|
+
*
|
|
83
|
+
* @param prs - Active (non-shelved) PRs to check
|
|
84
|
+
* @param lastDigestAt - ISO timestamp of previous digest (for "new contribution" detection)
|
|
85
|
+
* @returns Ordered actionable issues grouped by priority
|
|
56
86
|
*/
|
|
57
87
|
export declare function collectActionableIssues(prs: FetchedPR[], lastDigestAt?: string): ActionableIssue[];
|
|
58
88
|
/**
|
|
59
|
-
* Format a maintainer action hint as a human-readable label
|
|
89
|
+
* Format a maintainer action hint as a human-readable label.
|
|
90
|
+
* @param hint - The maintainer action hint enum value
|
|
91
|
+
* @returns Human-readable label (e.g., "tests requested")
|
|
60
92
|
*/
|
|
61
93
|
export declare function formatActionHint(hint: MaintainerActionHint): string;
|
|
62
94
|
/**
|
|
63
95
|
* Compute the action menu from PR data and capacity.
|
|
64
96
|
* The orchestration layer can insert issue-list options (e.g., "Pick from list")
|
|
65
97
|
* using the context flags.
|
|
98
|
+
*
|
|
99
|
+
* @param actionableIssues - Issues requiring attention
|
|
100
|
+
* @param capacity - Current capacity assessment
|
|
101
|
+
* @param commentedIssues - Issues with comment activity
|
|
102
|
+
* @returns Action menu with context flags for orchestration
|
|
66
103
|
*/
|
|
67
104
|
export declare function computeActionMenu(actionableIssues: ActionableIssue[], capacity: CapacityAssessment, commentedIssues?: CommentedIssue[]): ActionMenu;
|
|
68
105
|
/**
|
|
69
|
-
* Format a brief one-liner summary for the action-first flow
|
|
106
|
+
* Format a brief one-liner summary for the action-first flow.
|
|
107
|
+
*
|
|
108
|
+
* @param digest - The daily digest containing PR summary stats
|
|
109
|
+
* @param issueCount - Number of actionable issues needing attention
|
|
110
|
+
* @param issueResponseCount - Number of issue replies from maintainers
|
|
111
|
+
* @returns One-line status string (e.g., "3 Active PRs | 1 needs attention | 2 issue replies")
|
|
70
112
|
*/
|
|
71
113
|
export declare function formatBriefSummary(digest: DailyDigest, issueCount: number, issueResponseCount?: number): string;
|
|
72
114
|
/**
|
|
73
|
-
* Format summary as markdown
|
|
115
|
+
* Format the full dashboard summary as markdown.
|
|
116
|
+
* Used in JSON output for Claude to display verbatim — includes all PR sections,
|
|
117
|
+
* issue replies, and capacity status.
|
|
118
|
+
*
|
|
119
|
+
* @param digest - The daily digest with all PR categories
|
|
120
|
+
* @param capacity - Current capacity assessment for display
|
|
121
|
+
* @param issueResponses - Issue replies from maintainers to display
|
|
122
|
+
* @returns Multi-line markdown string suitable for terminal or chat display
|
|
74
123
|
*/
|
|
75
124
|
export declare function formatSummary(digest: DailyDigest, capacity: CapacityAssessment, issueResponses?: CommentedIssueWithResponse[]): string;
|
|
76
125
|
/**
|
|
77
|
-
* Print digest to console
|
|
78
|
-
* Unified renderer: uses the same section ordering as formatSummary
|
|
126
|
+
* Print digest to console as plain text.
|
|
127
|
+
* Unified renderer: uses the same section ordering as {@link formatSummary}
|
|
79
128
|
* but outputs plain text with console.log instead of markdown links.
|
|
129
|
+
*
|
|
130
|
+
* @param digest - The daily digest with all PR categories
|
|
131
|
+
* @param capacity - Current capacity assessment for display
|
|
132
|
+
* @param commentedIssues - All commented issues (filtered to responses internally)
|
|
80
133
|
*/
|
|
81
134
|
export declare function printDigest(digest: DailyDigest, capacity: CapacityAssessment, commentedIssues?: CommentedIssue[]): void;
|
package/dist/core/daily-logic.js
CHANGED
|
@@ -38,6 +38,7 @@ export const STALE_STATUSES = new Set(['dormant', 'approaching_dormant']);
|
|
|
38
38
|
// ---------------------------------------------------------------------------
|
|
39
39
|
// Status overrides
|
|
40
40
|
// ---------------------------------------------------------------------------
|
|
41
|
+
const VALID_OVERRIDE_STATUSES = new Set(['needs_addressing', 'waiting_on_maintainer']);
|
|
41
42
|
/**
|
|
42
43
|
* Apply status overrides from state to the PR list.
|
|
43
44
|
* Overrides are auto-cleared if the PR has new activity since the override was set.
|
|
@@ -45,8 +46,11 @@ export const STALE_STATUSES = new Set(['dormant', 'approaching_dormant']);
|
|
|
45
46
|
* When an override changes the status, the contradictory reason field is cleared
|
|
46
47
|
* and an appropriate default is set so downstream logic (assessCapacity, collectActionableIssues)
|
|
47
48
|
* works correctly.
|
|
49
|
+
*
|
|
50
|
+
* @param prs - The fetched PR list to apply overrides to
|
|
51
|
+
* @param state - Current agent state containing status overrides
|
|
52
|
+
* @returns New PR array with overrides applied (original array is not mutated)
|
|
48
53
|
*/
|
|
49
|
-
const VALID_OVERRIDE_STATUSES = new Set(['needs_addressing', 'waiting_on_maintainer']);
|
|
50
54
|
export function applyStatusOverrides(prs, state) {
|
|
51
55
|
const overrides = state.config.statusOverrides;
|
|
52
56
|
if (!overrides || Object.keys(overrides).length === 0)
|
|
@@ -106,8 +110,11 @@ function buildRepoMap(prs, label) {
|
|
|
106
110
|
// Domain functions
|
|
107
111
|
// ---------------------------------------------------------------------------
|
|
108
112
|
/**
|
|
109
|
-
*
|
|
113
|
+
* Project a PR to a lightweight ShelvedPRRef for digest output.
|
|
110
114
|
* Only the fields needed for display are retained, reducing JSON payload size.
|
|
115
|
+
*
|
|
116
|
+
* @param pr - Any object with at least the ShelvedPRRef fields
|
|
117
|
+
* @returns Lightweight reference for display
|
|
111
118
|
*/
|
|
112
119
|
export function toShelvedPRRef(pr) {
|
|
113
120
|
return {
|
|
@@ -122,6 +129,9 @@ export function toShelvedPRRef(pr) {
|
|
|
122
129
|
/**
|
|
123
130
|
* Group PRs by repository (#80).
|
|
124
131
|
* Ensures one agent per repo during parallel dispatch, preventing branch checkout conflicts.
|
|
132
|
+
*
|
|
133
|
+
* @param prs - PRs to group
|
|
134
|
+
* @returns Array of repo groups, each with the repo name and its PRs
|
|
125
135
|
*/
|
|
126
136
|
export function groupPRsByRepo(prs) {
|
|
127
137
|
const repoMap = buildRepoMap(prs, 'GROUP_BY_REPO');
|
|
@@ -135,6 +145,9 @@ export function groupPRsByRepo(prs) {
|
|
|
135
145
|
* Compute per-repo maintainer signals from observed open PR data.
|
|
136
146
|
* - isResponsive: true if any PR in the repo has a maintainer comment and stalenessTier is active
|
|
137
147
|
* - hasActiveMaintainers: true if any non-stale PR exists in the repo (stalenessTier is 'active')
|
|
148
|
+
*
|
|
149
|
+
* @param prs - Open PRs to compute signals from
|
|
150
|
+
* @returns Map of repo names to maintainer responsiveness signals
|
|
138
151
|
*/
|
|
139
152
|
export function computeRepoSignals(prs) {
|
|
140
153
|
const repoMap = buildRepoMap(prs, 'COMPUTE_SIGNALS');
|
|
@@ -149,6 +162,11 @@ export function computeRepoSignals(prs) {
|
|
|
149
162
|
/**
|
|
150
163
|
* Assess whether user has capacity for new issues.
|
|
151
164
|
* Only active (non-shelved) PRs count against the limit.
|
|
165
|
+
*
|
|
166
|
+
* @param activePRs - Non-shelved open PRs
|
|
167
|
+
* @param maxActivePRs - User's configured PR limit
|
|
168
|
+
* @param shelvedPRCount - Number of shelved PRs (for display)
|
|
169
|
+
* @returns Capacity assessment with reason string
|
|
152
170
|
*/
|
|
153
171
|
export function assessCapacity(activePRs, maxActivePRs, shelvedPRCount) {
|
|
154
172
|
const activePRCount = activePRs.length;
|
|
@@ -188,6 +206,10 @@ export function assessCapacity(activePRs, maxActivePRs, shelvedPRCount) {
|
|
|
188
206
|
*
|
|
189
207
|
* Note: Recently closed PRs are informational only and excluded from this list.
|
|
190
208
|
* They are available separately in digest.recentlyClosedPRs (#156).
|
|
209
|
+
*
|
|
210
|
+
* @param prs - Active (non-shelved) PRs to check
|
|
211
|
+
* @param lastDigestAt - ISO timestamp of previous digest (for "new contribution" detection)
|
|
212
|
+
* @returns Ordered actionable issues grouped by priority
|
|
191
213
|
*/
|
|
192
214
|
export function collectActionableIssues(prs, lastDigestAt) {
|
|
193
215
|
const issues = [];
|
|
@@ -256,7 +278,9 @@ export function collectActionableIssues(prs, lastDigestAt) {
|
|
|
256
278
|
return issues;
|
|
257
279
|
}
|
|
258
280
|
/**
|
|
259
|
-
* Format a maintainer action hint as a human-readable label
|
|
281
|
+
* Format a maintainer action hint as a human-readable label.
|
|
282
|
+
* @param hint - The maintainer action hint enum value
|
|
283
|
+
* @returns Human-readable label (e.g., "tests requested")
|
|
260
284
|
*/
|
|
261
285
|
export function formatActionHint(hint) {
|
|
262
286
|
switch (hint) {
|
|
@@ -276,6 +300,11 @@ export function formatActionHint(hint) {
|
|
|
276
300
|
* Compute the action menu from PR data and capacity.
|
|
277
301
|
* The orchestration layer can insert issue-list options (e.g., "Pick from list")
|
|
278
302
|
* using the context flags.
|
|
303
|
+
*
|
|
304
|
+
* @param actionableIssues - Issues requiring attention
|
|
305
|
+
* @param capacity - Current capacity assessment
|
|
306
|
+
* @param commentedIssues - Issues with comment activity
|
|
307
|
+
* @returns Action menu with context flags for orchestration
|
|
279
308
|
*/
|
|
280
309
|
export function computeActionMenu(actionableIssues, capacity, commentedIssues = []) {
|
|
281
310
|
const issueResponses = commentedIssues.filter((i) => i.status === 'new_response');
|
|
@@ -329,7 +358,12 @@ export function computeActionMenu(actionableIssues, capacity, commentedIssues =
|
|
|
329
358
|
// Rendering / formatting
|
|
330
359
|
// ---------------------------------------------------------------------------
|
|
331
360
|
/**
|
|
332
|
-
* Format a brief one-liner summary for the action-first flow
|
|
361
|
+
* Format a brief one-liner summary for the action-first flow.
|
|
362
|
+
*
|
|
363
|
+
* @param digest - The daily digest containing PR summary stats
|
|
364
|
+
* @param issueCount - Number of actionable issues needing attention
|
|
365
|
+
* @param issueResponseCount - Number of issue replies from maintainers
|
|
366
|
+
* @returns One-line status string (e.g., "3 Active PRs | 1 needs attention | 2 issue replies")
|
|
333
367
|
*/
|
|
334
368
|
export function formatBriefSummary(digest, issueCount, issueResponseCount = 0) {
|
|
335
369
|
const attentionText = issueCount > 0 ? `${issueCount} need${issueCount === 1 ? 's' : ''} attention` : 'all on track';
|
|
@@ -337,7 +371,14 @@ export function formatBriefSummary(digest, issueCount, issueResponseCount = 0) {
|
|
|
337
371
|
return `\u{1F4CA} ${digest.summary.totalActivePRs} Active PRs | ${attentionText}${issueReplyText}`;
|
|
338
372
|
}
|
|
339
373
|
/**
|
|
340
|
-
* Format summary as markdown
|
|
374
|
+
* Format the full dashboard summary as markdown.
|
|
375
|
+
* Used in JSON output for Claude to display verbatim — includes all PR sections,
|
|
376
|
+
* issue replies, and capacity status.
|
|
377
|
+
*
|
|
378
|
+
* @param digest - The daily digest with all PR categories
|
|
379
|
+
* @param capacity - Current capacity assessment for display
|
|
380
|
+
* @param issueResponses - Issue replies from maintainers to display
|
|
381
|
+
* @returns Multi-line markdown string suitable for terminal or chat display
|
|
341
382
|
*/
|
|
342
383
|
export function formatSummary(digest, capacity, issueResponses = []) {
|
|
343
384
|
const lines = [];
|
|
@@ -418,9 +459,13 @@ export function formatSummary(digest, capacity, issueResponses = []) {
|
|
|
418
459
|
return lines.join('\n');
|
|
419
460
|
}
|
|
420
461
|
/**
|
|
421
|
-
* Print digest to console
|
|
422
|
-
* Unified renderer: uses the same section ordering as formatSummary
|
|
462
|
+
* Print digest to console as plain text.
|
|
463
|
+
* Unified renderer: uses the same section ordering as {@link formatSummary}
|
|
423
464
|
* but outputs plain text with console.log instead of markdown links.
|
|
465
|
+
*
|
|
466
|
+
* @param digest - The daily digest with all PR categories
|
|
467
|
+
* @param capacity - Current capacity assessment for display
|
|
468
|
+
* @param commentedIssues - All commented issues (filtered to responses internally)
|
|
424
469
|
*/
|
|
425
470
|
export function printDigest(digest, capacity, commentedIssues = []) {
|
|
426
471
|
console.log('\n\u{1F4CA} OSS Daily Check\n');
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatter Detection Module (#703)
|
|
3
|
+
*
|
|
4
|
+
* Programmatically detects formatters/linters configured in a local repo directory
|
|
5
|
+
* and diagnoses CI formatting failures from log output.
|
|
6
|
+
*/
|
|
7
|
+
export type FormatterName = 'prettier' | 'eslint' | 'biome' | 'black' | 'ruff' | 'rustfmt' | 'gofmt' | 'clang-format' | 'rubocop';
|
|
8
|
+
export interface DetectedFormatter {
|
|
9
|
+
name: FormatterName;
|
|
10
|
+
/** Relative to repo root */
|
|
11
|
+
configPath: string;
|
|
12
|
+
/** e.g., "npx prettier --write ." */
|
|
13
|
+
fixCommand: string;
|
|
14
|
+
/** e.g., "npx prettier --check ." */
|
|
15
|
+
checkCommand: string;
|
|
16
|
+
/** Whether the formatter accepts individual file paths as arguments */
|
|
17
|
+
supportsFileArgs: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface FormatterDetectionResult {
|
|
20
|
+
formatters: DetectedFormatter[];
|
|
21
|
+
packageJsonScripts: {
|
|
22
|
+
name: string;
|
|
23
|
+
command: string;
|
|
24
|
+
}[];
|
|
25
|
+
repoPath: string;
|
|
26
|
+
}
|
|
27
|
+
export interface CIFormatterDiagnosis {
|
|
28
|
+
isFormattingFailure: boolean;
|
|
29
|
+
formatter?: FormatterName;
|
|
30
|
+
fixCommand?: string;
|
|
31
|
+
evidence: string[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Detect formatters and linters configured in a repository.
|
|
35
|
+
*
|
|
36
|
+
* Checks config files in priority order using fs.existsSync() / fs.readFileSync().
|
|
37
|
+
* Returns all detected formatters, plus any formatting-related package.json scripts.
|
|
38
|
+
*
|
|
39
|
+
* @param repoPath - Absolute path to the repository root directory
|
|
40
|
+
* @returns Detection result with formatters ordered by priority and extracted package.json scripts
|
|
41
|
+
* @throws {Error} If repoPath does not exist or is not a directory
|
|
42
|
+
*/
|
|
43
|
+
export declare function detectFormatters(repoPath: string): FormatterDetectionResult;
|
|
44
|
+
/**
|
|
45
|
+
* Diagnose whether CI log output indicates a formatting failure.
|
|
46
|
+
*
|
|
47
|
+
* Pattern-matches known formatter error strings. When repoPath is provided,
|
|
48
|
+
* cross-references with {@link detectFormatters} to provide a targeted fix command.
|
|
49
|
+
*
|
|
50
|
+
* @param logOutput - Raw CI log output to analyze
|
|
51
|
+
* @param repoPath - Optional repo path for cross-referencing with local formatter config
|
|
52
|
+
* @returns Diagnosis with matched formatter, fix command, and evidence strings
|
|
53
|
+
*/
|
|
54
|
+
export declare function diagnoseCIFormatterFailure(logOutput: string, repoPath?: string): CIFormatterDiagnosis;
|
|
55
|
+
/**
|
|
56
|
+
* Return the first (highest-priority) detected formatter, or undefined if none found.
|
|
57
|
+
*
|
|
58
|
+
* @param result - Detection result from {@link detectFormatters}
|
|
59
|
+
* @returns The highest-priority formatter, or undefined if none detected
|
|
60
|
+
*/
|
|
61
|
+
export declare function getPreferredFormatter(result: FormatterDetectionResult): DetectedFormatter | undefined;
|