{"record":{"id":"ae4a6de6f29e0389","repo":"affaan-m/ECC","slug":"unable-to-infer-ecc-repo-root-from-install-state-o","errorCode":null,"errorMessage":"Unable to infer ECC repo root from install-state operations","messagePattern":"Unable to infer ECC repo root from install-state operations","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/auto-update.js","lineNumber":80,"sourceCode":"    if (typeof operation.sourceRelativePath !== 'string' || !operation.sourceRelativePath.trim()) {\n      continue;\n    }\n\n    const relativeParts = operation.sourceRelativePath.split(/[\\\\/]+/).filter(Boolean);\n\n    if (relativeParts.length === 0) {\n      continue;\n    }\n\n    let repoRoot = path.resolve(operation.sourcePath);\n    for (let index = 0; index < relativeParts.length; index += 1) {\n      repoRoot = path.dirname(repoRoot);\n    }\n\n    return repoRoot;\n  }\n\n  throw new Error('Unable to infer ECC repo root from install-state operations');\n}\n\nfunction buildInstallApplyArgs(record) {\n  const state = record.state;\n  const target = state.target.target || record.adapter.target;\n  const request = state.request || {};\n  const args = [];\n\n  if (target) {\n    args.push('--target', target);\n  }\n\n  if (request.profile) {\n    args.push('--profile', request.profile);\n  }\n\n  if (Array.isArray(request.modules) && request.modules.length > 0) {\n    args.push('--modules', request.modules.join(','));","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/auto-update.js#L62-L98","documentation":"The `diff` field is mandatory in the orch-review payload and must be a non-empty string containing a unified diff. This throw fires when `diff` is missing, not a string (e.g. an array of lines), or is empty/whitespace-only. Without a real diff there is nothing for any review dimension to evaluate, so the gate rejects rather than approving an empty review.","triggerScenarios":"Omitting diff entirely ({ changedFiles: [...] }); passing diff as an array of lines; passing diff: '' or diff: '   '; passing a diff produced by `git diff` with --no-patch or when there are no staged changes.","commonSituations":"The migration/commit produced no diff (nothing changed) and the caller still invoked the review gate; caller stored diff as an array and forgot to .join('\\n'); a stale or cached empty diff was reused.","solutions":["Generate the diff from real changes: const diff = execSync('git diff HEAD~1').toString(); and only call orchReview if diff.trim() is non-empty.","If diff is stored as an array of lines, join it: diff: lines.join('\\n').","Skip the review gate entirely when there are no changes rather than passing an empty diff."],"exampleFix":"// before\norchReview({ diff: '', changedFiles: ['a.js'] }); // empty diff\n\n// after\nconst diff = execSync('git diff --cached').toString();\nif (diff.trim()) orchReview({ diff, changedFiles: ['a.js'] });","handlingStrategy":"validation","validationCode":"// Only call the gate when there is a real, non-empty diff.\nconst diff = execSync('git diff --cached').toString();\nif (typeof diff !== 'string' || diff.trim() === '') {\n  console.log('No changes to review — skipping orch-review.');\n} else {\n  orchReview({ diff, changedFiles });\n}","typeGuard":"function hasNonEmptyDiff(p) {\n  return p && typeof p.diff === 'string' && p.diff.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Skip the review gate when the diff is empty rather than passing an empty string.","If you store diff as an array of lines, join with '\\n' before passing.","Generate the diff from a real git command, not a hardcoded constant."],"tags":["validation","diff","workflow","review-gate","git"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}