{"record":{"id":"1895ca456ebbf1f0","repo":"pbakaus/impeccable","slug":"concept-seed-grain-must-be-one-of-composition-1895ca","errorCode":null,"errorMessage":"concept-seed: --grain must be one of ${COMPOSITION_GRAINS.join(', ')}","messagePattern":"concept-seed: --grain must be one of (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skill/scripts/concept-seed.mjs","lineNumber":327,"sourceCode":"  if (!Number.isInteger(reroll) || reroll < 0) {\n    throw new Error('concept-seed: --reroll must be a non-negative integer');\n  }\n  if (register !== null && register !== 'safer' && register !== 'bolder') {\n    throw new Error('concept-seed: --register must be safer or bolder');\n  }\n  if (register !== null && reroll < 1) {\n    throw new Error('concept-seed: --register steers a re-roll round; pass --reroll <n> with it');\n  }\n  if (register !== null && scope !== 'direction') {\n    throw new Error('concept-seed: --register applies to direction rounds only');\n  }\n  if (mode !== null && !SEED_MODES.has(mode)) {\n    throw new Error('concept-seed: --mode must be persuade, operate, read, or experience');\n  }\n  // Grain needs no mode: how much of the product is in play is independent of\n  // which register of work it is.\n  if (grain !== null && !COMPOSITION_GRAINS.includes(grain)) {\n    throw new Error(`concept-seed: --grain must be one of ${COMPOSITION_GRAINS.join(', ')}`);\n  }\n  if (platform !== null && !COMPOSITION_PLATFORMS.includes(platform)) {\n    throw new Error(`concept-seed: --platform must be one of ${COMPOSITION_PLATFORMS.join(', ')}`);\n  }\n  if (!Number.isInteger(candidateCount) || candidateCount < 5 || candidateCount > 7) {\n    throw new Error('concept-seed: --candidate-count must be an integer from 5 to 7');\n  }\n  const unit = (salt) => {\n    const h = crypto.createHash('sha256').update(`${scope}:${salt}:${key}`).digest();\n    return h.readUInt32BE(0) / 0xffffffff;\n  };\n  const indexSalt = reroll === 0 ? 'index' : `index:reroll-${reroll}`;\n  const buildIndex = 3 + Math.floor(unit(indexSalt) * (candidateCount - 2)); // 3..candidateCount\n  // Surface scope deals a hand of three grounded structures: one card is not\n  // a choice, and the full ranked list would hand selection back to the\n  // model's taste. The dice pick all three; the primary index leads. The\n  // no-lineup rule stays direction-only, where it was written for worlds.\n  const dealtIndices = [buildIndex];","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/pbakaus/impeccable/blob/d14711ae3d1a1dd62dee61a358d27f107c51ccd0/skill/scripts/concept-seed.mjs#L309-L345","documentation":"Thrown when `grain` is set to a value not in COMPOSITION_GRAINS = [product, flow, view, region]. Grain is optional (default null) and describes how much of the product is in play — it is intentionally independent of mode. The dynamic message interpolates the full allowed list.","triggerScenarios":"Passing 'page' or 'screen' (confusing grain with view); passing 'component', 'section', 'module'; confusing grain with platform (web/ios/android).","commonSituations":"Carrying over vocabulary from another design system; a caller mapping grain from a UI dropdown with different labels.","solutions":["Use one of product, flow, view, region, or omit grain / pass null.","Double-check you are not passing a platform value (web/ios/android) into grain."],"exampleFix":"// before\nawait seedConcepts({ scope: 'surface', grain: 'page' });\n\n// after\nawait seedConcepts({ scope: 'surface', grain: 'view' }); // or product|flow|region","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"import { COMPOSITION_GRAINS, isGrain } from './lib/roll-selection.mjs';\nfunction isValidGrain(v) {\n  return v == null || isGrain(v);\n}","tryCatchPattern":null,"preventionTips":["Use product, flow, view, or region, or omit / pass null.","Do not confuse grain with platform (web/ios/android).","Reuse the exported COMPOSITION_GRAINS / isGrain for validation."],"tags":["validation","concept-seed","cli","enum"],"backgroundTag":null,"analyzedSha":"d14711ae3d1a1dd62dee61a358d27f107c51ccd0","analyzedAt":"2026-08-13T00:52:25.771Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}