Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/ai-angular/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"noEmit": true,
"module": "preserve",
Expand Down
2 changes: 1 addition & 1 deletion scripts/maintainer/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* through the REST API.
*/

import type { GitHubClient } from './github'
import type { GitHubClient } from './github.ts'

export const MANAGED_LABELS: Array<{
name: string
Expand Down
6 changes: 3 additions & 3 deletions scripts/maintainer/classify.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest'
import { classifyDiscussion, classifyIssue, classifyPR } from './classify'
import { ACK_MARKER, REPRO_MARKER } from './comments'
import { classifyDiscussion, classifyIssue, classifyPR } from './classify.ts'
import { ACK_MARKER, REPRO_MARKER } from './comments.ts'
import {
NOW,
comment,
Expand All @@ -12,7 +12,7 @@ import {
makeIssue,
makePR,
review,
} from './fixtures'
} from './fixtures.ts'

describe('classifyPR — waiting-on state machine', () => {
it('brand-new PR with no maintainer response waits on maintainer', () => {
Expand Down
8 changes: 4 additions & 4 deletions scripts/maintainer/classify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
* heuristic, and per-item hygiene checks. No I/O — fixture-testable.
*/

import { isRosterMaintainer } from './config'
import { ACK_MARKER, REPRO_MARKER } from './comments'
import { matchesAnyGlob } from './glob'
import { isRosterMaintainer } from './config.ts'
import { ACK_MARKER, REPRO_MARKER } from './comments.ts'
import { matchesAnyGlob } from './glob.ts'
import type {
DiscussionItem,
DiscussionTriage,
Expand All @@ -18,7 +18,7 @@ import type {
ToolsetConfig,
TriageResult,
WaitingOn,
} from './types'
} from './types.ts'

export const HOUR_MS = 60 * 60 * 1000

Expand Down
6 changes: 3 additions & 3 deletions scripts/maintainer/collect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* the shapes in types.ts. Read-only — never mutates anything.
*/

import { isBotLogin } from './config'
import type { GitHubClient } from './github'
import { isBotLogin } from './config.ts'
import type { GitHubClient } from './github.ts'
import type {
CIState,
ClosedItem,
Expand All @@ -15,7 +15,7 @@ import type {
RepoSnapshot,
TimelineEvent,
ToolsetConfig,
} from './types'
} from './types.ts'

const CLOSED_LOOKBACK_DAYS = 14

Expand Down
2 changes: 1 addition & 1 deletion scripts/maintainer/comments.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { PRTriage } from './types'
import type { PRTriage } from './types.ts'

/**
* HTML markers embedded in bot comments so sweeps stay idempotent: before
Expand Down
2 changes: 1 addition & 1 deletion scripts/maintainer/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { readFile } from 'node:fs/promises'
import type { ToolsetConfig } from './types'
import type { ToolsetConfig } from './types.ts'

export const DEFAULT_CONFIG_PATH = '.github/maintainers.json'

Expand Down
4 changes: 2 additions & 2 deletions scripts/maintainer/discord.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* Rendering is pure; posting takes an injected fetch.
*/

import { formatDuration } from './metrics'
import type { Scorecard } from './metrics'
import { formatDuration } from './metrics.ts'
import type { Scorecard } from './metrics.ts'

const MAX_LINES_PER_SECTION = 12
const MAX_EMBED_DESCRIPTION = 4000
Expand Down
2 changes: 1 addition & 1 deletion scripts/maintainer/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {
PRItem,
TimelineEvent,
ToolsetConfig,
} from './types'
} from './types.ts'

export const NOW = new Date('2026-07-16T00:00:00Z')

Expand Down
10 changes: 5 additions & 5 deletions scripts/maintainer/metrics.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { describe, expect, it } from 'vitest'
import { classifyAll } from './classify'
import { buildScorecardEmbeds, chunkEmbeds } from './discord'
import { computeScorecard, formatDuration, percentile } from './metrics'
import { classifyAll } from './classify.ts'
import { buildScorecardEmbeds, chunkEmbeds } from './discord.ts'
import { computeScorecard, formatDuration, percentile } from './metrics.ts'
import {
NOW,
review,
Expand All @@ -12,8 +12,8 @@ import {
makeDiscussion,
makeIssue,
makePR,
} from './fixtures'
import type { RepoSnapshot } from './types'
} from './fixtures.ts'
import type { RepoSnapshot } from './types.ts'

function snapshotFixture(): RepoSnapshot {
return {
Expand Down
8 changes: 4 additions & 4 deletions scripts/maintainer/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
* sections and stats. Pure — no I/O.
*/

import { deriveResponseState } from './classify'
import { isRosterMaintainer } from './config'
import { computeLoad, routePR } from './route'
import { deriveResponseState } from './classify.ts'
import { isRosterMaintainer } from './config.ts'
import { computeLoad, routePR } from './route.ts'
import type {
DiscussionTriage,
IssueTriage,
PRTriage,
RepoSnapshot,
ToolsetConfig,
TriageResult,
} from './types'
} from './types.ts'

const DAY_MS = 24 * 60 * 60 * 1000

Expand Down
11 changes: 8 additions & 3 deletions scripts/maintainer/route.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { describe, expect, it } from 'vitest'
import { globToRegExp, matchesGlob } from './glob'
import { computeLoad, requiresCoreReview, routeIssue, routePR } from './route'
import { config, daysAgo } from './fixtures'
import { globToRegExp, matchesGlob } from './glob.ts'
import {
computeLoad,
requiresCoreReview,
routeIssue,
routePR,
} from './route.ts'
import { config, daysAgo } from './fixtures.ts'

describe('glob matcher', () => {
it.each([
Expand Down
4 changes: 2 additions & 2 deletions scripts/maintainer/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* needing any stored state.
*/

import { matchesAnyGlob, matchesGlob } from './glob'
import type { ClosedItem, MaintainerEntry, ToolsetConfig } from './types'
import { matchesAnyGlob, matchesGlob } from './glob.ts'
import type { ClosedItem, MaintainerEntry, ToolsetConfig } from './types.ts'

export type AssignmentLoad = Map<string, number>

Expand Down
14 changes: 7 additions & 7 deletions scripts/maintainer/scorecard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@

import { readdir } from 'node:fs/promises'
import process from 'node:process'
import { classifyAll } from './classify'
import { collectSnapshot } from './collect'
import { loadConfig } from './config'
import { buildScorecardEmbeds, postToDiscord } from './discord'
import { createGitHubClient } from './github'
import { computeScorecard } from './metrics'
import { isDryRun, resolveToken, writeStepSummary } from './env'
import { classifyAll } from './classify.ts'
import { collectSnapshot } from './collect.ts'
import { loadConfig } from './config.ts'
import { buildScorecardEmbeds, postToDiscord } from './discord.ts'
import { createGitHubClient } from './github.ts'
import { computeScorecard } from './metrics.ts'
import { isDryRun, resolveToken, writeStepSummary } from './env.ts'

async function countPendingChangesets(): Promise<number> {
try {
Expand Down
36 changes: 25 additions & 11 deletions scripts/maintainer/sweep.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { execFile } from 'node:child_process'
import { promisify } from 'node:util'
import { describe, expect, it } from 'vitest'
import { executeMutations, planLabelChanges } from './actions'
import { ACK_MARKER, REPRO_MARKER, buildAckComment } from './comments'
import { classifyPR } from './classify'
import { planSweep } from './sweep'
import { executeMutations, planLabelChanges } from './actions.ts'
import { ACK_MARKER, REPRO_MARKER, buildAckComment } from './comments.ts'
import { classifyPR } from './classify.ts'
import { planSweep } from './sweep.ts'
import {
NOW,
review,
Expand All @@ -12,8 +14,8 @@ import {
hoursAgo,
makeIssue,
makePR,
} from './fixtures'
import type { RepoSnapshot } from './types'
} from './fixtures.ts'
import type { RepoSnapshot } from './types.ts'

function makeSnapshot(overrides: Partial<RepoSnapshot> = {}): RepoSnapshot {
return {
Expand Down Expand Up @@ -376,11 +378,11 @@ describe('routing and review requests', () => {
})

it('runs collection → routing → REST mutations → scorecard with paginated GitHub data', async () => {
const { collectSnapshot } = await import('./collect')
const { createGitHubClient } = await import('./github')
const { classifyAll } = await import('./classify')
const { computeScorecard } = await import('./metrics')
const { buildScorecardEmbeds } = await import('./discord')
const { collectSnapshot } = await import('./collect.ts')
const { createGitHubClient } = await import('./github.ts')
const { classifyAll } = await import('./classify.ts')
const { computeScorecard } = await import('./metrics.ts')
const { buildScorecardEmbeds } = await import('./discord.ts')
const roster = {
...config,
maintainers: config.maintainers.map((m) => ({
Expand Down Expand Up @@ -573,3 +575,15 @@ it('does not treat assignment or review-request events as contributor replies',
expect(after.unansweredSince).toBe(before.unansweredSince)
expect(after.firstResponseHours).toBe(before.firstResponseHours)
})

const execFileAsync = promisify(execFile)

it('links the sweep module when node loads the file', async () => {
const sweepHref = new URL('./sweep.ts', import.meta.url).href
const { stdout } = await execFileAsync(process.execPath, [
'--input-type=module',
'--eval',
`await import(${JSON.stringify(sweepHref)}); console.log('sweep-module-linked')`,
])
expect(stdout).toContain('sweep-module-linked')
})
25 changes: 15 additions & 10 deletions scripts/maintainer/sweep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,21 @@ import {
ensureManagedLabels,
executeMutations,
planLabelChanges,
} from './actions'
import { classifyAll } from './classify'
import { collectSnapshot } from './collect'
import { buildAckComment, buildReproComment } from './comments'
import { isRosterMaintainer, loadConfig } from './config'
import { createGitHubClient } from './github'
import { computeLoad, requiresCoreReview, routeIssue, routePR } from './route'
import { isDryRun, resolveToken, writeStepSummary } from './env'
import type { Mutation } from './actions'
import type { PRItem, RepoSnapshot, ToolsetConfig } from './types'
} from './actions.ts'
import { classifyAll } from './classify.ts'
import { collectSnapshot } from './collect.ts'
import { buildAckComment, buildReproComment } from './comments.ts'
import { isRosterMaintainer, loadConfig } from './config.ts'
import { createGitHubClient } from './github.ts'
import {
computeLoad,
requiresCoreReview,
routeIssue,
routePR,
} from './route.ts'
import { isDryRun, resolveToken, writeStepSummary } from './env.ts'
import type { Mutation } from './actions.ts'
import type { PRItem, RepoSnapshot, ToolsetConfig } from './types.ts'

export interface SweepPlan {
mutations: Array<Mutation>
Expand Down
3 changes: 3 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "./tsconfig.base.json",
"compilerOptions": {
"allowImportingTsExtensions": true
},
"include": ["scripts", "*.config.ts", "*.config.js"]
}
Loading