{"record":{"id":"25f9907d3e496957","repo":"tinyhumansai/openhuman","slug":"owned-paths-must-be-a-non-empty-array","errorCode":null,"errorMessage":"owned_paths must be a non-empty array","messagePattern":"owned_paths must be a non-empty array","errorType":"validation","errorClass":"SpecError","httpStatus":null,"severity":"error","filePath":"scripts/agent-batch/lib.mjs","lineNumber":140,"sourceCode":"    }\n    if (m[1] !== agent.id) {\n      throw new SpecError(\n        `branch id segment \"${m[1]}\" does not match agent id \"${agent.id}\"`,\n        `${at}.branch`,\n      );\n    }\n    if (Number(m[2]) !== agent.issue) {\n      throw new SpecError(\n        `branch issue segment \"${m[2]}\" does not match agent issue ${agent.issue}`,\n        `${at}.branch`,\n      );\n    }\n    if (seenBranch.has(agent.branch)) {\n      throw new SpecError(`duplicate branch \"${agent.branch}\"`, `${at}.branch`);\n    }\n    seenBranch.add(agent.branch);\n    if (!Array.isArray(agent.owned_paths) || agent.owned_paths.length === 0) {\n      throw new SpecError(\n        \"owned_paths must be a non-empty array\",\n        `${at}.owned_paths`,\n      );\n    }\n    for (let j = 0; j < agent.owned_paths.length; j++) {\n      const p = agent.owned_paths[j];\n      if (typeof p !== \"string\" || p.length === 0) {\n        throw new SpecError(\n          \"must be a non-empty string\",\n          `${at}.owned_paths[${j}]`,\n        );\n      }\n      if (p.includes(\"*\") || p.includes(\"?\")) {\n        throw new SpecError(\n          `globs not allowed — use directory prefixes (got \"${p}\")`,\n          `${at}.owned_paths[${j}]`,\n        );\n      }","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/agent-batch/lib.mjs#L122-L158","documentation":"agent.owned_paths must be a non-empty Array — these are the directory prefixes the agent is allowed to write, and the input to findOverlaps() for disjointness checking downstream. An agent owning nothing is meaningless, so empty arrays (or non-arrays) are rejected before element validation. Path is \"agents[i].owned_paths\".","triggerScenarios":"\"owned_paths\": [], \"owned_paths\": \"src/\", \"owned_paths\": {\"src\": true}, or null on an agent entry.","commonSituations":"Omitting scope decisions until later and leaving an empty list; putting a single string instead of a one-element array; generator defaulting to [] when it could not map the work to paths.","solutions":["List at least one repo-relative directory prefix covering the agent's changes, e.g. [\"scripts/ci/\"]","Wrap single paths in an array: \"src/\" → [\"src/\"]","If unsure of scope, give the owning domain directory (one of src/openhuman/<domain>/)"],"exampleFix":"// before\n\"owned_paths\": []\n\n// after\n\"owned_paths\": [\"scripts/ci/\", \".github/workflows/\"]","handlingStrategy":"validation","validationCode":"for (const [i, a] of spec.agents.entries()) {\n  if (!Array.isArray(a.owned_paths) || a.owned_paths.length === 0) {\n    console.error(`agents[${i}].owned_paths must be a non-empty array`);\n    process.exit(1);\n  }\n}","typeGuard":"/** @param {unknown} v */\nfunction isNonEmptyStringArray(v) {\n  return Array.isArray(v) && v.length > 0 && v.every((p) => typeof p === \"string\" && p.length > 0);\n}","tryCatchPattern":"try {\n  validateSpec(spec);\n} catch (e) {\n  if (e instanceof SpecError && e.path?.endsWith(\".owned_paths\")) {\n    console.error(`scope the agent to at least one directory prefix: ${e.message}`);\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Decide file ownership during slicing, before writing the spec","Own the deepest directory that covers the changes; arrays can hold several prefixes"],"tags":["validation","json","spec","agent-batch","ownership"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}