Skip to content
← Public packages

@kentcdodds/kody-issue-triage

Loop-safe triage for Kody run errors and fleet package-runtime error-rate elevations. Wakes Cole (Grok Bot) to decide; Cursor agents only when Cole escalates.

src/loop-guard.ts

117 lines · 3.1 KB · TypeScript
import {
	activityUrlFor,
	fingerprintFor,
	matchFamiliesOverlap,
	maxAgentsPerHour,
	ownerFor,
	sanitizeForPrompt,
	truncate,
	type FingerprintRecord,
	type RunSnippet,
} from './shared.ts'

export const MATCHING_OPEN_RUN_LIMIT = 8

export type MatchingOpenRun = {
	id: string
	surface: string
	name: string
	kodyId: string | null
	startedAt: string | null
	activityUrl: string | null
	errorMessage: string
}

export type LoopGuardSnapshot = {
	gatheredAt: string
	alreadyEscalatedToKody: boolean
	spawnedThisHour: number
	fingerprintsThisHour: number
	eventsThisHour: number
	capRemaining: number
	lease: {
		holder: string | null
		fingerprint: string | null
		acquiredAt: string | null
	} | null
	matchingOpenRuns: MatchingOpenRun[]
	matchingOpenRunCount: number
	openRunsScanned: number
}

export function emptyLoopGuardSnapshot(): LoopGuardSnapshot {
	return {
		gatheredAt: new Date(0).toISOString(),
		alreadyEscalatedToKody: false,
		spawnedThisHour: 0,
		fingerprintsThisHour: 0,
		eventsThisHour: 0,
		capRemaining: maxAgentsPerHour,
		lease: null,
		matchingOpenRuns: [],
		matchingOpenRunCount: 0,
		openRunsScanned: 0,
	}
}

export function runMatchesRecord(
	run: RunSnippet,
	record: Pick<
		FingerprintRecord,
		'fingerprint' | 'owner' | 'kody_id' | 'error_family' | 'sample_message'
	>,
) {
	if (fingerprintFor(run) === record.fingerprint) return true
	if (
		!matchFamiliesOverlap(
			{
				error_family: run.error_message || 'unknown',
				sample_message: run.error_message,
			},
			record,
		)
	) {
		return false
	}
	if (record.kody_id && run.kody_id === record.kody_id) return true
	return ownerFor(run) === record.owner
}

export function slimMatchingRun(run: RunSnippet): MatchingOpenRun {
	const id = String(run.id || '')
	return {
		id,
		surface: String(run.surface || 'unknown'),
		name: String(run.name || ''),
		kodyId: run.kody_id ? String(run.kody_id) : null,
		startedAt: run.started_at ? String(run.started_at) : null,
		activityUrl: run.activity_url || activityUrlFor(id),
		errorMessage: truncate(run.error_message || '', 160),
	}
}

export function formatLoopGuardForPrompt(snapshot: LoopGuardSnapshot) {
	const runs = snapshot.matchingOpenRuns.map((run) =>
		sanitizeForPrompt(
			`${run.surface} ${run.name || '(unnamed)'} · ${run.id} · ${run.activityUrl || 'no url'} · ${truncate(run.errorMessage, 120)}`,
		),
	)
	const runLines = runs.length
		? runs.map((line) => `  - ${line}`).join('\n')
		: '  - none in the scanned open-error page'

	return [
		`- Gathered at: ${snapshot.gatheredAt}`,
		`- capRemaining: ${snapshot.capRemaining} (${snapshot.spawnedThisHour} spawned this hour)`,
		`- fingerprintsThisHour: ${snapshot.fingerprintsThisHour}`,
		`- eventsThisHour: ${snapshot.eventsThisHour}`,
		`- alreadyEscalatedToKody: ${snapshot.alreadyEscalatedToKody ? 'yes' : 'no'}`,
		`- lease: ${
			snapshot.lease
				? `${snapshot.lease.holder || 'unknown'} holding ${snapshot.lease.fingerprint || 'unknown'}`
				: 'none'
		}`,
		`- Matching open runs: ${snapshot.matchingOpenRunCount} of ${snapshot.openRunsScanned} scanned (showing ${snapshot.matchingOpenRuns.length})`,
		runLines,
	].join('\n')
}