Yeachan-Heo/oh-my-codex · error · Error
Cannot advance Autopilot from ralplan to ultragoal with forg
Error message
Cannot advance Autopilot from ralplan to ultragoal with forged handoff evidence (${forged.join('; ')}); durable planning artifacts, sequential Architect and Critic approvals, and a bound execution handoff are required. What it means
The worker pane is live with the right PID but its @omx_team_pane_owner tag doesn't match the expected team incarnation id. The owner tag ties a pane to a specific team-session incarnation; a mismatch means the pane belongs to an older or different team session, and operating on it would cross session boundaries.
Source
Thrown at src/autopilot/completion-gate.ts:216
const gate = objectRecord(rawGate);
const execution = objectRecord(rawExecution);
requireObjectShape(gate.ralplan_architect_review, 'ralplan_architect_review');
requireObjectShape(gate.ralplan_critic_review, 'ralplan_critic_review');
const architect = objectRecord(gate.ralplan_architect_review);
const critic = objectRecord(gate.ralplan_critic_review);
const requireInteger = (value: unknown, label: string): void => {
if (present(value) && exactInteger(value) === null) forged.push(`${label} must be an integer`);
};
requireInteger(architect.sequence_index, 'architect sequence_index');
requireInteger(critic.sequence_index, 'critic sequence_index');
requireInteger(architect.review_cycle ?? architect.iteration, 'architect review_cycle');
requireInteger(critic.review_cycle ?? critic.iteration, 'critic review_cycle');
requireInteger(execution.review_cycle, 'execution review_cycle');
if (present(execution.authorized_at) && !validIsoTimestamp(execution.authorized_at)) {
forged.push('execution authorized_at must be an ISO-8601 timestamp');
}
if (forged.length === 0) return;
throw new Error(
'Cannot advance Autopilot from ralplan to ultragoal with forged handoff evidence '
+ `(${forged.join('; ')}); durable planning artifacts, sequential Architect and Critic `
+ 'approvals, and a bound execution handoff are required.',
);
}
function hasRalplanHandoff(state: JsonObject): boolean {
const handoffs = objectRecord(stateField(state, 'handoff_artifacts'));
const ralplan = objectRecord(handoffs.ralplan);
const gate = objectRecord(stateField(state, 'ralplan_consensus_gate'));
const execution = objectRecord(stateField(state, 'ralplan_execution_handoff'));
const planPath = ralplan.plan_path ?? ralplan.prd_path;
const planExists = existingRepoArtifact(state, planPath, ['plans/']);
const reviews = approvedReview(gate.ralplan_architect_review, 'architect')
&& approvedReview(gate.ralplan_critic_review, 'critic');
const architect = objectRecord(gate.ralplan_architect_review);
const critic = objectRecord(gate.ralplan_critic_review);
const authorized = execution.authorized === true || execution.authorized_by_user === true;View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Recreate the team session so surviving panes are retagged with the new incarnation id
- Explicitly kill leftover panes from prior sessions before creating a new one
- Check `tmux show-option -qv -p -t <pane> @omx_team_pane_owner` against the expected id
- Ensure only one team session manages a given set of panes
Example fix
# inspect the tag vs expected incarnation tmux show-option -qv -p -t %4 @omx_team_pane_owner
Defensive patterns
Strategy: validation
Validate before calling
const owner = execSync(`tmux show-option -qv -p -t ${workerPaneId} @omx_team_pane_owner`).toString().trim(); if (owner !== expectedTeamOwnerId) halt(); Try / catch
catch (err) { if (/worker pane incarnation changed/.test(err.message)) { recreateTeamSession(); } } Prevention
- Kill leftover panes before creating new sessions
- One team session per pane set
- Re-tag surviving panes via library APIs after recreation
When it happens
Trigger: Worker-pane operations after the team session was recreated (new incarnation id) while panes from the old session survived, or after the owner option was cleared/overwritten.
Common situations: Session restore flows that reuse old panes, two team sessions sharing a server, or tmux config that wipes user options on certain events.
Related errors
- ${label} must not be a symlink: ${path}
- Cannot use out-of-scope artifact path; ${evidenceDescription
- Refusing to overwrite existing ${repoRelative(cwd, missionPa
- startup_cleanup_pane_owner_unavailable:${cleanupPane.pane_id
- worker_notify_failed
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/2ba42694d5f3da7d.
Report an issue: GitHub.