{"record":{"id":"6e9b07e8c6603bbe","repo":"affaan-m/ECC","slug":"task-description-is-required","errorCode":null,"errorMessage":"task_description is required","messagePattern":"task_description is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/skill-evolution/tracker.js","lineNumber":66,"sourceCode":"  }\n\n  const skillId = input.skill_id || input.skillId;\n  const skillVersion = input.skill_version || input.skillVersion;\n  const taskDescription = input.task_description || input.task_attempted || input.taskAttempted;\n  const outcome = input.outcome;\n  const recordedAt = input.recorded_at || options.now || new Date().toISOString();\n  const userFeedback = input.user_feedback || input.userFeedback || null;\n\n  if (typeof skillId !== 'string' || skillId.trim().length === 0) {\n    throw new Error('skill_id is required');\n  }\n\n  if (typeof skillVersion !== 'string' || skillVersion.trim().length === 0) {\n    throw new Error('skill_version is required');\n  }\n\n  if (typeof taskDescription !== 'string' || taskDescription.trim().length === 0) {\n    throw new Error('task_description is required');\n  }\n\n  if (!VALID_OUTCOMES.has(outcome)) {\n    throw new Error('outcome must be one of success, failure, or partial');\n  }\n\n  if (userFeedback !== null && !VALID_FEEDBACK.has(userFeedback)) {\n    throw new Error('user_feedback must be accepted, corrected, rejected, or null');\n  }\n\n  if (Number.isNaN(Date.parse(recordedAt))) {\n    throw new Error('recorded_at must be an ISO timestamp');\n  }\n\n  return {\n    skill_id: skillId,\n    skill_version: skillVersion,\n    task_description: taskDescription,","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/skill-evolution/tracker.js#L48-L84","documentation":"Thrown by normalizeExecutionRecord when task_description is missing. The field accepts three aliases in priority order: task_description, task_attempted, taskAttempted. All must resolve to a non-empty trimmed string.","triggerScenarios":"recordSkillRun({ skill_id, skill_version, outcome }) with none of task_description/task_attempted/taskAttempted; all aliases empty/whitespace.","commonSituations":"Recording a run without capturing what was attempted; using yet another alias name (e.g. task) that the normalizer does not recognize; empty task string from a UI.","solutions":["Provide task_description (or task_attempted / taskAttempted) as a non-empty string.","Capture the user's prompt or a summary before invoking recordSkillRun.","If the task is genuinely empty, require a placeholder description rather than skipping."],"exampleFix":"// before\nrecordSkillRun({ skill_id, skill_version, outcome: 'success' });\n\n// after\nrecordSkillRun({ skill_id, skill_version, task_description: prompt || '(no description)', outcome: 'success' });","handlingStrategy":"validation","validationCode":"function resolveTask(input) {\n  const t = input.task_description || input.task_attempted || input.taskAttempted;\n  if (typeof t !== 'string' || t.trim().length === 0) {\n    throw new TypeError('task_description missing');\n  }\n  return t;\n}","typeGuard":"function hasTaskDescription(input) {\n  const t = input?.task_description || input?.task_attempted || input?.taskAttempted;\n  return typeof t === 'string' && t.trim().length > 0;\n}","tryCatchPattern":"try {\n  recordSkillRun(input);\n} catch (err) {\n  if (/task_description is required/.test(err.message)) { input.task_description = '(untitled)'; recordSkillRun(input); }\n  else throw err;\n}","preventionTips":["Capture the user's prompt or a summary at invocation time.","Disallow empty descriptions in the recording UI.","Reuse the same alias consistently (task_description preferred)."],"tags":["tracker","required-field","validation"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}