Yeachan-Heo/oh-my-codex · error · UltragoalError
Final code-review must use an independent architect subagent
Error message
Final code-review must use an independent architect subagent; self-review or default/authoring-lane review cannot approve the ultragoal gate.
What it means
During final ultragoal quality-gate validation, the codeReview.independentReview.architect evidence exists but its agentRole is not 'architect'. The gate requires that the final code review be performed by an independent architect subagent; a self-review or a review performed by the default/authoring lane cannot approve the ultragoal gate.
Source
Thrown at src/ultragoal/artifacts.ts:1744
assertNonEmpty(review.evidence, 'codeReview.evidence');
const independentReview = (review as Partial<UltragoalQualityGate['codeReview']>).independentReview;
if (!independentReview || typeof independentReview !== 'object') {
throw new UltragoalError('Final code-review independent review unavailable: codeReview.independentReview must include completed code-reviewer and architect subagent evidence; use record-review-blockers instead of self-approving.');
}
const codeReviewer = independentReview.codeReviewer;
if (!codeReviewer || typeof codeReviewer !== 'object') {
throw new UltragoalError('Final code-review independent review unavailable: missing codeReview.independentReview.codeReviewer evidence from the code-reviewer subagent.');
}
if (codeReviewer.agentRole !== 'code-reviewer') {
throw new UltragoalError('Final code-review must use an independent code-reviewer subagent; self-review or default/authoring-lane review cannot approve the ultragoal gate.');
}
assertNonEmpty(codeReviewer.evidence, 'codeReview.independentReview.codeReviewer.evidence');
const architect = independentReview.architect;
if (!architect || typeof architect !== 'object') {
throw new UltragoalError('Final code-review independent review unavailable: missing codeReview.independentReview.architect evidence from the architect subagent.');
}
if (architect.agentRole !== 'architect') {
throw new UltragoalError('Final code-review must use an independent architect subagent; self-review or default/authoring-lane review cannot approve the ultragoal gate.');
}
assertNonEmpty(architect.evidence, 'codeReview.independentReview.architect.evidence');
validateArchitectureInvariantGate(gate, requiredInvariants);
return gate as UltragoalQualityGate;
}
export async function startNextUltragoal(cwd: string, options: StartNextOptions = {}): Promise<{ plan: UltragoalPlan; goal: UltragoalItem | null; resumed: boolean; done: boolean }> {
return withUltragoalMutationLock(cwd, async () => {
const plan = await readUltragoalPlanUnderLock(cwd);
const now = iso(options.now);
if (plan.aggregateCompletion?.status === 'complete') return { plan, goal: null, resumed: false, done: true };
const existing = plan.goals.find((goal) => goal.status === 'in_progress' && isScheduleEligibleGoal(goal));
if (existing) {
await appendLedger(cwd, { ts: now, event: 'goal_resumed', goalId: existing.id, status: existing.status, message: 'Resuming active ultragoal' });
return { plan, goal: existing, resumed: true, done: false };
}
let next = plan.goals.find((goal) => goal.status === 'pending' && isScheduleEligible(goal));View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Re-run the final code review using an independent architect subagent and set independentReview.architect.agentRole to exactly 'architect' with non-empty evidence
- Check the quality-gate JSON producer: ensure it records the architect subagent's role, not the authoring agent's role
- Verify codeReviewer evidence and other required gate sections are also non-empty before resubmitting
Example fix
// before
"independentReview": { "codeReviewer": {"agentRole": "general", "evidence": ["..."]}, "architect": {"agentRole": "general", "evidence": ["reviewed diff"]} }
// after
"independentReview": { "codeReviewer": {"agentRole": "code-reviewer", "evidence": ["..."]}, "architect": {"agentRole": "architect", "evidence": ["architect subagent review notes"]} } Defensive patterns
Strategy: validation
Validate before calling
const ok = gate?.codeReview?.independentReview?.architect?.agentRole === 'architect'
&& (gate.codeReview.independentReview.architect.evidence ?? []).length > 0;
if (!ok) throw new Error('quality gate lacks independent architect review'); Type guard
const isArchitectReview = (g: unknown): g is { agentRole: 'architect'; evidence: string[] } =>
typeof g === 'object' && g !== null && (g as any).agentRole === 'architect' && Array.isArray((g as any).evidence); Try / catch
catch (e) { if (e instanceof UltragoalError && /independent architect subagent/.test(e.message)) { rerunReviewWithArchitectSubagent(); } else throw e; } Prevention
- Always spawn a dedicated architect subagent for final code review
- Validate the quality-gate JSON against its schema before submitting completion
When it happens
Trigger: Calling checkpointUltragoal/completion with --quality-gate-json whose codeReview.independentReview.architect object is present but has agentRole !== 'architect' (e.g. 'default', 'coder', 'authoring-lane', or missing role) while the goal is a final gate candidate under strict mode.
Common situations: Teams wiring up the quality gate JSON by hand or via a script that fills in the reviewing agent's own role; pipelines where the architect subagent wasn't spawned and someone pasted reviewer evidence from the main agent; schema changes to the gate format that renamed agentRole.
Related errors
- Refusing to derive ${parentItems.length} implicit ultragoal
- Missing ${label}.
- Final quality gate is missing architectureInvariantGate evid
- Final architecture-invariant gate requires architectureInvar
- Final architecture-invariant gate requires architectureInvar
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/ad5a99af443cbdfa.
Report an issue: GitHub.