{"record":{"id":"ad97df5595b8e0c7","repo":"affaan-m/ECC","slug":"outcome-must-be-one-of-success-failure-or-partia","errorCode":null,"errorMessage":"outcome must be one of success, failure, or partial","messagePattern":"outcome must be one of success, failure, or partial","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/skill-evolution/tracker.js","lineNumber":70,"sourceCode":"  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,\n    outcome,\n    failure_reason: input.failure_reason || input.failureReason || null,\n    tokens_used: toNullableNumber(input.tokens_used ?? input.tokensUsed, 'tokens_used'),\n    duration_ms: toNullableNumber(input.duration_ms ?? input.durationMs, 'duration_ms'),","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/skill-evolution/tracker.js#L52-L88","documentation":"Thrown by normalizeExecutionRecord when outcome is not in VALID_OUTCOMES = { success, failure, partial }. Unlike other fields, outcome has no alias and no default; it must be exactly one of the three lowercase strings.","triggerScenarios":"recordSkillRun({ ..., outcome: 'succeeded' }); outcome: 'ok'; outcome: 'SUCCESS' (case-sensitive); outcome omitted (undefined not in set); outcome: 'error'.","commonSituations":"Using a synonym (succeeded, completed, failed, errored); uppercase from a config; forgetting to set outcome in the recording path.","solutions":["Use exactly 'success', 'failure', or 'partial' (lowercase).","Map your internal status vocabulary onto these three before recording.","If outcome is unknown, default to 'partial' rather than omitting."],"exampleFix":"// before\nrecordSkillRun({ ..., outcome: run.ok ? 'succeeded' : 'failed' });\n\n// after\nconst outcome = run.ok ? 'success' : 'failure';\nrecordSkillRun({ ..., outcome });","handlingStrategy":"validation","validationCode":"const VALID_OUTCOMES = new Set(['success','failure','partial']);\nfunction normalizeOutcome(o) {\n  if (!VALID_OUTCOMES.has(o)) throw new TypeError(`outcome '${o}' invalid`);\n  return o;\n}","typeGuard":"function isValidOutcome(o) {\n  return ['success','failure','partial'].includes(o);\n}","tryCatchPattern":"try {\n  recordSkillRun(input);\n} catch (err) {\n  if (/outcome must be one of/.test(err.message)) { input.outcome = 'partial'; recordSkillRun(input); }\n  else throw err;\n}","preventionTips":["Map internal statuses to the three canonical outcomes at the boundary.","Default uncertain results to 'partial'.","Add a unit test asserting every internal status maps to a valid outcome."],"tags":["tracker","enum","validation"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}