← run

ts-10-rule-engine

0.000
0/1 tests· architecture

Proposed solution

```ts
export type Rule =
  | { op: "and"; rules: Rule[] }
  | { op: "or"; rules: Rule[] }
  | { op: "not"; rule: Rule }
  | { op: "eq" | "ne" | "lt" | "lte" | "gt" | "gte"; field: string; value: number | string }
  | { op: "in"; field: string; values: Array<number | string> };

export class RuleError extends Error {}

export function evaluate(rule: Rule, record: Record<string, unknown>): boolean;

export function filter(
  rule: Rule,
  records: Array<Record<string, unknown>>,
): Array<Record<string, unknown>>;

function evaluate(rule: Rule, record: Record<string, unknown>): boolean {
  switch (rule.op) {
    case "and":
      return rule.rules.every(evaluate);
    case "or":
      return rule.rules.some(evaluate);
    case "not":
      return !evaluate(rule.rule, record);
    case "eq":
    case "ne":
    case "lt":
    case "lte":
    case "gt":
    case "gte":
      const fieldValue = record[rule.field];
      if (typeof fieldValue !== typeof rule.value) {
        throw new RuleError("Type mismatch for comparison");
      }
      switch (rule.op) {
        case "eq":
          return fieldValue === rule.value;
        case "ne":
          return fieldValue !== rule.value;
        case "lt":
          return fieldValue < rule.value;
        case "lte":
          return fieldValue <= rule.value;
        case "gt":
          return fieldValue > rule.value;
        case "gte":
          return fieldValue >= rule.value;
      }
    default:
      throw new RuleError("Unknown operator");
  }
}

export function filter(
  rule: Rule,
  records: Array<Record<string, unknown>>,
): Array<Record<string, unknown>> {
  const filteredRecords = [];
  for (const record of records) {
    try {
      if (evaluate(rule, record)) {
        filteredRecords.push(record);
      }
    } catch (error) {
      if (error instanceof RuleError) {
        throw error;
      }
    }
  }
  return filteredRecords;
}
```

Test output (stdout)

TAP version 13
# /tmp/llmlab-ts-10-rule-engine-6bky_9dl/solution.test.ts:3
# import { evaluate, filter, RuleError, type Rule } from "./solution.ts";
#          ^
# SyntaxError: The requested module './solution.ts' does not provide an export named 'evaluate'
#     at \#asyncInstantiate (node:internal/modules/esm/module_job:327:21)
#     at async ModuleJob.run (node:internal/modules/esm/module_job:431:5)
#     at async node:internal/modules/esm/loader:633:26
#     at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5)
# Node.js v24.16.0
# Subtest: solution.test.ts
not ok 1 - solution.test.ts
  ---
  duration_ms: 65.729598
  type: 'test'
  location: '/tmp/llmlab-ts-10-rule-engine-6bky_9dl/solution.test.ts:1:1'
  failureType: 'testCodeFailure'
  exitCode: 1
  signal: ~
  error: 'test failed'
  code: 'ERR_TEST_FAILURE'
  ...
1..1
# tests 1
# suites 0
# pass 0
# fail 1
# cancelled 0
# skipped 0
# todo 0
# duration_ms 69.514857
Self-repair attempts
[
  {
    "total": 1,
    "answer": "```ts\nexport type Rule =\n  | { op: \"and\"; rules: Rule[] }\n  | { op: \"or\"; rules: Rule[] }\n  | { op: \"not\"; rule: Rule }\n  | { op: \"eq\" | \"ne\" | \"lt\" | \"lte\" | \"gt\" | \"gte\"; field: string; value: number | string }\n  | { op: \"in\"; field: string; values: Array<number | string> };\n\nexport class RuleError extends Error {}\n\nexport function evaluate(rule: Rule, record: Record<string, unknown>): boolean;\n\nexport function filter(\n  rule: Rule,\n  records: Array<Record<string, unknown>>,\n): Array<Record<string, unknown>>;\n\nfunction evaluate(rule: Rule, record: Record<string, unknown>): boolean {\n  switch (rule.op) {\n    case \"and\":\n      return rule.rules.every(evaluate);\n    case \"or\":\n      return rule.rules.some(evaluate);\n    case \"not\":\n      return !evaluate(rule.rule, record);\n    case \"eq\":\n    case \"ne\":\n    case \"lt\":\n    case \"lte\":\n    case \"gt\":\n    case \"gte\":\n      const fieldValue = record[rule.field];\n      if (typeof fieldValue !== typeof rule.value) {\n        throw new RuleError(\"Type mismatch for comparison\");\n      }\n      switch (rule.op) {\n        case \"eq\":\n          return fieldValue === rule.value;\n        case \"ne\":\n          return fieldValue !== rule.value;\n        case \"lt\":\n          return fieldValue < rule.value;\n        case \"lte\":\n          return fieldValue <= rule.value;\n        case \"gt\":\n          return fieldValue > rule.value;\n        case \"gte\":\n          return fieldValue >= rule.value;\n      }\n    default:\n      throw new RuleError(\"Unknown operator\");\n  }\n}\n\nexport function filter(\n  rule: Rule,\n  records: Array<Record<string, unknown>>,\n): Array<Record<string, unknown>> {\n  const filteredRecords = [];\n  for (const record of records) {\n    try {\n      if (evaluate(rule, record)) {\n        filteredRecords.push(record);\n      }\n    } catch (error) {\n      if (error instanceof RuleError) {\n        throw error;\n      }\n    }\n  }\n  return filteredRecords;\n}\n```",
    "passed": 0,
    "test_error": "TAP version 13\n# /tmp/llmlab-ts-10-rule-engine-6bky_9dl/solution.test.ts:3\n# import { evaluate, filter, RuleError, type Rule } from \"./solution.ts\";\n#          ^\n# SyntaxError: The requested module './solution.ts' does not provide an export named 'evaluate'\n#     at \\#asyncInstantiate (node:internal/modules/esm/module_job:327:21)\n#     at async ModuleJob.run (node:internal/modules/esm/module_job:431:5)\n#     at async node:internal/modules/esm/loader:633:26\n#     at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5)\n# Node.js v24.16.0\n# Subtest: solution.test.ts\nnot ok 1 - solution.test.ts\n  ---\n  duration_ms: 65.729598\n  type: 'test'\n  location: '/tmp/llmlab-ts-10-rule-engine-6bky_9dl/solution.test.ts:1:1'\n  failureType: 'testCodeFailure'\n  exitCode: 1\n  signal: ~\n  error: 'test failed'\n  code: 'ERR_TEST_FAILURE'\n  ...\n1..1\n# tests 1\n# suites 0\n# pass 0\n# fail 1\n# cancelled 0\n# skipped 0\n# todo 0\n# duration_ms 69.514857"
  },
  {
    "total": 1,
    "answer": "```ts\nexport type Rule =\n  | { op: \"and\"; rules: Rule[] }\n  | { op: \"or\"; rules: Rule[] }\n  | { op: \"not\"; rule: Rule }\n  | { op: \"eq\" | \"ne\" | \"lt\" | \"lte\" | \"gt\" | \"gte\"; field: string; value: number | string }\n  | { op: \"in\"; field: string; values: Array<number | string> };\n\nexport class RuleError extends Error {}\n\nexport function evaluate(rule: Rule, record: Record<string, unknown>): boolean;\n\nexport function filter(\n  rule: Rule,\n  records: Array<Record<string, unknown>>,\n): Array<Record<string, unknown>>;\n\nfunction evaluate(rule: Rule, record: Record<string, unknown>): boolean {\n  switch (rule.op) {\n    case \"and\":\n      return rule.rules.every(evaluate);\n    case \"or\":\n      return rule.rules.some(evaluate);\n    case \"not\":\n      return !evaluate(rule.rule, record);\n    case \"eq\":\n    case \"ne\":\n    case \"lt\":\n    case \"lte\":\n    case \"gt\":\n    case \"gte\":\n      const fieldValue = record[rule.field];\n      if (fieldValue === undefined) {\n        throw new RuleError(\"Field not found in record\");\n      }\n      if (typeof fieldValue !== typeof rule.value) {\n        throw new RuleError(\"Type mismatch for comparison\");\n      }\n      switch (rule.op) {\n        case \"eq\":\n          return fieldValue === rule.value;\n        case \"ne\":\n          return fieldValue !== rule.value;\n        case \"lt\":\n          return fieldValue < rule.value;\n        case \"lte\":\n          return fieldValue <= rule.value;\n        case \"gt\":\n          return fieldValue > rule.value;\n        case \"gte\":\n          return fieldValue >= rule.value;\n      }\n    default:\n      throw new RuleError(\"Unknown operator\");\n  }\n}\n\nexport function filter(\n  rule: Rule,\n  records: Array<Record<string, unknown>>,\n): Array<Record<string, unknown>> {\n  const filteredRecords = [];\n  for (const record of records) {\n    try {\n      if (evaluate(rule, record)) {\n        filteredRecords.push(record);\n      }\n    } catch (error) {\n      if (error instanceof RuleError) {\n        throw error;\n      }\n    }\n  }\n  return filteredRecords;\n}\n```",
    "passed": 0,
    "test_error": "TAP version 13\n# /tmp/llmlab-ts-10-rule-engine-ekysley1/solution.test.ts:3\n# import { evaluate, filter, RuleError, type Rule } from \"./solution.ts\";\n#          ^\n# SyntaxError: The requested module './solution.ts' does not provide an export named 'evaluate'\n#     at \\#asyncInstantiate (node:internal/modules/esm/module_job:327:21)\n#     at async ModuleJob.run (node:internal/modules/esm/module_job:431:5)\n#     at async node:internal/modules/esm/loader:633:26\n#     at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5)\n# Node.js v24.16.0\n# Subtest: solution.test.ts\nnot ok 1 - solution.test.ts\n  ---\n  duration_ms: 67.96632\n  type: 'test'\n  location: '/tmp/llmlab-ts-10-rule-engine-ekysley1/solution.test.ts:1:1'\n  failureType: 'testCodeFailure'\n  exitCode: 1\n  signal: ~\n  error: 'test failed'\n  code: 'ERR_TEST_FAILURE'\n  ...\n1..1\n# tests 1\n# suites 0\n# pass 0\n# fail 1\n# cancelled 0\n# skipped 0\n# todo 0\n# duration_ms 71.718157"
  },
  {
    "total": 1,
    "answer": "```ts\nexport type Rule =\n  | { op: \"and\"; rules: Rule[] }\n  | { op: \"or\"; rules: Rule[] }\n  | { op: \"not\"; rule: Rule }\n  | { op: \"eq\" | \"ne\" | \"lt\" | \"lte\" | \"gt\" | \"gte\"; field: string; value: number | string }\n  | { op: \"in\"; field: string; values: Array<number | string> };\n\nexport class RuleError extends Error {}\n\nexport function evaluate(rule: Rule, record: Record<string, unknown>): boolean;\n\nexport function filter(\n  rule: Rule,\n  records: Array<Record<string, unknown>>,\n): Array<Record<string, unknown>>;\n\nfunction evaluate(rule: Rule, record: Record<string, unknown>): boolean {\n  switch (rule.op) {\n    case \"and\":\n      return rule.rules.every(evaluate);\n    case \"or\":\n      return rule.rules.some(evaluate);\n    case \"not\":\n      return !evaluate(rule.rule, record);\n    case \"eq\":\n    case \"ne\":\n    case \"lt\":\n    case \"lte\":\n    case \"gt\":\n    case \"gte\":\n      const fieldValue = record[rule.field];\n      if (fieldValue === undefined) {\n        throw new RuleError(\"Field not found in record\");\n      }\n      if (typeof fieldValue !== typeof rule.value) {\n        throw new RuleError(\"Type mismatch for comparison\");\n      }\n      switch (rule.op) {\n        case \"eq\":\n          return fieldValue === rule.value;\n        case \"ne\":\n          return fieldValue !== rule.value;\n        case \"lt\":\n          return fieldValue < rule.value;\n        case \"lte\":\n          return fieldValue <= rule.value;\n        case \"gt\":\n          return fieldValue > rule.value;\n        case \"gte\":\n          return fieldValue >= rule.value;\n      }\n    default:\n      throw new RuleError(\"Unknown operator\");\n  }\n}\n\nexport function filter(\n  rule: Rule,\n  records: Array<Record<string, unknown>>,\n): Array<Record<string, unknown>> {\n  const filteredRecords = [];\n  for (const record of records) {\n    try {\n      if (evaluate(rule, record)) {\n        filteredRecords.push(record);\n      }\n    } catch (error) {\n      if (error instanceof RuleError) {\n        throw error;\n      }\n    }\n  }\n  return filteredRecords;\n}\n```",
    "passed": 0,
    "test_error": ""
  }
]
System prompt
You are an expert programmer. Solve the task exactly as specified. Output your solution as fenced code blocks using the required file name(s) and the exact function/type signatures requested. Prefer correctness; do not include prose outside code unless asked.