{"record":{"id":"07aca2c3a268a2e3","repo":"tinyhumansai/openhuman","slug":"batch-id-must-be-a-kebab-case-slug","errorCode":null,"errorMessage":"batch_id must be a kebab-case slug","messagePattern":"batch_id must be a kebab-case slug","errorType":"validation","errorClass":"SpecError","httpStatus":null,"severity":"error","filePath":"scripts/agent-batch/lib.mjs","lineNumber":54,"sourceCode":"  }\n  return json;\n}\n\n// Validate a parsed spec. Returns the spec on success, throws SpecError on\n// any policy violation. The caller is responsible for printing.\nexport function validateSpec(spec) {\n  if (!spec || typeof spec !== \"object\" || Array.isArray(spec)) {\n    throw new SpecError(\"spec must be a JSON object\");\n  }\n  for (const key of REQUIRED_TOP) {\n    if (!(key in spec))\n      throw new SpecError(`missing required top-level field \"${key}\"`);\n  }\n  if (\n    typeof spec.batch_id !== \"string\" ||\n    !/^[a-z0-9][a-z0-9-]*$/.test(spec.batch_id)\n  ) {\n    throw new SpecError(\"batch_id must be a kebab-case slug\", \"batch_id\");\n  }\n  if (spec.base_repo !== \"tinyhumansai/openhuman\") {\n    throw new SpecError(\n      `base_repo must be \"tinyhumansai/openhuman\" (got \"${spec.base_repo}\")`,\n      \"base_repo\",\n    );\n  }\n  if (spec.base_branch !== \"main\") {\n    throw new SpecError(\n      `base_branch must be \"main\" (got \"${spec.base_branch}\")`,\n      \"base_branch\",\n    );\n  }\n  if (!Number.isInteger(spec.tracking_issue) || spec.tracking_issue <= 0) {\n    throw new SpecError(\n      \"tracking_issue must be a positive integer\",\n      \"tracking_issue\",\n    );","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/agent-batch/lib.mjs#L36-L72","documentation":"Thrown by validateSpec() in scripts/agent-batch/lib.mjs when the top-level batch_id field is present but is not a string matching ^[a-z0-9][a-z0-9-]*$. The slug policy exists because batch_id is used to name tracking artifacts (branches, files, issue titles), so it must be lowercase, start with a letter/digit, and contain only letters, digits, and dashes. SpecError prefixes the message with the JSON path \"batch_id\" via its `path` argument.","triggerScenarios":"Calling validateSpec(spec) (directly or via the agent-batch CLI) with a spec whose batch_id is \"Batch-August\" (uppercase), \"batch_01\" (underscore), \"-august\" or \"august-\" (leading/trailing dash), \"\" (empty), or a non-string like 2026 or null.","commonSituations":"Hand-editing a spec JSON after copying an internal ticket name that is CamelCase or snake_case; generating the spec from a template that inserts a title with spaces; a trailing whitespace or newline pasted into the value.","solutions":["Set batch_id to a lowercase kebab-case slug, e.g. \"batch-august-ci\"","Verify with node: /^[a-z0-9][a-z0-9-]*$/.test(batchId) before running the tool","If the value comes from user input, normalize it first: s.trim().toLowerCase().replace(/[^a-z0-9]+/g, '-')","Check the error's `.path` field (\"batch_id\") to confirm which field was rejected"],"exampleFix":"// before\n{\n  \"batch_id\": \"Batch_August_CI\",\n  ...\n}\n\n// after\n{\n  \"batch_id\": \"batch-august-ci\",\n  ...\n}","handlingStrategy":"validation","validationCode":"const slugOk = (v) => typeof v === \"string\" && /^[a-z0-9][a-z0-9-]*$/.test(v);\nif (!slugOk(spec.batch_id)) {\n  console.error(\"batch_id must be kebab-case\");\n  process.exit(1);\n}","typeGuard":"function isKebabSlug(v) {\n  return typeof v === \"string\" && /^[a-z0-9][a-z0-9-]*$/.test(v);\n}","tryCatchPattern":"import { SpecError, validateSpec } from \"./scripts/agent-batch/lib.mjs\";\ntry {\n  validateSpec(spec);\n} catch (e) {\n  if (e instanceof SpecError) {\n    console.error(`spec invalid at ${e.path ?? \"<root>\"}: ${e.message}`);\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Generate batch_id from the batch title with slugify (lowercase, dashes) rather than typing it","Run validateSpec immediately after loadSpec in your script so errors surface before any git/gh side effects","Keep a known-good spec around and diff new specs against it"],"tags":["validation","json","spec","agent-batch","naming"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}