Skip to content

Commit 3508879

Browse files
committed
docs: record R graphics device decision
1 parent 1ea9a35 commit 3508879

2 files changed

Lines changed: 56 additions & 24 deletions

File tree

docs/futurework/r-graphics-device-for-incremental-plot-emission.md

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,17 @@
22

33
## Summary
44

5-
The current R plot-capture path is good enough for many cases, but it cannot
6-
reliably surface a plot as soon as it becomes visible on an interactive device.
5+
A custom R graphics device was investigated as a way to emit plot updates closer
6+
to draw time. It is not currently recommended.
7+
8+
The known plot-before-later-stdout ordering bug was a server-side timeline
9+
problem, not a graphics-device problem. That bug is now handled by timeline
10+
reconstruction, and a custom device would not remove the need for that ordering
11+
logic.
12+
13+
The current R plot-capture path still has one real limitation: it cannot reliably
14+
surface a plot as soon as it becomes visible on an interactive device inside a
15+
single grouped top-level expression.
716

817
The most obvious failure shape is a grouped top-level expression such as:
918

@@ -15,8 +24,8 @@ In an interactive R session, the plot is already visible before the later
1524
`cat("done\n")`. In `mcp-repl`, the current hook-based capture path can delay
1625
the plot image until later than that.
1726

18-
This future work item covers a more direct graphics-capture design that can
19-
emit plots incrementally, without waiting for top-level task completion.
27+
This note is retained as a decision record for why that limitation is not enough
28+
to justify a custom graphics device today.
2029

2130
## Current Design
2231

@@ -32,7 +41,7 @@ Today, `mcp-repl` captures R plots by:
3241
That path is intentionally lightweight and avoids implementing a full graphics
3342
device in Rust or C.
3443

35-
## Why This Is Insufficient
44+
## Remaining Limitation
3645

3746
The current hook set is too coarse for some timing-sensitive cases.
3847

@@ -47,13 +56,38 @@ So for a grouped expression, the current design has no precise “plot is now on
4756
screen” signal. That means server-side timeline fixes can only help after the
4857
image exists; they cannot make an image arrive earlier than the worker emits it.
4958

50-
## Candidate Approaches
59+
That limitation is separate from ordinary plot/stdout ordering across separate
60+
input lines. The server timeline can already place an emitted `plot_image`
61+
before later stdout when the sideband facts contain that ordering.
62+
63+
## Investigation Outcome
64+
65+
Do not implement a custom graphics device now.
66+
67+
The reasons are:
68+
69+
- The main observed ordering failure was fixed in server-side timeline
70+
reconstruction.
71+
- A custom device would not by itself solve cross-stream ordering; the server
72+
would still need to merge stdout/stderr pipes with sideband image events.
73+
- The remaining grouped-expression limitation is narrower than the original
74+
ordering problem.
75+
- A device implementation would add a large native graphics surface: page
76+
lifecycle, clipping, text, rasters, sizing, platform behavior, and replay
77+
compatibility.
78+
- Lower-level graphics-engine hooks without a device do not appear to expose a
79+
clean "current page changed" signal for the existing architecture.
80+
81+
Keep the hook/replay path unless there is a concrete product requirement for
82+
mid-expression plot visibility.
83+
84+
## Investigated Approaches
5185

5286
### 1. Real MCP graphics device
5387

5488
Implement a real R graphics device for `mcp-repl`.
5589

56-
Why this is attractive:
90+
Why this looked attractive:
5791

5892
- drawing callbacks run as graphics operations happen,
5993
- the device can know immediately when a page becomes dirty,
@@ -69,6 +103,8 @@ Tradeoffs:
69103
sizing,
70104
- likely more cross-platform complexity.
71105

106+
Current decision: not recommended.
107+
72108
### 2. Custom offscreen capture device
73109

74110
Implement a narrower custom device whose job is only to capture the active page
@@ -86,6 +122,9 @@ Tradeoffs:
86122
- still needs careful handling of page boundaries and device state,
87123
- may end up close in complexity to a full custom device anyway.
88124

125+
Current decision: not recommended. The narrower version still carries most of
126+
the hard device-lifecycle work.
127+
89128
### 3. Deeper graphics-engine integration without a device
90129

91130
Investigate whether a lower-level hook into the R graphics engine could observe
@@ -101,24 +140,17 @@ Current read on this option:
101140

102141
This option should be treated as a long shot, not the default plan.
103142

104-
## Recommendation
105-
106-
If `mcp-repl` needs grouped expressions to surface plots before later stdout
107-
text, the serious path is a custom graphics device.
108-
109-
If the goal is the smallest architectural leap from today’s code:
143+
## Revisit Criteria
110144

111-
- prefer a custom offscreen capture device first,
112-
- keep the emitted artifact as PNG,
113-
- dedupe on content hash as today,
114-
- leave server-side ordering logic unchanged except for consuming earlier image
115-
arrivals.
145+
Revisit this only if there is a concrete public requirement for plots to appear
146+
while a single grouped R expression is still running.
116147

117-
If the goal is the cleanest long-term architecture:
148+
Before changing the graphics device, require:
118149

119-
- implement a real `mcp-repl` graphics device explicitly,
120-
- stop depending on `recordPlot()` / `replayPlot()` for timing-sensitive plot
121-
emission.
150+
- a public API regression test that demonstrates the user-visible gap,
151+
- a prototype showing materially earlier image emission for that case,
152+
- evidence that the improvement is worth the native-device complexity,
153+
- no regression to current base and grid plot capture.
122154

123155
## Relationship To Other Work
124156

@@ -132,7 +164,7 @@ specifically about the plot-capture mechanism.
132164

133165
## Non-Goals
134166

135-
- Fixing plot/stdout ordering only in the server timeline.
167+
- Reopening the fixed plot/stdout ordering bug.
136168
- Expanding the existing `recordPlot()` hook set indefinitely.
137169
- Redesigning Python plotting.
138170
- Redefining request completion as part of the same work item.

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ checked-in execution plans without relying on stale notes.
3434
- `docs/futurework/offline-manual-surfaces.md`: deferred design note on exposing R manuals and future Python manuals through better offline model-facing surfaces than the current inline `RShowDoc()` flow.
3535
- `docs/futurework/per-turn-history-bundles.md`: design brief for always-materialized per-turn REPL history bundles.
3636
- `docs/futurework/r-embedding-minimal-callbacks.md`: deferred note on reducing custom embedded-R callbacks while keeping readline integration.
37-
- `docs/futurework/r-graphics-device-for-incremental-plot-emission.md`: deferred design note on replacing hook/replay plot capture with a device-level path that can emit plots before grouped expressions finish.
37+
- `docs/futurework/r-graphics-device-for-incremental-plot-emission.md`: decision record for not currently replacing hook/replay plot capture with a custom graphics device.
3838
- `docs/futurework/worker-session-tempdir-rotation.md`: deferred design note on rotating worker tempdir paths per launch so stale temp trees do not block respawn.
3939
- `docs/futurework/stronger-worker-child-containment.md`: deferred design note on tighter worker descendant containment, especially on Windows.
4040
- `docs/futurework/unified-output-timeline-pipeline.md`: deferred design note for converging pager and files mode onto one shared resolved timeline pipeline.

0 commit comments

Comments
 (0)