{"record":{"id":"0117cc99472fc7db","repo":"Yeachan-Heo/oh-my-codex","slug":"sandbox-md-frontmatter-evaluator-keep-policy-must","errorCode":null,"errorMessage":"sandbox.md frontmatter evaluator.keep_policy must be a string when provided.","messagePattern":"sandbox\\.md frontmatter evaluator\\.keep_policy must be a string when provided\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/autoresearch/contracts.ts","lineNumber":138,"sourceCode":"      const section = result[currentSection];\n      if (!section || typeof section !== 'object' || Array.isArray(section)) {\n        throw contractError(`Invalid sandbox.md frontmatter section: ${currentSection}`);\n      }\n      (section as Record<string, unknown>)[key] = value;\n      continue;\n    }\n\n    result[key] = value;\n    currentSection = null;\n  }\n\n  return result;\n}\n\nfunction parseKeepPolicy(raw: unknown): AutoresearchKeepPolicy | undefined {\n  if (raw === undefined) return undefined;\n  if (typeof raw !== 'string') {\n    throw contractError('sandbox.md frontmatter evaluator.keep_policy must be a string when provided.');\n  }\n  const normalized = raw.trim().toLowerCase();\n  if (!normalized) return undefined;\n  if (normalized === 'pass_only') return 'pass_only';\n  if (normalized === 'score_improvement') return 'score_improvement';\n  throw contractError('sandbox.md frontmatter evaluator.keep_policy must be one of: score_improvement, pass_only.');\n}\n\nexport function parseSandboxContract(content: string): ParsedSandboxContract {\n  const { frontmatter, body } = extractFrontmatter(content);\n  const parsedFrontmatter = parseSimpleYamlFrontmatter(frontmatter);\n  const evaluatorRaw = parsedFrontmatter.evaluator;\n\n  if (!evaluatorRaw || typeof evaluatorRaw !== 'object' || Array.isArray(evaluatorRaw)) {\n    throw contractError(EVALUATOR_BLOCK_ERROR);\n  }\n\n  const evaluator = evaluatorRaw as { command?: unknown; format?: unknown; keep_policy?: unknown };","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/autoresearch/contracts.ts#L120-L156","documentation":"parseKeepPolicy throws when sandbox.md frontmatter defines evaluator.keep_policy but its value is not a string (e.g. a number, boolean, or nested map). The parser only accepts a string (or omission/empty, which means undefined).","triggerScenarios":"Frontmatter containing 'keep_policy: 2', 'keep_policy: true', or an indented block under keep_policy; parseSandboxContract passes evaluator.keep_policy into parseKeepPolicy and the typeof check fails.","commonSituations":"Quoting mistakes that still parse to non-strings in this simple parser, YAML booleans/numbers written without quotes where a policy name was intended, or copy-pasting a structured policy object.","solutions":["Set keep_policy to one of the quoted or unquoted string values: score_improvement or pass_only, e.g. 'keep_policy: pass_only'.","Remove the key entirely if you want the default policy.","Ensure it is a single scalar line, not an indented block."],"exampleFix":"# before\nevaluator:\n  keep_policy:\n    policy: pass_only\n\n# after\nevaluator:\n  keep_policy: pass_only","handlingStrategy":"type-guard","validationCode":"import { parseSandboxContract } from './contracts'; // parse first; keep_policy type errors surface here\n\n// or pre-check the raw YAML value yourself before parsing:\nfunction keepPolicyIsString(raw: unknown): boolean {\n  return raw === undefined || typeof raw === 'string';\n}","typeGuard":"const isKeepPolicyShaped = (raw: unknown): boolean =>\n  raw === undefined || (typeof raw === 'string' && (['', 'pass_only', 'score_improvement'].includes(raw.trim().toLowerCase())));","tryCatchPattern":"try {\n  parseSandboxContract(content);\n} catch (err) {\n  if ((err as Error).message.includes('keep_policy must be a string')) {\n    // replace structured keep_policy with a scalar 'pass_only'/'score_improvement' or remove it\n  }\n  throw err;\n}","preventionTips":["Write keep_policy as a single scalar line.","Never use an indented block or number/boolean for keep_policy."],"tags":["yaml","frontmatter","keep-policy","sandbox-md"],"backgroundTag":"invalid-config-value-type","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}