diff --git a/gui/pr-assets/storage-log-guard-ux.png b/gui/pr-assets/storage-log-guard-ux.png
new file mode 100644
index 0000000000..c95154ed45
Binary files /dev/null and b/gui/pr-assets/storage-log-guard-ux.png differ
diff --git a/gui/src/components/storage-workspace/StorageWorkspace.tsx b/gui/src/components/storage-workspace/StorageWorkspace.tsx
index fb5ed7808d..bfeb98ea77 100644
--- a/gui/src/components/storage-workspace/StorageWorkspace.tsx
+++ b/gui/src/components/storage-workspace/StorageWorkspace.tsx
@@ -72,6 +72,11 @@ export interface CodexLogGuardReport {
freelistPages: number;
reclaimableBytes: number;
estimatedLogBytes: number | null;
+ writePoster?: {
+ off: { keepRowsShare: number; keepBytesShare: number | null };
+ compat: { keepRowsShare: number; keepBytesShare: number | null };
+ quiet: { keepRowsShare: number; keepBytesShare: number | null };
+ };
};
}
@@ -138,6 +143,62 @@ function mutationErrorLabel(locale: Locale, code: unknown): string {
}
}
+function writePosterShare(
+ mode: { keepRowsShare: number; keepBytesShare: number | null },
+): { share: number; unit: "bytes" | "rows" } {
+ if (mode.keepBytesShare !== null) {
+ return { share: mode.keepBytesShare, unit: "bytes" };
+ }
+ return { share: mode.keepRowsShare, unit: "rows" };
+}
+
+function formatWritePosterPercent(share: number, locale: Locale): string {
+ return (share * 100).toLocaleString(locale, {
+ maximumFractionDigits: 0,
+ minimumFractionDigits: 0,
+ }) + "%";
+}
+
+function formatRankedSourceLabel(locale: Locale, target: string): string {
+ const match = /^TARGET_(\d+)$/.exec(target);
+ if (!match) return target;
+ const rank = Number(match[1]);
+ if (!Number.isFinite(rank) || rank <= 0) return target;
+ return logGuardLabel(locale, "rankedSourceRank").replace("{rank}", String(rank));
+}
+
+function WritePosterMeter({
+ locale,
+ modeKey,
+ modeLabel,
+ share,
+ unit,
+}: {
+ locale: Locale;
+ modeKey: "off" | "compat" | "quiet";
+ modeLabel: string;
+ share: number;
+ unit: "bytes" | "rows";
+}) {
+ const clamped = Math.max(0, Math.min(1, share));
+ const percent = formatWritePosterPercent(clamped, locale);
+ return (
+
+
+ {modeLabel}
+ {percent}
+
+
+
+ );
+}
+
function CodexLogGuardPanel({
report,
locale,
@@ -213,23 +274,67 @@ function CodexLogGuardPanel({
+ {metrics?.writePoster && (
+
+
+ {logGuardLabel(locale, "writePoster")}
+
+
{logGuardLabel(locale, "writePosterHelp")}
+ {([
+ ["off", logGuardLabel(locale, "writePosterOff")] as const,
+ ["compat", logGuardLabel(locale, "compat")] as const,
+ ["quiet", logGuardLabel(locale, "quiet")] as const,
+ ]).map(([modeKey, modeLabel]) => {
+ const poster = writePosterShare(metrics.writePoster![modeKey]);
+ return (
+
+ );
+ })}
+
+ {metrics.writePoster.off.keepBytesShare !== null
+ ? logGuardLabel(locale, "writePosterUnitBytes")
+ : logGuardLabel(locale, "writePosterUnitRows")}
+
+
+ )}
+
{protection && (
-
{logGuardLabel(locale, "protection")}
-
- {logGuardProtectionStateLabel(locale, protection.state)}
-
- {logGuardProtectionModeLabel(locale, protection.desiredMode)}
- {protection.observedMode !== protection.desiredMode ? <> · {logGuardProtectionModeLabel(locale, protection.observedMode)}> : null}
-
-
-
+
+ {logGuardLabel(locale, "protection")}
+
+
{logGuardLabel(locale, "protectionHelp")}
+
+
+
- {logGuardLabel(locale, "desiredMode")}
+ {logGuardProtectionModeLabel(locale, protection.desiredMode)}
+
+
+
- {t("dash.status")}
+ {logGuardProtectionStateLabel(locale, protection.state)}
+
+ {protection.observedMode !== protection.desiredMode ? (
+
+
- {logGuardLabel(locale, "observedMode")}
+ {logGuardProtectionModeLabel(locale, protection.observedMode)}
+
+ ) : null}
+
+