{"record":{"id":"c7d43e15c014e000","repo":"paperclipai/paperclip","slug":"runner-live-rotation-requires-a-valid-generated-at","errorCode":null,"errorMessage":"Runner live rotation requires a valid generated-at time","messagePattern":"Runner live rotation requires a valid generated-at time","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/eval/live-workflow-matrix.ts","lineNumber":30,"sourceCode":"export const RUNNER_LIVE_SCHEDULE_SCHEMA =\n  \"paperclip.runner.live-eval-schedule.v1\" as const;\n\nexport function parseRunnerLiveCampaignCostLimit(\n  value: string | undefined,\n): number {\n  const parsed = Number(value ?? \"12\");\n  if (!Number.isFinite(parsed) || parsed <= 0) {\n    throw new Error(\n      \"PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD must be a positive finite number\",\n    );\n  }\n  return parsed;\n}\n\nexport function runnerLiveRotationWeek(generatedAt: string): number {\n  const epochMs = Date.parse(generatedAt);\n  if (!Number.isFinite(epochMs)) {\n    throw new Error(\"Runner live rotation requires a valid generated-at time\");\n  }\n  const epochWeek = Math.floor(epochMs / (7 * 86_400_000));\n  return ((epochWeek % 7) + 7) % 7;\n}\n\nexport type RunnerLiveAdapter =\n  \"codex_app_server\" | \"opencode_server\" | \"acpx_runtime\";\nexport type RunnerLiveTier = \"strong\" | \"inexpensive\";\n\nexport interface RunnerLiveEvalCandidate {\n  schema: typeof RUNNER_LIVE_CANDIDATE_SCHEMA;\n  id: string;\n  slotId: string;\n  adapter: RunnerLiveAdapter;\n  provider: RunnerWorkflowProvider;\n  model: string;\n  tier: RunnerLiveTier;\n  reasoningEffort?: string;","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/eval/live-workflow-matrix.ts#L12-L48","documentation":"runnerLiveRotationWeek converts a generated-at timestamp into a stable rotation index (0-6) used to pick which live adapter candidates run this week. It requires Date.parse to yield a finite epoch value; an unparseable or missing timestamp string throws this error, since rotation cannot be computed deterministically without a valid instant.","triggerScenarios":"Calling runnerLiveRotationWeek with a string Date.parse cannot parse: an empty string, a non-ISO formatted date, a localized date, 'undefined'/'null' as literal strings, or a truncated timestamp from a hand-edited schedule manifest (RUNNER_LIVE_SCHEDULE_SCHEMA) — called from first/second rotation selection paths.","commonSituations":"Hand-editing a live-eval schedule JSON and mistyping generatedAt; generating the manifest with a non-ISO8601 date format; a template leaving ${generatedAt} unsubstituted; timezone-localized strings that V8's Date.parse rejects in some runtimes.","solutions":["Use a valid ISO 8601 UTC timestamp for generatedAt, e.g. new Date().toISOString() produces '2026-09-02T12:00:00.000Z'.","Regenerate the schedule manifest with the tooling that produces it instead of hand-editing the timestamp field.","Check for unsubstituted template placeholders or empty strings in the manifest's generatedAt field.","If parsing external input, validate with Number.isFinite(Date.parse(v)) before calling and surface the raw value in the failure."],"exampleFix":"// before\nrunnerLiveRotationWeek(\"09/02/2026 12:00 PM\")\n// after\nrunnerLiveRotationWeek(new Date().toISOString()) // \"2026-09-02T12:00:00.000Z\"","handlingStrategy":"validation","validationCode":"function isValidGeneratedAt(v: string): boolean {\n  return typeof v === \"string\" && v.length > 0 && Number.isFinite(Date.parse(v));\n}\n// usage: if (!isValidGeneratedAt(schedule.generatedAt)) throw new Error(`bad generatedAt: ${JSON.stringify(schedule.generatedAt)}`);","typeGuard":"function isParsableDate(v: unknown): v is string {\n  return typeof v === \"string\" && v.trim() !== \"\" && Number.isFinite(Date.parse(v));\n}","tryCatchPattern":"try {\n  const week = runnerLiveRotationWeek(schedule.generatedAt);\n} catch (error) {\n  if (String(error).includes(\"valid generated-at\")) {\n    console.error(`schedule.generatedAt is not a parseable date: ${JSON.stringify(schedule.generatedAt)}; regenerate the manifest`);\n  }\n  throw error;\n}","preventionTips":["Always write generatedAt with new Date().toISOString() (ISO 8601 UTC), never locale-formatted strings.","Regenerate schedule manifests with the producing tooling rather than hand-editing timestamps.","Search manifests for unsubstituted placeholders ('${generatedAt}') or empty strings before running rotation.","Validate schedule JSON against RUNNER_LIVE_SCHEDULE_SCHEMA before passing fields to rotation helpers."],"tags":["validation","date-parsing","eval","configuration"],"backgroundTag":"invalid-timestamp-input","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-02T18:44:00.616Z","contentChangedAt":"2026-09-02T18:44:00.616Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}