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/apply-matching-runs.ts

106 lines · 2.8 KB · TypeScript
import { kody } from 'kody:runtime'
import {
	fingerprintFor,
	truncate,
	type FingerprintRecord,
} from './shared.ts'

export type SoftTriage = 'ignored' | 'resolved'

export function softTriageForOutcome(outcome: string | null | undefined): SoftTriage | null {
	if (outcome === 'fixed' || outcome === 'resolved_noise') return 'resolved'
	if (outcome === 'ignored' || outcome === 'loop_detected') return 'ignored'
	return null
}

function snippetFromListedRun(run: {
	id?: string
	surface?: string | null
	name?: string | null
	package_id?: string | null
	kody_id?: string | null
	job_id?: string | null
	error_name?: string | null
	error_message?: string | null
	started_at?: string | null
	metadata?: Record<string, unknown> | null
}) {
	return {
		id: run.id,
		surface: run.surface,
		name: run.name,
		package_id: run.package_id,
		kody_id: run.kody_id,
		job_id: run.job_id,
		error_name: run.error_name,
		error_message: run.error_message,
		started_at: run.started_at,
		metadata: run.metadata ?? null,
	}
}

async function listMatchingOpenRunIds(record: FingerprintRecord) {
	if (record.surface === 'fleet-rate' || record.surface === 'unknown' || record.surface === 'sweep') {
		return []
	}
	const ids: string[] = []
	let cursor: string | undefined
	for (let page = 0; page < 8; page++) {
		const listed = await kody.runList({
			status: 'error',
			error_triage: 'open',
			surface: record.surface as
				| 'execute'
				| 'export'
				| 'subscription'
				| 'app_fetch'
				| 'app_realtime'
				| 'job'
				| 'workflow'
				| 'retriever'
				| 'webhook',
			...(record.package_id ? { package_id: record.package_id } : {}),
			limit: 100,
			...(cursor ? { cursor } : {}),
		})
		const runs = listed.runs || []
		for (const run of runs) {
			if (!run.id) continue
			if (!record.package_id && record.owner && record.owner !== 'ad-hoc') {
				const name = run.name || run.kody_id || ''
				if (name !== record.owner && run.kody_id !== record.owner) continue
			}
			if (fingerprintFor(snippetFromListedRun(run)) === record.fingerprint) {
				ids.push(run.id)
			}
		}
		if (!listed.next_cursor || !runs.length) break
		cursor = listed.next_cursor
	}
	return [...new Set(ids)]
}

/** Soft-triage every open Activity row whose fingerprint matches. Pages until done. */
export async function applyTriageToMatchingOpenRuns(
	record: FingerprintRecord,
	triage: SoftTriage,
	note: string,
) {
	const ids = await listMatchingOpenRunIds(record)
	let updated = 0
	const trimmed = truncate(note, 2000)
	for (let i = 0; i < ids.length; i += 100) {
		const chunk = ids.slice(i, i + 100)
		try {
			const result = await kody.runUpdateBulk({
				run_ids: chunk,
				triage,
				note: trimmed,
			})
			updated += result.updated_count || 0
		} catch {
			// Best-effort; fingerprint status is already recorded.
		}
	}
	return { matched: ids.length, updated }
}