← 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 · TypeScriptimport {
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')
}