Understanding the Adaptive Flush Mechanism in OfficeCLI Resident Mode

The adaptive flush mechanism in OfficeCLI Resident Mode automatically adjusts autosave intervals between 2 and 10 seconds based on the exponential moving average of previous save durations, ensuring background serialization never consumes more than 25% of wall-clock time.

OfficeCLI's Resident Mode keeps documents in memory for rapid command execution, deferring disk writes until specific flush points. The adaptive flush mechanism, implemented as the default ResidentFlushMode.Auto strategy in the iOfficeAI/OfficeCLI repository, dynamically tunes these intervals based on measured save costs to balance data safety with performance.

How the Adaptive Flush Interval Is Computed

The algorithm, defined in src/officecli/Core/ResidentFlushPolicy.cs, calculates the debounce interval through a five-stage process that responds to serialization latency in real time.

Cost Model and Bounds

The system constrains CPU usage using a cost multiplier and hard interval limits. ResidentFlushPolicy.CostMultiplier is set to 4.0, ensuring autosave operations never exceed approximately 25% of available wall-clock time. Two constants define the acceptable range: MinAdaptiveInterval at 2 seconds and MaxAdaptiveInterval at 10 seconds.

Exponential Moving Average (EMA) Calculation

Instead of using raw save durations, the mechanism employs an asymmetric EMA that reacts differently to speed changes. The ResidentFlushPolicy.NextEmaSeconds(previous, sample) method applies RiseAlpha = 0.7 when saves slow down, causing the EMA to spike immediately on expensive operations. When saves speed up, it uses FallAlpha = 0.2, allowing the average to decrease gradually and preventing "save storms" from rapid successive triggers.

Interval Derivation and Updating

The ResidentFlushPolicy.IntervalForEma(ema) method derives the next interval by multiplying the current EMA by the cost multiplier (clamped to the 2-10 second bounds). After each successful save, ResidentServer.RecordSaveDuration(elapsed) updates _saveEmaMillis and _adaptiveIntervalTicks, instantly influencing the next watchdog timeout.

Implementation in the Autosave Watchdog

The adaptive value drives the background persistence loop in src/officecli/ResidentServer.cs. Inside RunAutosaveWatchdogAsync, the watchdog queries CurrentAutosaveInterval before each delay:

await Task.Delay(CurrentAutosaveInterval, linked.Token);
await TryAutosaveAsync(token);

The CurrentAutosaveInterval property resolves to either a fixed user-provided duration or the adaptive value stored in _adaptiveIntervalTicks:

private TimeSpan CurrentAutosaveInterval => FlushMode == ResidentFlushMode.Fixed
    ? FixedFlushInterval
    : TimeSpan.FromTicks(Volatile.Read(ref _adaptiveIntervalTicks));

This design ensures that the adaptive calculation directly controls the Task.Delay duration without restarting the watchdog process.

Why Adaptive Flush Improves Performance

The mechanism provides three key benefits for document-heavy workflows:

  • Back-off on heavy saves: When serializing large Excel workbooks takes seconds, the EMA immediately rises toward the 10-second ceiling, preventing expensive operations from dominating CPU cycles.
  • Quick recovery on fast saves: Rapid saves only nudge the EMA down slowly via the 0.2 fall alpha, maintaining stability rather than collapsing the interval prematurely.
  • Bounded CPU use: The 4.0 cost multiplier guarantees that autosave never consumes more than ~25% of wall-clock time, regardless of underlying serialization costs.

Configuring Resident Mode Flush Behavior

Developers can control persistence strategy through environment variables before invoking officecli open:

Variable Purpose Example
OFFICECLI_RESIDENT_FLUSH Sets flush mode (auto, each, fixed seconds, or off) export OFFICECLI_RESIDENT_FLUSH=auto
OFFICECLI_RESIDENT_IDLE_SECONDS Idle timeout before shutdown (unrelated to autosave) export OFFICECLI_RESIDENT_IDLE_SECONDS=720

When OFFICECLI_RESIDENT_FLUSH is unset or set to auto, the server defaults to the adaptive algorithm described above.

To enable adaptive autosave explicitly:

export OFFICECLI_RESIDENT_FLUSH=auto
export OFFICECLI_RESIDENT_IDLE_SECONDS=720

officecli open large-workbook.xlsx

Summary

  • The adaptive flush mechanism in OfficeCLI Resident Mode uses an exponential moving average (EMA) of save durations to calculate autosave intervals dynamically.
  • Intervals are constrained between 2 and 10 seconds and derived using a 4.0 cost multiplier to limit CPU usage to approximately 25%.
  • The algorithm applies asymmetric smoothing (RiseAlpha = 0.7, FallAlpha = 0.2) to respond immediately to slow saves while recovering gradually from fast ones.
  • Core logic resides in src/officecli/Core/ResidentFlushPolicy.cs, while src/officecli/ResidentServer.cs implements the watchdog loop that consumes the adaptive interval via CurrentAutosaveInterval.

Frequently Asked Questions

How does OfficeCLI determine when to autosave in Resident Mode?

The resident server calculates the next autosave delay using the ResidentFlushPolicy class. It measures the wall-clock time of each save operation, feeds that duration into an EMA calculation with asymmetric alpha values (0.7 for rises, 0.2 for falls), and multiplies the result by 4.0 to determine the interval. This value is then clamped between 2 and 10 seconds before being passed to the watchdog's Task.Delay.

Why does the adaptive flush use different alpha values for rising and falling EMA?

The asymmetric alphas prevent oscillation between fast and slow save states. When a save suddenly becomes expensive (e.g., due to document growth), RiseAlpha = 0.7 immediately raises the EMA toward the new reality, backing off quickly to conserve CPU. Conversely, FallAlpha = 0.2 ensures that when saves become cheap again, the interval descends slowly, preventing a "save storm" where too frequent disk writes hurt performance.

Can I set a fixed autosave interval instead of using the adaptive mechanism?

Yes. Set the environment variable OFFICECLI_RESIDENT_FLUSH to a positive integer representing seconds (e.g., export OFFICECLI_RESIDENT_FLUSH=5) or use each to flush after every command. When FlushMode is set to Fixed, the CurrentAutosaveInterval property bypasses the adaptive calculation and uses the user-provided FixedFlushInterval instead.

What happens if a save operation takes longer than the current adaptive interval?

The EMA calculation immediately incorporates the long duration via the high rise alpha (0.7), causing subsequent intervals to stretch toward the 10-second maximum. Because the cost multiplier caps background work at roughly 25% of wall-clock time, even pathologically slow saves cannot dominate the process indefinitely—the interval will simply max out at 10 seconds until performance improves.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →