{"record":{"id":"48bfa4dd79c5c7ba","repo":"Yeachan-Heo/oh-my-codex","slug":"mission-execution-requires-a-task-runner-use-stat","errorCode":null,"errorMessage":"Mission execution requires a task runner; use status for read-only inspection.","messagePattern":"Mission execution requires a task runner; use status for read-only inspection\\.","errorType":"validation","errorClass":"MissionCommandError","httpStatus":null,"severity":"error","filePath":"src/cli/mission.ts","lineNumber":400,"sourceCode":"      task.status = parsed.markStatus ?? task.status;\n      task.completed_at = now().toISOString();\n      delete task.exit_code;\n      syncSummary(summary, { status: missionStatus(summary.tasks) });\n      await persistSummary(paths.summaryPath, summary);\n      await appendLedger(paths.ledgerPath, { event: \"task_marked\", at: task.completed_at, slug: summary.slug, task_id: task.id, status: task.status });\n      if (parsed.json) stdout(JSON.stringify({ ok: true, summary_path: paths.summaryPath, ledger_path: paths.ledgerPath, summary }, null, 2));\n      else {\n        stdout(`mission task marked ${task.status}: ${summary.slug} ${task.id}`);\n        stdout(`summary: ${paths.summaryPath}`);\n        stdout(`ledger: ${paths.ledgerPath}`);\n      }\n      return;\n    }\n\n    if (parsed.action === \"resume\" || parsed.action === \"rerun\") {\n      const summary = await readSummary(paths.summaryPath);\n      const runTask = options.runTask;\n      if (!runTask) throw new MissionCommandError(\"Mission execution requires a task runner; use status for read-only inspection.\");\n      if (parsed.action === \"rerun\" && !summary.tasks.some((task) => task.id === parsed.taskId)) {\n        throw new MissionCommandError(`No mission task found for --task ${parsed.taskId}.`);\n      }\n\n      summary.input_path = paths.inputPath;\n      summary.dry_run = false;\n      summary.continue_on_error = parsed.continueOnError;\n      summary.codex_args = parsed.codexArgs;\n      summary.status = \"running\";\n      delete summary.completed_at;\n      for (const task of summary.tasks) {\n        if (task.status === \"running\") task.status = \"pending\";\n      }\n      syncSummary(summary, { status: \"running\" });\n      await persistSummary(paths.summaryPath, summary);\n      await appendLedger(paths.ledgerPath, { event: parsed.action === \"resume\" ? \"mission_resumed\" : \"mission_rerun_started\", at: now().toISOString(), slug: summary.slug, summary_path: paths.summaryPath, task_id: parsed.taskId });\n\n      const shouldRun = parsed.action === \"resume\"","sourceCodeStart":382,"sourceCodeEnd":418,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/mission.ts#L382-L418","documentation":"For mission resume/rerun, the command was invoked without a runTask function in options. Execution actions require a caller-supplied task runner; only status is available without one.","triggerScenarios":"Calling missionCommand(['resume', file], {}) or with options.runTask undefined — e.g. embedding the CLI in a host that only wires up read-only inspection.","commonSituations":"Library embedding where the host deliberately omits the runner; refactoring that dropped the runTask option; tests invoking missionCommand without a stub runner.","solutions":["Pass options.runTask: a function that executes a task and returns its exit code","Use mission status when no runner is available","For plan-only validation, use run --dry-run with a runner or the parser directly"],"exampleFix":"// before\nawait missionCommand(['resume', 'mission.md'], { stdout });\n// after\nawait missionCommand(['resume', 'mission.md'], { stdout, runTask: async (task) => spawnRunner(task) });","handlingStrategy":"validation","validationCode":"if ((action === 'resume' || action === 'rerun') && typeof options.runTask !== 'function') {\n  failEarly('no task runner configured');\n}","typeGuard":"const hasRunner = (o: MissionOptions): o is MissionOptions & { runTask: RunTask } =>\n  typeof o.runTask === 'function';","tryCatchPattern":null,"preventionTips":["Wire runTask at application bootstrap","Guard read-only embeds to only expose status"],"tags":["mission","missing-runner","embedding"],"backgroundTag":"missing-dependency-callback","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}