[content] src/extension.ts (typescript)
	if (suppress) {
		suppressAutoPreview = true;
	}
	currentReplacePreview = undefined;
	currentInsertPreview = undefined;
	replacePreviewProvider?.refresh();
}

// -------------------- Hardcoded single-step actions --------------------
function getHardcodedNextAction(editor: vscode.TextEditor): PlannedAction | undefined {
	const cursor = editor.selection.active;
	const doc = editor.document;
	const lineCount = doc.lineCount;
	const clamp = (n: number, min: number, max: number) => Math.max(min, Math.min(max, n));

	// Step 0: Insert multiline content two lines below the cursor (start of target line)
	if (mockStep === 0) {
		const targetLine = clamp(cursor.line + 2, 0, Math.max(0, lineCount - 1));
		return {
			kind: 'editInsert',
			position: [targetLine, 0],
			text: '/* crowd-pilot: insert start */
line A
line B
/* crowd-pilot: insert end */
'
		};
	}
	// Step 1: Replace a two-line range three and four lines below the cursor
	if (mockStep === 1) {
		const startLine = clamp(cursor.line + 3, 0, Math.max(0, lineCount - 1));
		const endLine = clamp(startLine + 1, 0, Math.max(0, lineCount - 1));
		const endChar = doc.lineAt(endLine).range.end.character;
		const range = {
			start: [startLine, 0] as [number, number],
			end: [endLine, endChar] as [number, number]
		};
		const replacement = [
			'/* crowd-pilot: replacement */',
			'REPLACED LINE 1',
			'REPLACED LINE 2'
		].join('
');
		return { kind: 'editReplace', range, text: replacement };
	}
	// Step 2: Delete a three-line range six to eight lines below the cursor
	if (mockStep === 2) {
		const startLine = clamp(cursor.line + 6, 0, Math.max(0, lineCount - 1));
		const endLine = clamp(startLine + 2, 0, Math.max(0, lineCount - 1));
		const endChar = doc.lineAt(endLine).range.end.character;
		const range = {
			start: [startLine, 0] as [number, number],
			end: [endLine, endChar] as [number, number]
		};
		return { kind: 'editDelete', range };
	}
	return undefined;
}

function advanceMockStep(): void {
	mockStep = (mockStep + 1) % 3;
}

function autoShowNextAction(): void {
	if (suppressAutoPreview) { return; }
	const editor = vscode.window.activeTextEditor;
	if (!editor) { return; }
	const next = getHardcodedNextAction(editor);
	if (next) {
		showPreviewUI([next]);
	} else {
		hidePreviewUI();
	}
}

class ReplacePreviewCodeLensProvider implements vscode.CodeLensProvider {
	private emitter = new vscode.EventEmitter<void>();
	public onDidChangeCodeLenses = this.emitter.event;
	refresh(): void { this.emitter.fire(); }
	provideCodeLenses(document: vscode.TextDocument): vscode.ProviderResult<vscode.CodeLens[]> {
		if (!previewVisible) { return []; }
		const lenses: vscode.CodeLens[] = [];
		// Replace lens
		if (currentReplacePreview && document.uri.toString() === currentReplacePreview.uri.toString()) {
			const startLine = currentReplacePreview.range.start.line;
			const range = new vscode.Range(startLine, 0, startLine, 0);
			const title = currentReplacePreview.text.length > 120
				? currentReplacePreview.text.slice(0, 117).replace(/\s+/g, ' ') + '…'
				: currentReplacePreview.text.replace(/\s+/g, ' ');
			const cmd: vscode.Command = {
				title,
				command: 'crowd-pilot.previewNoop',
				tooltip: 'Replacement preview'
			};
			lenses.push(new vscode.CodeLens(range, cmd));
		}
		// Insert lens
		if (currentInsertPreview && document.uri.toString() === currentInsertPreview.uri.toString()) {
			const range = new vscode.Range(currentInsertPreview.line, 0, currentInsertPreview.line, 0);
			const title = currentInsertPreview.text.length > 120
				? currentInsertPreview.text.slice(0, 117).replace(/\s+/g, ' ') + '…'
				: currentInsertPreview.text.replace(/\s+/g, ' ');
			const cmd: vscode.Command = {
				title,
				command: 'crowd-pilot.previewNoop',
				tooltip: 'Insert preview'
			};
			lenses.push(new vscode.CodeLens(range, cmd));
		}
		return lenses;
	}