Repository navigation
v1.3.9
v1.3.9 - 2026-05-27
Cancellation and concurrency hardening release. v1.3.9 makes the cancel button responsive sub-100 ms in every phase of a Codex run (Codex thinking, mid-writeback, post-write verification), adds a force-release recovery for stuck project locks, eliminates the cross-project write race introduced by long per-op pipelines, and ships a cleanup batch (debt registry, architecture budgets, extractFunction helper) that returned the codebase to a maintainable state after the v1.3.8 P0 churn.
Added
- Sub-100 ms cancel during writeback. The content-side
sendPageBridgeRequestnow registers a per-request reject handler inactivePageBridgeCancellationHandlersfor the writeback methods (applyOperations,acceptTrackedChanges,rejectTrackedChanges).cancelActiveRunsynchronously rejects every in-flight handler before doing anything else, so the run-card's spinner stops on the very next microtask instead of waiting for the page bridge to finish its loop. The nativecodex.canceland the page-sidecancelActiveWritesignals are now fire-and-forget (Promise.allSettled) — UI no longer waits for either round-trip. A new page-side cross-world cancel mechanism (pageBridge.cancelActiveWrite+writebackRouter.applyOperationsCore's sequence-bump check + per-opPromise.raceagainst a 50 ms poller) tells the background writeback to also stop cleanly so abandoned ops do not keep mutating Overleaf state. - Force-release recovery for stuck project locks. When a run leaks the native-host project lock (Codex CLI hangs past the idle watchdog, a previous extension version crashed mid-writeback, etc.),
codex.cancelnow accepts aprojectKeyto find the controller without the originalrequestIdand aforce: trueflag to drop the lock entry when no controller is registered. The completion-report renders a one-click "Force-release the stuck task" button undercodex_project_lockedfailures so the user no longer has to restart Chrome to escape a stuck lock. - Mid-run project-change guard inside
applyOperationsCore. Each per-op iteration re-checks the editor's current project against the run's boundrunProjectId. If the user SPA-navigates Overleaf to a different project mid-writeback, the remaining operations are skipped withaborted_project_changedinstead of landing in the wrong project.ensureReviewing/ensureEditingdispatchers now run the same guard so the pre-flight toggle cannot flip Track Changes in a wrong project. - Hydration-tolerant write-guard. The page-side editor project-id reader now retries with 100/300/700 ms backoff (~1.1 s ceiling) before failing closed, so a writeback that starts during Overleaf's editor hydration window no longer reports the misleading "Refresh Overleaf and retry" error. URL is accepted as a third source only when it exactly matches the immutable run project id.
- Codex app-server idle watchdog.
codexSessionRunnernow has a default 10-minute idle timeout (CODEX_OVERLEAF_CODEX_IDLE_TIMEOUT_MSoverridable) that aborts a Codex session if it stays silent past the deadline and releases the project lock — covers the "Codex sendsturn/startedand hangs forever" case. - New FailureReason catalog codes:
codex_project_locked,codex_timeout,codex_output_limit,codex_not_found, plus bilingual i18n strings.translateRawError's eleven regex branches now also return afailureCodeso callers attach structured failure data alongside the human text. - Structured run-state persistence:
runProjectIdis now persisted on every run record (sessionState+storageDb), so writeback / Accept / Undo on a restored run targets the original project rather than the editor's current one.getRunProjectIdForWritebackfails closed when the run record has norunProjectIdinstead of falling back to the current project id. - Native-host transient reconnect filter. The Codex app-server's
error: 'Reconnecting X/Y'notifications during network blips are recognized as transient and surfaced as warnings — they no longer abort the turn. The reconnect text is surfaced as the visible event title so the run timeline readsReconnecting... 2/5instead of a genericerror.
Changed
- Completion-report visual demotion of system meta: the human-language conclusion keeps its 13 px /
#d4d4d4styling;Why nothing changed/Write result/Undo/Nextrender in a dedicated<dl>block beneath a thin separator at 11.5 px in muted color, so they read as run metadata rather than part of Codex's answer. Failed-status reports keep their alert color on the conclusion while the meta stays muted. applyOperationspage-bridge timeout raised 8 s → 30 s. Page-sideopenFileByPathalone can wait 5 s × 4 fallback methods on slow file trees; the pre-fix 8 s timeout fired mid-write and left zombie writes running while the content side reported failure. 30 s covers the realistic slow path; cancel responsiveness is now driven by the cross-world cancel mechanism above, not by the timeout.- Misleading "no usable result" fallback retired.
translateRawErrornow accepts acodexReturnedcontext flag; when Codex'sassistantMessagearrived on the stream before an unrelated exception escaped, the conclusion reads "Codex returned a result, but local post-processing of this run failed" instead of claiming Codex returned nothing. The legacy copy still fires for genuine no-result paths. needs_reviewtracked-change runs now render the same primary Accept / Undo buttons aspending— the previous "needs review" labels conflated an internal retryable proof state with a different UX.- Settings back-button respects the current route: clicking Back from Settings on the
/projectRecent-projects URL now returns to Recent rather than unconditionally showing the per-project session view. - Codex Overleaf skills entry now displays a single clean row name (with the underlying id as the tooltip) and the enabled count refreshes immediately after toggles.
- Architecture budget enforcement added freeze-line ceilings for the four largest unbudgeted files (
contentRuntime.js,writebackRouter.js,treeOperations.js,storageDb.js). The write-guard surface was extracted frompageBridge.jstoextension/src/page/writeGuard.js, returningpageBridge.jsunder the 2200-line budget; the v1.3.8 budget shim was removed. - Shared test helper for
extractFunction(consolidated from five duplicate copies; the parser now walks past the parenthesized signature so default-value braces likefunction foo(input = {}) { … }no longer break extraction — the dormant bug that bit v1.3.8 work three times). translateRawErrorregex branches now also returnfailureCodeso callers attach structured FailureReason events alongside the existing text; three new catalog codes (codex_timeout,codex_output_limit,codex_not_found) cover branches that previously had no structured match.- DI
typeof X === 'function'guards collapsed to destructuring defaults incontextTray.js,localSkillsPanel.js,writebackRouter.js,treeOperations.js— 34+13 occurrences eliminated; passingnullor a non-function value now fails loudly rather than silently swapping in a noop. - Stale
v1.3.8 add-onframing comments (~30 sites) rewritten as plain feature descriptions now that v1.3.8 has shipped. contentRuntime.jssource reads centralized: the 145fs.readFileSync(.../contentRuntime.js)repetitions intest/p0ProductExperience.test.jsare replaced with a cachedgetContentScriptSource()helper; 77extractFunction(contentScript, name)call sites adopt theextractFromContentScript(name)shortcut.- Six unused exports trimmed from
staleGuard.js/sensitiveScan.js/pathRedaction.js, and one truly-dead function (mightContainLocalPath) removed. - Release metadata alignment: bumped the package, lockfile, extension manifest, compatibility target, and release tracking metadata for the v1.3.9 release.
- Bumped package, extension manifest, compatibility target, README release commands, and release tracking metadata to
1.3.9while keeping native protocol1. - Current release artifact names now resolve to
codex-overleaf-link-extension-v1.3.9.zip,codex-overleaf-native-host-v1.3.9.tar.gz, andcodex-overleaf-link-1.3.9.tgz. - Native host install remains
npm exec --yes codex-overleaf-link@1.3.9 -- install-native. - Native host diagnostics remain
npm exec --yes codex-overleaf-link@1.3.9 -- doctor. - Native host uninstall is
npm exec --yes codex-overleaf-link@1.3.9 -- uninstall-native.
Fixed
- Write-guard batch-skip crash that masked partial-sync conclusions (v1.3.8 add-on): the guard emitted
operation: nullskip entries;summarizeOperationForAudit(operation = {}, ...)only defaulted onundefinedsonull.paththrew and the outer catch swallowed the partial-sync report. The summarizer now normalizes null/undefined; both emit sites pushoperation: {}. saveStateSoonin-flight race: a debounce timer firing while an asyncsaveState()was still writing could let an older snapshot land after newer state mutations. Tracks an in-flight flag and queues at most one trailing run.- Settings back-button on
/projectURL no longer renders an empty per-project session view.
Notes
- Native protocol stays
1; this release adds cancellation responsiveness, structured cancellation cleanup, the writeback project-ID guard, the force-release recovery, and the native-host idle watchdog, not the native messaging protocol. - The page-side
Promise.racecancel mechanism is preserved as the cleanup path for abandoned background writes — the user-perceived "instant cancel" is delivered by the content-side reject path, but the page-side race still tells the background work to stop so abandoned ops do not keep mutating Overleaf.
npm native host package
Install or update the native host with the pinned npm package. Official release builds use the bundled stable extension id by default; pass --extension-id only for a custom or mismatched unpacked extension id:
npm exec --yes codex-overleaf-link@1.3.9 -- install-nativeRun native diagnostics with the same pinned package:
npm exec --yes codex-overleaf-link@1.3.9 -- doctorUninstall the native host with the same pinned package:
npm exec --yes codex-overleaf-link@1.3.9 -- uninstall-native