Summary
When officecli watch <file> is running, single-command edits (add / set / move / remove) live-update the preview via SSE content patches (word-patch / replace / excel-patch). But batch and create --force edits do not trigger any content patch — the preview stays stale until the watch process is manually restarted.
This breaks any client that uses watch as a live preview while the agent edits the document via batch (the recommended way to apply multi-step edits) or re-creates the file.
Reproduce
BIN=officecli # v1.0.125, macOS darwin-x64
mkdir -p /tmp/repro && cd /tmp/repro
$BIN create deck.pptx --force --json
$BIN add deck.pptx '/' --type slide --json
$BIN add deck.pptx '/slide[1]' --type shape --prop text="initial" --prop x=1cm --prop y=1cm --json
$BIN watch deck.pptx --port 9560 &
sleep 2
# stream /events in the background
curl -s -N --max-time 5 http://127.0.0.1:9560/events > /tmp/repro/ev.txt &
sleep 1
# (A) single add -> SSE emits a content patch ("replace") ✅
$BIN add deck.pptx '/slide[1]' --type shape --prop text="via single add" --prop x=1cm --prop y=4cm --json
sleep 2
# (B) batch via stdin -> SSE emits ONLY mark-update/selection-update, NO content patch ❌
echo '[{"command":"add","parent":"/slide[1]","type":"shape","props":{"text":"via batch","x":"1cm","y":"7cm"}}]' \
| $BIN batch deck.pptx --json
sleep 2
# (C) create --force overwrite -> same, NO content patch ❌
$BIN create deck.pptx --force --json
sleep 2
grep -oE '"action":"[^"]+"' /tmp/repro/ev.txt | sort -u
Observed SSE action values: mark-update, replace, selection-update.
- The
replace comes only from the single add in step (A).
- Steps (B)
batch and (C) create --force produce no content action — only mark-update / selection-update. The watched DOM never updates for those writes.
Same result for .xlsx (excel-patch is emitted for single set/add but not for batch) and .docx (word-patch for single add but not for batch).
Expected
batch and create applied to a file that has a running watch should trigger the same SSE content update as the equivalent single commands, so the preview reflects the new content without a manual watch restart.
Root cause
In src/officecli/ResidentServer.cs, ExecuteCommand dispatches each verb and calls a NotifyWatch* helper after the mutation (e.g. NotifyWatchSlideChanged, NotifyWatchRootChanged, NotifyWatchFullRefresh):
- the
add / set / move / remove / etc. cases each call NotifyWatch* after mutating (~lines 954–1006), so the watch SSE-patches the rendered DOM.
- the
batch case (~line 1016) only calls ExecuteBatch(request), and ExecuteBatch (~line 1039) applies items directly via CommandBuilder.ApplyBatchItems(_handler, items, …) without calling any NotifyWatch* helper before returning. So the in-memory document is updated but the watch is never notified → no content SSE event.
create --force overwriting a file that is currently watched likewise produces no content notification.
The non-resident (standalone CLI) path goes through CommandBuilder.cs which does call WatchNotifier.NotifyIfWatching(...) (~lines 1503–1563), but when a resident/watch is already holding the file, edits route through ResidentServer and miss the notification.
Suggested fix
Call a watch notification at the end of ResidentServer.ExecuteBatch (after ReconcileGlobalIds / PrintBatchResults) — e.g. NotifyWatchFullRefresh() (or the per-handler variant already used by the other verbs) — and ensure the create --force overwrite path notifies when the file is currently watched.
Environment
- officecli:
1.0.125 (darwin-x64 bundled runtime)
- Discovered while integrating
officecli watch as a live in-place preview surface (single stable iframe over the watch HTTP server) in an Electron app, where batch/create are the common multi-step write paths.
Happy to send a PR if maintainers confirm the intended fix location.
Summary
When
officecli watch <file>is running, single-command edits (add/set/move/remove) live-update the preview via SSE content patches (word-patch/replace/excel-patch). Butbatchandcreate --forceedits do not trigger any content patch — the preview stays stale until the watch process is manually restarted.This breaks any client that uses
watchas a live preview while the agent edits the document viabatch(the recommended way to apply multi-step edits) or re-creates the file.Reproduce
Observed SSE
actionvalues:mark-update,replace,selection-update.replacecomes only from the singleaddin step (A).batchand (C)create --forceproduce no content action — onlymark-update/selection-update. The watched DOM never updates for those writes.Same result for
.xlsx(excel-patchis emitted for singleset/addbut not forbatch) and.docx(word-patchfor singleaddbut not forbatch).Expected
batchandcreateapplied to a file that has a runningwatchshould trigger the same SSE content update as the equivalent single commands, so the preview reflects the new content without a manual watch restart.Root cause
In
src/officecli/ResidentServer.cs,ExecuteCommanddispatches each verb and calls aNotifyWatch*helper after the mutation (e.g.NotifyWatchSlideChanged,NotifyWatchRootChanged,NotifyWatchFullRefresh):add/set/move/remove/ etc. cases each callNotifyWatch*after mutating (~lines 954–1006), so the watch SSE-patches the rendered DOM.batchcase (~line 1016) only callsExecuteBatch(request), andExecuteBatch(~line 1039) applies items directly viaCommandBuilder.ApplyBatchItems(_handler, items, …)without calling anyNotifyWatch*helper before returning. So the in-memory document is updated but the watch is never notified → no content SSE event.create --forceoverwriting a file that is currently watched likewise produces no content notification.The non-resident (standalone CLI) path goes through
CommandBuilder.cswhich does callWatchNotifier.NotifyIfWatching(...)(~lines 1503–1563), but when a resident/watch is already holding the file, edits route throughResidentServerand miss the notification.Suggested fix
Call a watch notification at the end of
ResidentServer.ExecuteBatch(afterReconcileGlobalIds/PrintBatchResults) — e.g.NotifyWatchFullRefresh()(or the per-handler variant already used by the other verbs) — and ensure thecreate --forceoverwrite path notifies when the file is currently watched.Environment
1.0.125(darwin-x64 bundled runtime)officecli watchas a live in-place preview surface (single stable iframe over the watch HTTP server) in an Electron app, wherebatch/createare the common multi-step write paths.Happy to send a PR if maintainers confirm the intended fix location.