{"record":{"id":"bb047328bfb73a9a","repo":"affaan-m/ECC","slug":"skill-id-is-required","errorCode":null,"errorMessage":"skill_id is required","messagePattern":"skill_id is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/skill-evolution/tracker.js","lineNumber":58,"sourceCode":"  }\n\n  return numericValue;\n}\n\nfunction normalizeExecutionRecord(input, options = {}) {\n  if (!input || typeof input !== 'object' || Array.isArray(input)) {\n    throw new Error('skill execution payload must be an object');\n  }\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","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/skill-evolution/tracker.js#L40-L76","documentation":"normalizeExecutionRecord() requires every execution record to identify which skill ran. skill_id is read from input.skill_id or input.skillId (camelCase accepted); if it is missing, not a string, or an empty/whitespace-only string, the function throws 'skill_id is required'. skill_id is the primary key for correlating executions with a skill, so it cannot be defaulted.","triggerScenarios":"record({ skill_version: '1.0.0', task_description: 'x', outcome: 'success' }) with no skill_id/skillId key; passing skill_id: '' or skill_id: '   '; passing a non-string like skill_id: 42.","commonSituations":"Renaming the field in your telemetry pipeline to 'skill' or 'name' so skill_id is never set; building payloads programmatically and forgetting the id; trimming user input that was empty; using snake_case/camelCase inconsistently when both are undefined.","solutions":["Add a non-empty skill_id string to the payload: record({ skill_id: 'my-skill', ... }).","If your field is named differently (e.g. 'name'), rename it to skill_id (or skillId) before calling.","Trim and validate the value upstream; reject empty strings before they reach the tracker.","Coerce numeric IDs to strings (String(id)) if your source stores them as numbers."],"exampleFix":"// before\nrecord({ skill_version: '1.2.0', task_description: 'lint repo', outcome: 'success' });\n\n// after\nrecord({ skill_id: 'lint-repo', skill_version: '1.2.0', task_description: 'lint repo', outcome: 'success' });","handlingStrategy":"validation","validationCode":"function assertSkillId(payload) {\n  const id = payload?.skill_id ?? payload?.skillId;\n  if (typeof id !== 'string' || id.trim().length === 0) {\n    throw new TypeError('execution payload missing non-empty skill_id');\n  }\n  return id.trim();\n}","typeGuard":"function hasSkillId(input) {\n  const id = input?.skill_id ?? input?.skillId;\n  return typeof id === 'string' && id.trim().length > 0;\n}","tryCatchPattern":"try {\n  tracker.record(payload);\n} catch (err) {\n  if (err.message === 'skill_id is required') {\n    console.error('Execution payload missing skill_id:', JSON.stringify(Object.keys(payload)));\n    return;\n  }\n  throw err;\n}","preventionTips":["Standardize on one key name (skill_id) across your telemetry pipeline.","Validate payload keys with a schema (zod/ajv) before calling record().","Derive skill_id from the skill manifest at call time instead of hand-typing payloads."],"tags":["skill-evolution","validation","required-field"],"backgroundTag":"missing-required-argument","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"}