/** AUTO-GENERATED by scripts/gen-repair-oracle.ts — DO NOT EDIT. */
export interface RepairOracleEntry {
  id: string;
  classKeyPattern: string;
  category: 'mechanical' | 'semantic';
  route: 'impl' | 'ir';
  hint: string;
}

export const REPAIR_ORACLE: RepairOracleEntry[] = [
  {
    "id": "undefined-symbol-jest",
    "classKeyPattern": "^undefined-symbol\\|jest$",
    "category": "mechanical",
    "route": "ir",
    "hint": "undefined-symbol|jest mechanical fix (0 tok, never model): 1) harness provides jest as an alias of vi — prefer that 2) or rewrite jest. → vi. in the suite (accept iff re-parse + no other diffs) 3) do not ask the model to invent a jest shim"
  },
  {
    "id": "undefined-symbol-fn",
    "classKeyPattern": "^undefined-symbol\\|fn$",
    "category": "mechanical",
    "route": "ir",
    "hint": "undefined-symbol|fn mechanical fix (0 tok, never model): 1) harness binds bare fn → vi.fn 2) or rewrite fn( → vi.fn( in the suite when safe 3) do not ask the model to invent a mock shim"
  },
  {
    "id": "is-not-a-function-spyOn",
    "classKeyPattern": "^is-not-a-function\\|spyOn$",
    "category": "mechanical",
    "route": "ir",
    "hint": "is-not-a-function|spyOn mechanical fix (0 tok, never model): 1) harness binds spyOn → vi.spyOn 2) or rewrite spyOn( → vi.spyOn( in the suite when safe 3) do not ask the model to invent a spy shim"
  },
  {
    "id": "undefined-symbol",
    "classKeyPattern": "^undefined-symbol\\|",
    "category": "mechanical",
    "route": "impl",
    "hint": "undefined-symbol playbook (apply in order): 1) check export/import wiring — is the symbol exported from the owning module and imported by the caller? 2) verify signature arity and name spelling against the stub 3) add null-guards only if the contract allows undefined inputs 4) implement the missing export if the stub declares it but the body was omitted"
  },
  {
    "id": "is-not-a-function",
    "classKeyPattern": "^is-not-a-function\\|",
    "category": "semantic",
    "route": "impl",
    "hint": "is-not-a-function playbook (apply in order): 1) confirm the binding is a function export (not a value/object) matching the stub 2) check import { name } vs default/namespace mismatch 3) verify call arity and that the callee is not shadowed by a non-function 4) restore the function export if it was replaced by a constant"
  },
  {
    "id": "empty-draw",
    "classKeyPattern": "^empty-draw$",
    "category": "mechanical",
    "route": "ir",
    "hint": "empty-draw mechanical path (0 tok, never count as attempt): 1) model returned an empty body — classify as empty-draw, not unparseable 2) route method-anchor cases to the clade template (registerUser/createArticle/…) 3) drop messaging says N empty draws — do not burn attempt budget"
  },
  {
    "id": "nullread",
    "classKeyPattern": "^runtime\\|nullread\\|",
    "category": "semantic",
    "route": "impl",
    "hint": "nullread playbook (apply in order): 1) identify which receiver is null/undefined at the property access 2) add a guard or early return matching the frozen contract 3) ensure upstream builders initialize the object before use 4) do not weaken tests — make the implementation satisfy them"
  },
  {
    "id": "assertion-toBe",
    "classKeyPattern": "^assertion\\|toBe$",
    "category": "semantic",
    "route": "impl",
    "hint": "assertion|toBe value-shape playbook (apply in order): 1) compare actual vs expected primitives from the failure message 2) check type coercion (string vs number), Object.is edge cases (-0, NaN) 3) align return shape with the stub contract and frozen expect().toBe 4) prefer fixing implementation; do not weaken the frozen expected value"
  },
  {
    "id": "assertion-toHaveProperty",
    "classKeyPattern": "^assertion\\|toHaveProperty$",
    "category": "semantic",
    "route": "impl",
    "hint": "assertion|toHaveProperty playbook (apply in order): 1) confirm the object is non-null and the path exists on the return value 2) check nested path segments and optional value equality when asserted 3) align the returned object shape with the stub / frozen suite 4) prefer fixing implementation builders over deleting properties in tests"
  },
  {
    "id": "assertion",
    "classKeyPattern": "^assertion\\|",
    "category": "semantic",
    "route": "impl",
    "hint": "assertion playbook (apply in order): 1) compare actual vs expected from the failure message 2) check operator direction, off-by-one, and type coercion 3) align return shape with the stub and frozen expect() 4) prefer fixing implementation; IR surgery only after persistent multi-pass failure"
  },
  {
    "id": "regex-literal",
    "classKeyPattern": "^regex-literal\\|",
    "category": "mechanical",
    "route": "impl",
    "hint": "regex-literal playbook (apply in order): 1) locate the Invalid regular expression site (attributed file) 2) close unterminated /…/ literals and escape intentional slashes 3) prefer mechanical close-slash when the line has an odd unescaped / count 4) if the offender is the suite, route to IR-side case surgery"
  },
  {
    "id": "throw-mismatch",
    "classKeyPattern": "^throw-mismatch\\|",
    "category": "semantic",
    "route": "impl",
    "hint": "throw-mismatch playbook (apply in order): 1) read whether the test expects throw vs not.toThrow 2) check impl validation branch vs case expectation (throw on the named edge) 3) match error TYPE vs message only when the frozen suite asserts them 4) check stub contract — do not swallow errors the suite requires"
  },
  {
    "id": "runtime-generic",
    "classKeyPattern": "^runtime\\|(?!nullread\\|).+",
    "category": "semantic",
    "route": "impl",
    "hint": "runtime playbook (apply in order): 1) read the thrown message class first (TypeError/RangeError/custom) 2) locate the throw site from the attributed file / stack 3) satisfy the frozen contract with a guard or correct branch — do not catch-and-swallow 4) if the suite synthesizes code at runtime, route to IR-case surgery (dynamic-eval lint)"
  },
  {
    "id": "undefined-symbol-fn",
    "classKeyPattern": "^undefined-symbol\\|fn$",
    "category": "mechanical",
    "route": "ir",
    "hint": "undefined-symbol|fn mechanical fix (0 tok, never model): 1) harness binds bare fn to vi.fn 2) or rewrite fn( → vi.fn( in the suite when safe 3) do not ask the model to invent a jest/fn shim"
  },
  {
    "id": "is-not-a-function-spyOn",
    "classKeyPattern": "^is-not-a-function\\|spyOn$",
    "category": "mechanical",
    "route": "ir",
    "hint": "is-not-a-function|spyOn mechanical fix (0 tok, never model): 1) harness binds spyOn to vi.spyOn 2) or rewrite spyOn( → vi.spyOn( in the suite when safe 3) do not ask the model to invent a spyOn shim"
  },
  {
    "id": "empty-draw",
    "classKeyPattern": "^empty-draw$",
    "category": "mechanical",
    "route": "ir",
    "hint": "empty-draw playbook (0 tok, never count as attempt): 1) model returned an empty body — route to method-anchor / clade template 2) do not spend a repair draw on nothing 3) drop messaging says N empty draws, not N attempts"
  },
  {
    "id": "dynamic-eval-impl",
    "classKeyPattern": "^dynamic-eval\\|",
    "category": "semantic",
    "route": "impl",
    "hint": "dynamic-eval playbook (apply in order): 1) replace eval / new Function / dynamic new RegExp with direct logic 2) prefer literal RegExp / static parsers matching the frozen contract 3) never synthesize code at runtime in this artifact class"
  }
];

/** Match a classified classKey to the first oracle entry, or null. */
export function lookupRepairOracle(classKey: string | undefined | null): RepairOracleEntry | null {
  if (!classKey) return null;
  for (const e of REPAIR_ORACLE) {
    if (new RegExp(e.classKeyPattern).test(classKey)) return e;
  }
  return null;
}

/**
 * SET 16d/39 — hint text for repair/permutation prompts.
 * Unknown classes → catalog-drift (no-handler wording kept for legacy matchers).
 */
export function formatRepairOracleHint(classKey: string | undefined | null): string {
  const e = lookupRepairOracle(classKey);
  if (!e) {
    return 'Repair oracle: catalog-drift (no-handler) — no enumerated strategy for this classKey; enumerate candidates bounded by the frozen contract.';
  }
  return `Repair oracle [${e.id} | ${e.category}/${e.route}]: ${e.hint}`;
}
