can1357/oh-my-pi · error

Draft ${draft.round} has not been reviewed yet. End this tur

Error message

Draft ${draft.round} has not been reviewed yet. End this turn; the review turn arrives next, and you approve there.

What it means

`CompressProtocol.accept()` throws this when the newest draft's round number exceeds the highest round marked reviewed via `markReviewed()`. The protocol deliberately separates the turn that produces a draft from the turn that approves it, so the agent reviews measured size and declared losses before certifying its own work. Self-approval inside the producing turn is rejected.

Source

Thrown at packages/coding-agent/src/compress/protocol.ts:161

			losses: losses.map(loss => ({ content: loss.content, reason: loss.reason })),
		};
		this.#drafts.push(draft);
		this.#approved = false;
		this.#verdict = undefined;
		return draft;
	}

	/**
	 * Accept the newest draft and return it.
	 *
	 * Throws when no draft exists, or when the newest draft has not been shown back
	 * to the agent for a verdict — approval is only meaningful after that review.
	 */
	accept(verdict: string): CompressDraft {
		const draft = this.latest;
		if (!draft) throw new Error("Call rewrite before approve: there is no draft to accept");
		if (draft.round > this.#reviewed) {
			throw new Error(
				`Draft ${draft.round} has not been reviewed yet. End this turn; the review turn arrives next, and you approve there.`,
			);
		}
		this.#approved = true;
		this.#verdict = verdict;
		return draft;
	}

	/** Tool that records a draft. Thin adapter over {@link submit}. */
	rewriteTool(): ToolDefinition {
		return {
			name: "rewrite",
			label: "Rewrite",
			description: rewriteDescription.trim(),
			parameters: rewriteSchema,
			approval: "read",
			strict: true,
			execute: async (_toolCallId, rawParams) => {

View on GitHub (pinned to 9690622007)

Solutions

  1. End the current turn after `rewrite`; the command loop sends a review turn next, and approval happens there
  2. Ensure the driver calls `protocol.markReviewed(draft.round)` after showing the draft back to the agent
  3. Retry the approve call in the following turn once the review message has been delivered

Example fix

// before
const draft = protocol.submit(text, losses);
protocol.accept("ok"); // throws: draft 1 not reviewed
// after
const draft = protocol.submit(text, losses);
// command loop shows metrics + losses back to the agent, then:
protocol.markReviewed(draft.round);
protocol.accept("losses are acceptable");
Defensive patterns

Strategy: try-catch

Validate before calling

const draft = protocol.latest;
if (draft && draft.round > highestReviewed) throw new Error("End the turn; approve in the review turn");

Type guard

function isReviewed(p: CompressProtocol): boolean {
  const d = p.latest;
  return d !== undefined && d.round <= p.reviewedCount;
}

Try / catch

try {
  protocol.accept(verdict);
} catch (err) {
  if (err instanceof Error && err.message.includes("has not been reviewed yet")) {
    // defer approval to the next (review) turn
  } else throw err;
}

Prevention

When it happens

Trigger: Calling `approve` (or `accept`) in the same turn that just called `rewrite`, without the command loop having called `markReviewed(round)` for the new draft first.

Common situations: A model tries to rewrite and approve back-to-back within one turn; a custom driver calls `accept()` immediately after `submit()` without simulating the review turn; a loop forgets to call `markReviewed` after echoing draft metrics back to the agent.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/3f39b17f9d01ee54. Report an issue: GitHub.