{"record":{"id":"56827d6cae8f0513","repo":"tinyhumansai/openhuman","slug":"tracking-issue-must-be-a-positive-integer","errorCode":null,"errorMessage":"tracking_issue must be a positive integer","messagePattern":"tracking_issue must be a positive integer","errorType":"validation","errorClass":"SpecError","httpStatus":null,"severity":"error","filePath":"scripts/agent-batch/lib.mjs","lineNumber":69,"sourceCode":"    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    );\n  }\n  if (!Array.isArray(spec.agents) || spec.agents.length === 0) {\n    throw new SpecError(\"agents must be a non-empty array\", \"agents\");\n  }\n  if (spec.agents.length > 25) {\n    throw new SpecError(\n      `batch size ${spec.agents.length} exceeds hard cap of 25`,\n      \"agents\",\n    );\n  }\n\n  const seenId = new Set();\n  const seenIssue = new Set();\n  const seenBranch = new Set();\n  for (let i = 0; i < spec.agents.length; i++) {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/agent-batch/lib.mjs#L51-L87","documentation":"The top-level tracking_issue must satisfy Number.isInteger(x) && x > 0, tying the batch to one GitHub issue that tracks overall progress. The check fails for non-numbers, non-integers, zero, and negatives. A JSON string like \"5312\" is intentionally rejected — no string-to-number coercion is done.","triggerScenarios":"\"tracking_issue\": 0, -5, 1.5, \"5312\" (string), or null in the spec passed to validateSpec.","commonSituations":"Hand-writing the JSON and quoting the issue number out of habit; generating the spec from a form/CLI that yields strings; leaving a placeholder 0 while the tracking issue has not been opened yet.","solutions":["Open (or pick) the tracking issue first, then set tracking_issue to its unquoted positive integer, e.g. 5312","Remove quotes around the number in the spec file","If generating specs programmatically, coerce with Number.parseInt and re-check Number.isInteger before serializing"],"exampleFix":"// before\n\"tracking_issue\": \"5312\"\n\n// after\n\"tracking_issue\": 5312","handlingStrategy":"validation","validationCode":"if (!Number.isInteger(spec.tracking_issue) || spec.tracking_issue <= 0) {\n  console.error(\"tracking_issue must be a positive integer\");\n  process.exit(1);\n}","typeGuard":"/** @param {unknown} v */\nfunction isPositiveInt(v) {\n  return typeof v === \"number\" && Number.isInteger(v) && v > 0;\n}","tryCatchPattern":"try {\n  validateSpec(spec);\n} catch (e) {\n  if (e instanceof SpecError && e.path === \"tracking_issue\") {\n    console.error(`open the tracking GitHub issue first, then set the number: ${e.message}`);\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Open the tracking issue before writing the spec so you have the real number","Never quote issue numbers in spec JSON","If generating specs, run Number.parseInt + Number.isInteger checks before serializing"],"tags":["validation","json","spec","agent-batch","github-issues"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}