{"record":{"id":"b53a66d582f3d4ba","repo":"affaan-m/ECC","slug":"ecc-project-dir-must-be-a-child-path-within-works","errorCode":null,"errorMessage":"ECC_PROJECT_DIR must be a child path within /workspace.","messagePattern":"ECC_PROJECT_DIR must be a child path within /workspace\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"docker/plugin-setup/resolve-project-dir.js","lineNumber":20,"sourceCode":"\n'use strict';\n\nconst path = require('path');\n\nconst WORKSPACE_ROOT = '/workspace';\n\nfunction resolveProjectDir(candidate) {\n  if (\n    typeof candidate !== 'string'\n    || !path.posix.isAbsolute(candidate)\n    || /[\\0\\r\\n]/.test(candidate)\n  ) {\n    throw new Error('ECC_PROJECT_DIR must be an absolute path within /workspace.');\n  }\n\n  const resolved = path.posix.resolve(candidate);\n  if (resolved === WORKSPACE_ROOT || !resolved.startsWith(`${WORKSPACE_ROOT}/`)) {\n    throw new Error('ECC_PROJECT_DIR must be a child path within /workspace.');\n  }\n  return resolved;\n}\n\nfunction main() {\n  try {\n    process.stdout.write(`${resolveProjectDir(process.argv[2])}\\n`);\n  } catch (error) {\n    process.stderr.write(`Error: ${error.message}\\n`);\n    process.exitCode = 2;\n  }\n}\n\nif (require.main === module) main();\n\nmodule.exports = { resolveProjectDir };\n","sourceCodeStart":2,"sourceCodeEnd":37,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/docker/plugin-setup/resolve-project-dir.js#L2-L37","documentation":"The orch-review workflow is a fail-closed review gate: it validates its args payload before approving anything. This throw fires when args is a string that cannot be parsed as JSON. The workflow accepts either a plain object or a JSON-encoded string, but a malformed string is rejected outright so the gate never silently approves a payload it could not actually inspect.","triggerScenarios":"Calling orchReview(\"{diff: '...'}\") (unquoted keys = invalid JSON); orchReview(\"diff: ...\") (plain text, not JSON); orchReview(\"[broken\") (truncated); shell quoting mangles a stringified payload into invalid JSON.","commonSituations":"Caller hand-builds a JSON string instead of JSON.stringify-ing an object; a shell heredoc or variable expansion breaks the JSON; a templating layer emits JS-object literal syntax instead of JSON.","solutions":["Pass a plain JS object instead of a string: orchReview({ diff, changedFiles }).","If you must pass a string, build it with JSON.stringify(payload) so it is always valid JSON.","Pre-validate the string with JSON.parse in your caller and surface the parse error before invoking the workflow."],"exampleFix":"// before\norchReview('{diff: \"+++\", changedFiles: [\"a.js\"]}'); // invalid JSON keys\n\n// after\norchReview({ diff: '+++', changedFiles: ['a.js'] }); // pass an object","handlingStrategy":"validation","validationCode":"// Pre-validate a string payload before calling the workflow.\nlet payload = args;\nif (typeof payload === 'string') {\n  try { payload = JSON.parse(payload); }\n  catch { throw new Error('args is not valid JSON — pass an object or JSON.stringify first'); }\n}","typeGuard":"// Ensure args is a plain object before invoking the review gate.\nfunction isPlainObject(v) {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}","tryCatchPattern":"try {\n  orchReview(args);\n} catch (e) {\n  if (e.message.startsWith('orch-review: args must be an object or valid JSON')) {\n    // Rebuild the payload as a guaranteed-valid object and retry, or surface to caller.\n  }\n  throw e;\n}","preventionTips":["Always pass a plain JS object, not a hand-built JSON string.","When you must serialize, use JSON.stringify — never template JSON by hand.","Treat any orch-review input error as a caller bug, not a transient failure."],"tags":["validation","json","workflow","review-gate","fail-closed"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}