{"record":{"id":"bf04c94b1aaa4d2f","repo":"ruvnet/ruflo","slug":"bootstrap-iterations-must-be-100","errorCode":null,"errorMessage":"bootstrap iterations must be >= 100","messagePattern":"bootstrap iterations must be >= 100","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/services/flywheel-receipt.ts","lineNumber":263,"sourceCode":"    else return values[k];\n  }\n  return values[k] ?? 0;\n}\n\nexport function computePromotionStatistics(input: {\n  baselineScore: number;\n  candidateScore: number;\n  heldOutDeltas: number[];\n  frozenAnchorRegression: number;\n  corpusHash: string;\n  candidateId: string;\n  baselineRef: string;\n  evaluationRunId: string;\n  iterations?: number;\n  metricEpsilon?: number;\n}): PromotionStatistics {\n  const iterations = input.iterations ?? 10_000;\n  if (!Number.isInteger(iterations) || iterations < 100) throw new Error('bootstrap iterations must be >= 100');\n  const n = input.heldOutDeltas.length;\n  const metricEpsilon = input.metricEpsilon ?? 1e-12;\n  const relativeLift = (input.candidateScore - input.baselineScore) / Math.max(Math.abs(input.baselineScore), metricEpsilon);\n  const seeded = seedFrom([\n    'ruflo/bootstrap/v1',\n    input.corpusHash,\n    input.candidateId,\n    input.baselineRef,\n    input.evaluationRunId,\n  ]);\n  let state = seeded.seed >>> 0;\n  const rnd = () => {\n    state = (1664525 * state + 1013904223) >>> 0;\n    return state / 4294967296;\n  };\n  const means = new Array<number>(iterations);\n  let positiveMeans = 0;\n  if (n === 0) {","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/services/flywheel-receipt.ts#L245-L281","documentation":"Thrown by computePromotionStatistics() when the bootstrap iteration count is not an integer or is below 100. The paired bootstrap resamples heldOutDeltas `iterations` times to estimate the probability that the candidate beats baseline; fewer than 100 samples produces statistically meaningless quantiles. Default is 10,000.","triggerScenarios":"Calling createFlywheelReceipt({ bootstrapIterations: 50 }) or computePromotionStatistics({ iterations: 50 }), or passing a non-integer like 1000.5. The value flows from CreateReceiptInput.bootstrapIterations.","commonSituations":"A test/debug override set too low to speed up runs; a config typo; a fractional value from a division-based default.","solutions":["Omit bootstrapIterations entirely to use the 10,000 default.","Pass an integer >= 100 (e.g. 1000 for faster tests, 10000 for production).","Validate the value with Number.isInteger(x) && x >= 100 before passing."],"exampleFix":"// before\ncreateFlywheelReceipt({ /* ... */, bootstrapIterations: 50 });\n// after\ncreateFlywheelReceipt({ /* ... */, bootstrapIterations: 1000 }); // or omit for default 10000","handlingStrategy":"validation","validationCode":"const iterations = input.bootstrapIterations ?? 10_000;\nif (!Number.isInteger(iterations) || iterations < 100) {\n  throw new Error(`bootstrapIterations must be an integer >= 100, got ${iterations}`);\n}","typeGuard":"const isValidIterationCount = (x: unknown): x is number => typeof x === 'number' && Number.isInteger(x) && x >= 100;","tryCatchPattern":null,"preventionTips":["Omit bootstrapIterations in production to use the 10,000 default.","For faster test runs use 1000, never below 100.","Validate config values at load time rather than at receipt creation."],"tags":["validation","statistics","bootstrap","receipt"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}