43 lines
1.3 KiB
TypeScript
43 lines
1.3 KiB
TypeScript
// v2.8 Morph safety guards — prevents catastrophic truncation, marker leakage,
|
|
// and accidental import deletion during native edit_file application.
|
|
// Ported from opencode-morph-fast-apply (MIT) with threshold values preserved.
|
|
|
|
export interface GuardResult {
|
|
ok: boolean;
|
|
reason?: string;
|
|
charLoss?: number;
|
|
lineLoss?: number;
|
|
}
|
|
|
|
const TRUNCATION_CHAR_THRESHOLD = 0.6;
|
|
const TRUNCATION_LINE_THRESHOLD = 0.5;
|
|
|
|
export function validateEditResult(
|
|
original: string,
|
|
updated: string,
|
|
filePath: string,
|
|
): GuardResult {
|
|
// Check for catastrophic content truncation
|
|
if (original.length > 0 && updated.length > 0) {
|
|
const charLoss = 1 - updated.length / original.length;
|
|
const originalLines = original.split('\n').length;
|
|
const updatedLines = updated.split('\n').length;
|
|
const lineLoss = 1 - updatedLines / originalLines;
|
|
|
|
if (charLoss > TRUNCATION_CHAR_THRESHOLD && lineLoss > TRUNCATION_LINE_THRESHOLD) {
|
|
return {
|
|
ok: false,
|
|
reason: `Edit would truncate ${Math.round(charLoss * 100)}% of characters and ${Math.round(lineLoss * 100)}% of lines`,
|
|
charLoss,
|
|
lineLoss,
|
|
};
|
|
}
|
|
}
|
|
|
|
return { ok: true };
|
|
}
|
|
|
|
export function formatGuardError(guard: GuardResult, filePath: string): string {
|
|
return `Edit guard rejected change to ${filePath}: ${guard.reason ?? 'unknown error'}`;
|
|
}
|