Skip to content

Plan timings and reuse reasons

reflow plan inspects the selected flows and their current inputs without running them or sending target-readiness probes. Timing collection is automatic. Use the standard debug mode when investigating slow planning or preparing feedback:

Terminal window
reflow plan smoke checkout --log-level debug
reflow plan smoke checkout --json --log-level debug

Debug diagnostics go to stderr. Each timing event is one JSON line with level: "debug", event: "plan_timings" and a timings report. Normal terminal output and JSON stdout keep their usual plan data; diagnostics do not change reuse decisions or the reviewed plan fingerprint. There is no timing-specific flag. REFLOW_LOG_LEVEL=debug enables the same debug mode; an explicit CLI --log-level takes precedence.

For local MCP, set REFLOW_LOG_LEVEL=debug in the Reflow process environment and read its stderr through the agent host. A host may need to reconnect MCP after changing that environment. Local MCP plan diagnostics measure the daemon handler, excluding the rest of the agent host’s tool-call latency. CLI reports also measure process startup, discovery and the local round trip.

Durations use milliseconds. The breakdown includes CLI setup, daemon discovery, the daemon round trip and queue, source inspection, flow inventory and source fetching, plugin integrity checks, configuration and baseline reads, shared execution history, and remaining planning work. Shared-history timing includes the full client-observed request and response processing; it does not separate the server’s database and evidence-storage operations.

Parent durations include their children. Do not add every displayed row together: concurrent work overlaps, and the other/exclusive values account for those overlaps. The CLI total ends when the timing report is prepared; shell launcher time and the final output flush are outside that measurement. An external wall clock includes those additional costs; report it alongside the CLI total.

The diagnostic phase names are:

PhaseWhat it measures
cli_totalCLI process start to report preparation
cli_setupStartup and local setup before daemon discovery
daemon_discoveryFinding or starting the selected daemon
daemon_round_tripThe complete local request and response
daemon_requestThe daemon handler’s part of that round trip
daemon_queueWaiting behind earlier daemon operations
daemon_initializationPreparing the controller when needed
planningPreparing the plan and reading current ownership
local_configurationReading the local target, bindings and inputs
identity, test_data, configurationShared identity, test-data state and configuration reads
source_scanInspecting repository source files
storage_context, inventoryReading the application and flow inventory
source_resolution, source_fetchResolving selected flow sources and fetching their contents
plugin_integrityChecking the selected application lock and installed providers
baselinesReading visual baselines
shared_historyFetching shared execution outcomes and evidence availability
history_projectionTurning history into the latest step outcomes
ownerReading the group’s current owner

Only phases reached by that request appear. A phase’s count records how many measured calls it combines. other/exclusive is work inside that phase not accounted for by its measured children.

With an older daemon, the CLI still measures discovery and the round trip. In the debug report, an absent daemon_request child under daemon_round_trip means daemon detail was not available; it does not mean daemon work took zero time. Upgrade to obtain it.

Handled planning errors emit available partial timings on the debug channel. Generic planning failures retain the existing stderr error and nonzero exit; --json does not add a stdout error object. Argument errors, import failures or abrupt process termination can prevent a timing report entirely.

For a useful comparison, keep the flow selection, target and application lock unchanged and collect several warm runs. Report the CLI version, timing output, external wall time, and counts to run and reuse. Include the relevant sanitized plan_timings event in feedback, not a full unreviewed log. Never repeat an uncertain apply or another mutation solely to collect diagnostics. A faster source scan alone does not establish that the whole plan is faster.

Reuse requires matching target state, execution inputs, dependencies and retained evidence. After reflow init --upgrade changes a used provider’s pins, affected steps can need another run even when the repository is unchanged. Their previous evidence describes the earlier inputs; reuse can resume once the affected steps satisfy the current reuse requirements.

When the latest matching run retains a plugin lock for the same application, target and unchanged flow source, the plan names changed pins of providers used by that flow, with abbreviated old and new identities. This identifies a known change, not necessarily the only change. Missing historical metadata, edited flow source or changes to unused providers keep the generic explanation.

A plan can also require work because the flow, covered source, bindings, supplied inputs, configuration or visual baselines changed. An input-change explanation should not be read as permission to retry a step whose completion is unknown; inspect that outcome before explicitly tainting it.