{"record":{"id":"bc6daa1c9e6aa703","repo":"affaan-m/ECC","slug":"ecc-project-dir-must-be-an-absolute-path-within-workspace","errorCode":null,"errorMessage":"ECC_PROJECT_DIR must be an absolute path within /workspace.","messagePattern":"ECC_PROJECT_DIR must be an absolute path within /workspace\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"docker/plugin-setup/resolve-project-dir.js","lineNumber":15,"sourceCode":"#!/usr/bin/env node\n\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","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/docker/plugin-setup/resolve-project-dir.js#L1-L33","documentation":"After successfully parsing frontmatter lines, parseMemoryDocument checks that every key in FRONTMATTER_FIELDS was seen at least once (tracked in a Set of already-parsed object keys). If any required field is absent it throws this error listing the missing field names. This guarantees every memory document is normalized with a complete, known shape before body extraction.","triggerScenarios":"Calling parseMemoryDocument / memory / parsed with a document whose frontmatter omits one or more required fields (whatever FRONTMATTER_FIELDS declares, e.g. title or scope). Also occurs when a field is misspelled, commented out, or defined only in the body instead of the frontmatter block.","commonSituations":"Hand-authoring a new memory file and forgetting a required key; renaming a field to a name the schema doesn't recognize; an older document format predating a newly added required FRONTMATTER_FIELDS entry; a template copy where placeholder fields were deleted.","solutions":["Read the error's field list and add each missing key to the document's frontmatter with a valid value.","Check for typos in field names — compare against FRONTMATTER_FIELDS in scripts/lib/memory-vault-format.js.","If migrating old documents, run a one-time script that injects default values for newly required fields.","Recreate the document via the library's save/normalize API so required fields are always emitted."],"exampleFix":"// before\n---\ntitle: handoff note\n---\n\n// after (scope was missing)\n---\ntitle: handoff note\nscope: project\n---","handlingStrategy":"validation","validationCode":"const REQUIRED = ['title', 'scope']; // mirror FRONTMATTER_FIELDS\nfunction frontmatterIsComplete(source) {\n  const m = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---/.exec(source);\n  if (!m) return false;\n  const keys = new Set(m[1].split(/\\r?\\n/).map(l => l.split(':')[0].trim()).filter(Boolean));\n  const missing = REQUIRED.filter(k => !keys.has(k));\n  return missing.length === 0 ? true : missing;\n}","typeGuard":"const hasAllFields = (values, required) => required.every(k => Object.prototype.hasOwnProperty.call(values, k) && values[k] != null);","tryCatchPattern":"try {\n  const doc = parseMemoryDocument(source, sourcePath);\n} catch (err) {\n  const m = err.message.match(/missing fields: (.+)\\./);\n  if (m) console.error(`Add frontmatter keys: ${m[1]}`);\n  else throw err;\n}","preventionTips":["Keep a canonical template containing every FRONTMATTER_FIELDS key and copy it for new documents.","Keep the required-field list and document templates in sync — update templates whenever FRONTMATTER_FIELDS changes.","Validate documents in CI before they are committed to the vault.","Use the library's normalize/save API so required fields are always emitted."],"tags":["frontmatter","schema-validation","missing-field","memory-vault"],"backgroundTag":"schema-validation-failed","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}