<feed xmlns='http://www.w3.org/2005/Atom'>
<title>lattex.git/src/main/fileSyncBridge.ts, branch v0.6.0</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.
</subtitle>
<link rel='alternate' type='text/html' href='https://git.blackhao.com/lattex.git/'/>
<entry>
<title>Add browser-style project tabs: persistent home + one tab per project</title>
<updated>2026-08-18T12:24:40+00:00</updated>
<author>
<name>haoyuren</name>
<email>13851610112@163.com</email>
</author>
<published>2026-08-18T12:24:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.blackhao.com/lattex.git/commit/?id=ec8214a4d111d92ce7c44de29d1706f241aa9514'/>
<id>ec8214a4d111d92ce7c44de29d1706f241aa9514</id>
<content type='text'>
The project list is now a persistent home tab; each opened project runs
in its own WebContentsView tab below a 38px tab strip (hidden when only
home is open). Background tabs stay fully live (sync, collab, terminals).

Main process: per-project singletons (socket, sync bridge, compilation
manager, MCP state, compile watcher) become per-tab ProjectSession
objects keyed by webContents.id; PTYs are scoped per webContents.
Hardened against races found in review: concurrent ot:connect dedupe,
teardown/reopen serialization on the shared sync dir, destroyed-window
guards on all bridge sends, real logout that closes project tabs.

Renderer: tabs strip in the home renderer (wt-* classes, distinct from
the editor's .tab-bar file tabs), project tabs boot from ?projectId= and
connect straight into the editor; Back closes the tab.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The project list is now a persistent home tab; each opened project runs
in its own WebContentsView tab below a 38px tab strip (hidden when only
home is open). Background tabs stay fully live (sync, collab, terminals).

Main process: per-project singletons (socket, sync bridge, compilation
manager, MCP state, compile watcher) become per-tab ProjectSession
objects keyed by webContents.id; PTYs are scoped per webContents.
Hardened against races found in review: concurrent ot:connect dedupe,
teardown/reopen serialization on the shared sync dir, destroyed-window
guards on all bridge sends, real logout that closes project tabs.

Renderer: tabs strip in the home renderer (wt-* classes, distinct from
the editor's .tab-bar file tabs), project tabs boot from ?projectId= and
connect straight into the editor; Back closes the tab.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Cross-platform support: Windows build target and CI release workflow</title>
<updated>2026-07-30T01:00:55+00:00</updated>
<author>
<name>haoyuren</name>
<email>13851610112@163.com</email>
</author>
<published>2026-07-30T01:00:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.blackhao.com/lattex.git/commit/?id=7297f7c339186f8af50f4f0ed3734e4ad4b47aed'/>
<id>7297f7c339186f8af50f4f0ed3734e4ad4b47aed</id>
<content type='text'>
- Normalize watcher paths to forward slashes (Windows events use
  backslashes; all sync maps are '/'-keyed), path.delimiter for
  PATH/TEXINPUTS, dirname() instead of '/'-substring splits, bridge log
  in os.tmpdir()
- Platform-aware TeX search paths (TeX Live / MiKTeX on Windows),
  terminal shell default (COMSPEC/powershell), native window frame off
  macOS
- electron-builder: NSIS target + win icon + GitHub publish provider
- GitHub Actions workflow builds the Windows installer on tag push
  (node-pty needs MSVC — cannot cross-compile from macOS) and attaches
  it to the release

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
- Normalize watcher paths to forward slashes (Windows events use
  backslashes; all sync maps are '/'-keyed), path.delimiter for
  PATH/TEXINPUTS, dirname() instead of '/'-substring splits, bridge log
  in os.tmpdir()
- Platform-aware TeX search paths (TeX Live / MiKTeX on Windows),
  terminal shell default (COMSPEC/powershell), native window frame off
  macOS
- electron-builder: NSIS target + win icon + GitHub publish provider
- GitHub Actions workflow builds the Windows installer on tag push
  (node-pty needs MSVC — cannot cross-compile from macOS) and attaches
  it to the release

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Codex/agent-neutral setup, terminal IME fix, hide own overlay cursor</title>
<updated>2026-07-27T22:29:04+00:00</updated>
<author>
<name>haoyuren</name>
<email>13851610112@163.com</email>
</author>
<published>2026-07-27T22:29:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.blackhao.com/lattex.git/commit/?id=d35a6a0ef366f86aeba28c06f40e44cd29cf1f07'/>
<id>d35a6a0ef366f86aeba28c06f40e44cd29cf1f07</id>
<content type='text'>
- Write AGENTS.md (the cross-tool agent-instructions standard) at the
  project root alongside .claude/CLAUDE.md, generated from one guide;
  includes an Agent Setup section with the project-specific Codex MCP
  registration command. AGENTS.md is excluded from Overleaf sync.
- MCP server resolves the project directory from its own script location
  when cwd doesn't contain the state file, so clients that launch MCP
  servers from a global config (Codex) work without special setup
- Terminal: swallow the duplicate compositionend commit when switching
  input sources mid-composition (xterm finalizes on the keydown and then
  again on compositionend, sending pinyin text twice)
- Don't render our own colored overlay cursor — the native caret already
  marks our position; overlay cursors are collaborators-only (web parity)

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
- Write AGENTS.md (the cross-tool agent-instructions standard) at the
  project root alongside .claude/CLAUDE.md, generated from one guide;
  includes an Agent Setup section with the project-specific Codex MCP
  registration command. AGENTS.md is excluded from Overleaf sync.
- MCP server resolves the project directory from its own script location
  when cwd doesn't contain the state file, so clients that launch MCP
  servers from a global config (Codex) work without special setup
- Terminal: swallow the duplicate compositionend commit when switching
  input sources mid-composition (xterm finalizes on the keydown and then
  again on compositionend, sending pinyin text twice)
- Don't render our own colored overlay cursor — the native caret already
  marks our position; overlay cursors are collaborators-only (web parity)

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Overleaf web-client parity: dashboard, editor, and sync overhaul</title>
<updated>2026-07-27T21:16:20+00:00</updated>
<author>
<name>haoyuren</name>
<email>13851610112@163.com</email>
</author>
<published>2026-07-27T21:16:20+00:00</published>
<link rel='alternate' type='text/html' href='https://git.blackhao.com/lattex.git/commit/?id=2fbcf18010bf79d3c1517c920325f12b122ec96e'/>
<id>2fbcf18010bf79d3c1517c920325f12b122ec96e</id>
<content type='text'>
Uses the Overleaf open-source code as golden reference throughout.

Project dashboard (official /tag + /project endpoints):
- Sidebar filters (all/yours/shared/archived/trashed) with the web
  client's exact filtering predicates
- Tags: create/edit/delete with the official preset palette, per-row
  chips, bulk add/remove, uncategorized view
- Archive/trash/restore/delete-forever/leave, rename, copy, zip download,
  multi-select bulk actions (parallelized)

Editor:
- Remote cursors rewritten as a layer() overlay ported from Overleaf's
  cursor-highlights — no more inline widgets disturbing line wrapping,
  cursor motion, or IME composition
- Autocomplete ported from Overleaf's completion system: official
  top-hundred snippet data, environment templates, package/class/bib
  style data (verbatim, AGPL), project-wide \ref and \cite completion,
  package commands via the official /project/:id/metadata endpoint,
  brace-aware apply behavior, official keymap precedence
- Fixed completion popup keybindings (Enter/arrows previously fell
  through to the default keymap) and dead Enter/Backspace handlers in
  latexClosing

File sync reliability:
- Two-tier compile-artifact detection: pure build noise is ignored,
  while pdf/docx/gz/bbl sync unless there is concrete local-compile
  evidence — agent-generated figure PDFs now sync (previously all PDFs
  were blanket-ignored)
- Local compile outputs are registered with the bridge so nested-root
  projects don't upload the root PDF as junk
- Upload retry with exponential backoff and permanent-failure parking,
  CSRF refresh with session validation and single-flight guard,
  periodic orphan rescan, sync status surfaced in the status bar
- Official textExtensions list (plus legacy extras) for doc-vs-file
  classification

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Uses the Overleaf open-source code as golden reference throughout.

Project dashboard (official /tag + /project endpoints):
- Sidebar filters (all/yours/shared/archived/trashed) with the web
  client's exact filtering predicates
- Tags: create/edit/delete with the official preset palette, per-row
  chips, bulk add/remove, uncategorized view
- Archive/trash/restore/delete-forever/leave, rename, copy, zip download,
  multi-select bulk actions (parallelized)

Editor:
- Remote cursors rewritten as a layer() overlay ported from Overleaf's
  cursor-highlights — no more inline widgets disturbing line wrapping,
  cursor motion, or IME composition
- Autocomplete ported from Overleaf's completion system: official
  top-hundred snippet data, environment templates, package/class/bib
  style data (verbatim, AGPL), project-wide \ref and \cite completion,
  package commands via the official /project/:id/metadata endpoint,
  brace-aware apply behavior, official keymap precedence
- Fixed completion popup keybindings (Enter/arrows previously fell
  through to the default keymap) and dead Enter/Backspace handlers in
  latexClosing

File sync reliability:
- Two-tier compile-artifact detection: pure build noise is ignored,
  while pdf/docx/gz/bbl sync unless there is concrete local-compile
  evidence — agent-generated figure PDFs now sync (previously all PDFs
  were blanket-ignored)
- Local compile outputs are registered with the bridge so nested-root
  projects don't upload the root PDF as junk
- Upload retry with exponential backoff and permanent-failure parking,
  CSRF refresh with session validation and single-flight guard,
  periodic orphan rescan, sync status surfaced in the status bar
- Official textExtensions list (plus legacy extras) for doc-vs-file
  classification

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix Overleaf file tree sync updates</title>
<updated>2026-04-25T20:21:27+00:00</updated>
<author>
<name>haoyuren</name>
<email>13851610112@163.com</email>
</author>
<published>2026-04-25T20:21:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.blackhao.com/lattex.git/commit/?id=59cb73960ee68a47adbdc05915847cb8d45f795e'/>
<id>59cb73960ee68a47adbdc05915847cb8d45f795e</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix OT sync corruption: match Overleaf ShareJS ack/echo handling</title>
<updated>2026-03-18T08:06:32+00:00</updated>
<author>
<name>haoyuren</name>
<email>13851610112@163.com</email>
</author>
<published>2026-03-18T08:06:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.blackhao.com/lattex.git/commit/?id=9b5256718c2117511f0253a656bb8cff7410b92a'/>
<id>9b5256718c2117511f0253a656bb8cff7410b92a</id>
<content type='text'>
The server broadcasts otUpdateApplied (with ops) to ALL clients including
the sender. Our bridge was treating its own echoed ops as remote ops and
re-applying them, causing text duplication (e.g. "simulatorimulator").

Rewrite OT handling to match Overleaf's ShareJS _onMessage pattern:
- ACK = no ops OR meta.source matches our publicId (own echo)
- REMOTE = ops from a different source
- ACK path calls onAck() without re-applying ops
- OtClient silently drops duplicate acks in synchronized state
- OtClient drops stale remote ops (version &lt; current)
- Remove pendingEchos counter in favor of meta.source detection

Also: refresh MCP comment contexts on new-comment/delete-thread events,
add Overleaf reference repo to .gitignore.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The server broadcasts otUpdateApplied (with ops) to ALL clients including
the sender. Our bridge was treating its own echoed ops as remote ops and
re-applying them, causing text duplication (e.g. "simulatorimulator").

Rewrite OT handling to match Overleaf's ShareJS _onMessage pattern:
- ACK = no ops OR meta.source matches our publicId (own echo)
- REMOTE = ops from a different source
- ACK path calls onAck() without re-applying ops
- OtClient silently drops duplicate acks in synchronized state
- OtClient drops stale remote ops (version &lt; current)
- Remove pendingEchos counter in favor of meta.source detection

Also: refresh MCP comment contexts on new-comment/delete-thread events,
add Overleaf reference repo to .gitignore.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix OT ack/error swallowed when doc transitions to editor mode</title>
<updated>2026-03-16T00:13:57+00:00</updated>
<author>
<name>haoyuren</name>
<email>13851610112@163.com</email>
</author>
<published>2026-03-16T00:13:57+00:00</published>
<link rel='alternate' type='text/html' href='https://git.blackhao.com/lattex.git/commit/?id=c667ff6a58b36b67bb92ff5a20df646e0777c6d5'/>
<id>c667ff6a58b36b67bb92ff5a20df646e0777c6d5</id>
<content type='text'>
When addEditorDoc is called while the bridge has in-flight OT ops
(awaitingConfirm), the ack/error response was ignored because
handleOtUpdate/handleOtError skipped editor docs entirely. This left
the bridge's OtClient stuck and the edit appeared lost until
removeEditorDoc re-discovered the discrepancy.

Fix: always process acks regardless of editor doc status, and only
skip OT errors for editor docs when the bridge has no OtClient.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When addEditorDoc is called while the bridge has in-flight OT ops
(awaitingConfirm), the ack/error response was ignored because
handleOtUpdate/handleOtError skipped editor docs entirely. This left
the bridge's OtClient stuck and the edit appeared lost until
removeEditorDoc re-discovered the discrepancy.

Fix: always process acks regardless of editor doc status, and only
skip OT errors for editor docs when the bridge has no OtClient.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Add online users popover, MCP get_online_users, claude-workspace, stronger CLAUDE.md</title>
<updated>2026-03-15T23:47:29+00:00</updated>
<author>
<name>haoyuren</name>
<email>13851610112@163.com</email>
</author>
<published>2026-03-15T23:47:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.blackhao.com/lattex.git/commit/?id=a36b73505754acab6872d23c9add58dfca3cecdd'/>
<id>a36b73505754acab6872d23c9add58dfca3cecdd</id>
<content type='text'>
- Online users: click "N online" badge to see user names with cursor colors
- MCP get_online_users tool: main process tracks users in .lattex-online-users.json
- CLAUDE.md: show current user's Overleaf name (fetched from /user/settings)
- CLAUDE.md: mandatory first steps with MUST/NEVER language at top of file
- claude-workspace/ directory: untracked scratch space for Claude Code experiments
- chokidar + bridge skip claude-workspace/ to prevent syncing to Overleaf

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
- Online users: click "N online" badge to see user names with cursor colors
- MCP get_online_users tool: main process tracks users in .lattex-online-users.json
- CLAUDE.md: show current user's Overleaf name (fetched from /user/settings)
- CLAUDE.md: mandatory first steps with MUST/NEVER language at top of file
- claude-workspace/ directory: untracked scratch space for Claude Code experiments
- chokidar + bridge skip claude-workspace/ to prevent syncing to Overleaf

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix file sync for non-active tabs, MCP compile integration, OT resilience</title>
<updated>2026-03-15T23:21:06+00:00</updated>
<author>
<name>haoyuren</name>
<email>13851610112@163.com</email>
</author>
<published>2026-03-15T23:21:06+00:00</published>
<link rel='alternate' type='text/html' href='https://git.blackhao.com/lattex.git/commit/?id=c9d673d83037167553dcef3947065266743b2d5f'/>
<id>c9d673d83037167553dcef3947065266743b2d5f</id>
<content type='text'>
- Fix .bib (and other non-active tab) edits disappearing: call otLeaveDoc
  on tab switch so bridge takes back OT ownership; release .bib pre-loads
  immediately after reading content for citation autocomplete
- Always update lastKnownContent in processDocChange for editor docs to
  prevent stale state accumulation
- Flush pending OT ops in OverleafDocSync.destroy() before tab switch
- Add three-way merge in replaceContent to preserve concurrent remote edits
- Wire MCP compile to UI: file-based signal between MCP server and Electron
  main process, with compile animation and PDF refresh in renderer
- Add CLSI flush before compile to prevent stale cached results
- Add OT error recovery: re-join doc and re-apply disk changes on otUpdateError
- Add bridge reconnect handling: reset OtClient on docRejoined for non-editor docs
- Add compile concurrency lock to prevent duplicate compiles
- removeEditorDoc compares disk vs server content to catch in-flight ops

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
- Fix .bib (and other non-active tab) edits disappearing: call otLeaveDoc
  on tab switch so bridge takes back OT ownership; release .bib pre-loads
  immediately after reading content for citation autocomplete
- Always update lastKnownContent in processDocChange for editor docs to
  prevent stale state accumulation
- Flush pending OT ops in OverleafDocSync.destroy() before tab switch
- Add three-way merge in replaceContent to preserve concurrent remote edits
- Wire MCP compile to UI: file-based signal between MCP server and Electron
  main process, with compile animation and PDF refresh in renderer
- Add CLSI flush before compile to prevent stale cached results
- Add OT error recovery: re-join doc and re-apply disk changes on otUpdateError
- Add bridge reconnect handling: reset OtClient on docRejoined for non-editor docs
- Add compile concurrency lock to prevent duplicate compiles
- removeEditorDoc compares disk vs server content to catch in-flight ops

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix sync race condition: external edits overwritten by remote ops</title>
<updated>2026-03-15T20:02:15+00:00</updated>
<author>
<name>haoyuren</name>
<email>13851610112@163.com</email>
</author>
<published>2026-03-15T20:02:15+00:00</published>
<link rel='alternate' type='text/html' href='https://git.blackhao.com/lattex.git/commit/?id=72b38fed1d75fcb3420beeeeefd3dc2fc442e64b'/>
<id>72b38fed1d75fcb3420beeeeefd3dc2fc442e64b</id>
<content type='text'>
When Claude Code writes to disk, a debounce timer is set. If a remote
Overleaf op arrives during the debounce, onEditorContentChanged would
write the remote content back to disk, overwriting Claude Code's edit.

Fix: skip disk write and lastKnownContent update in onEditorContentChanged
when a debounce is pending (external disk change waiting to be processed).
Also increase writesInProgress guard to 800ms to exceed chokidar's 500ms
polling interval.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When Claude Code writes to disk, a debounce timer is set. If a remote
Overleaf op arrives during the debounce, onEditorContentChanged would
write the remote content back to disk, overwriting Claude Code's edit.

Fix: skip disk write and lastKnownContent update in onEditorContentChanged
when a debounce is pending (external disk change waiting to be processed).
Also increase writesInProgress guard to 800ms to exceed chokidar's 500ms
polling interval.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
