Skip to content
← Public packages

@kentcdodds/sentry-triage

Sentry triage wakes Cole (Grok Bot) per issue: one active wake per repo (lease + queue), loop-safe Discord. Cole may spawn Cursor for isolated repo work.

src/triage-core.test.ts

160 lines · 4.1 KB · TypeScript
import assert from 'node:assert/strict'
import { describe, it } from 'node:test'
import { seerGraceMs, seerPrGraceMs } from './shared.ts'
import {
	awaitingSeerGraceMs,
	findStaleAwaitingIssues,
	isAwaitingSeerStale,
} from './awaiting-seer.ts'

const now = Date.parse('2026-08-20T16:30:00.000Z')

function issue(overrides) {
	return {
		issueId: '1',
		projectSlug: 'kody',
		shortId: 'KODY-1',
		status: 'awaiting-seer',
		seerRequestedAt: new Date(now - seerGraceMs - 1).toISOString(),
		...overrides,
	}
}

function memoryStorage(records, { pageSize = Infinity } = {}) {
	const all = Object.entries(records)
		.sort(([a], [b]) => a.localeCompare(b))
		.map(([key, value]) => ({ key, value }))
	return {
		async list({ prefix = '', startAfter = null, limit = pageSize } = {}) {
			let rows = all.filter((entry) => entry.key.startsWith(prefix))
			if (startAfter) {
				rows = rows.filter((entry) => entry.key > startAfter)
			}
			const page = rows.slice(0, Number.isFinite(limit) ? limit : rows.length)
			const truncated = page.length < rows.length
			return {
				entries: page,
				truncated,
				nextStartAfter: truncated ? page[page.length - 1]?.key ?? null : null,
				pageSize: Number.isFinite(limit) ? limit : page.length,
			}
		},
		async get(key) {
			return records[key] ?? null
		},
	}
}

describe('isAwaitingSeerStale', () => {
	it('treats awaiting-seer as stale only after the 15-minute RCA grace', () => {
		assert.equal(awaitingSeerGraceMs('awaiting-seer'), seerGraceMs)
		assert.equal(
			isAwaitingSeerStale(
				issue({
					seerRequestedAt: new Date(now - seerGraceMs + 1).toISOString(),
				}),
				now,
			),
			false,
		)
		assert.equal(
			isAwaitingSeerStale(
				issue({
					seerRequestedAt: new Date(now - seerGraceMs - 1).toISOString(),
				}),
				now,
			),
			true,
		)
	})

	it('treats awaiting-seer-pr as stale only after the 45-minute PR grace', () => {
		assert.equal(awaitingSeerGraceMs('awaiting-seer-pr'), seerPrGraceMs)
		assert.equal(
			isAwaitingSeerStale(
				issue({
					status: 'awaiting-seer-pr',
					seerPrAwaitedAt: new Date(now - seerPrGraceMs + 1).toISOString(),
				}),
				now,
			),
			false,
		)
		assert.equal(
			isAwaitingSeerStale(
				issue({
					status: 'awaiting-seer-pr',
					seerPrAwaitedAt: new Date(now - seerPrGraceMs - 1).toISOString(),
				}),
				now,
			),
			true,
		)
	})

	it('ignores non-awaiting statuses and incomplete records', () => {
		assert.equal(
			isAwaitingSeerStale(issue({ status: 'agent-spawned' }), now),
			false,
		)
		assert.equal(isAwaitingSeerStale(issue({ issueId: undefined }), now), false)
		assert.equal(
			isAwaitingSeerStale(issue({ projectSlug: undefined }), now),
			false,
		)
	})
})

describe('findStaleAwaitingIssues', () => {
	it('returns oldest stale records first and respects the limit', async () => {
		const older = issue({
			issueId: 'old',
			shortId: 'OLD',
			seerRequestedAt: new Date(now - seerGraceMs - 60_000).toISOString(),
		})
		const newer = issue({
			issueId: 'new',
			shortId: 'NEW',
			seerRequestedAt: new Date(now - seerGraceMs - 1).toISOString(),
		})
		const fresh = issue({
			issueId: 'fresh',
			seerRequestedAt: new Date(now - 60_000).toISOString(),
		})
		const found = await findStaleAwaitingIssues(
			memoryStorage({
				'issue:new': newer,
				'issue:fresh': fresh,
				'issue:old': older,
			}),
			1,
			now,
		)
		assert.equal(found.length, 1)
		assert.equal(found[0].issueId, 'old')
	})
	it('pages past the first packageStorage list page to find newer stale keys', async () => {
		const records = {}
		for (let i = 0; i < 5; i++) {
			const id = String(1000 + i)
			records[`issue:${id}`] = issue({
				issueId: id,
				shortId: `OLD-${i}`,
				status: 'fixed',
				seerRequestedAt: new Date(now - seerGraceMs - 1).toISOString(),
			})
		}
		const staleId = '9999'
		records[`issue:${staleId}`] = issue({
			issueId: staleId,
			shortId: 'NEW-STALE',
			seerRequestedAt: new Date(now - seerGraceMs - 1).toISOString(),
		})
		const found = await findStaleAwaitingIssues(
			memoryStorage(records, { pageSize: 3 }),
			5,
			now,
		)
		assert.equal(found.some((record) => record.issueId === staleId), true)
	})
})