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