All checks were successful
boundary-lint / PR boundary-claim (Lint (push) Has been skipped
boundary-lint / duplication-deadline (Layer 1/2) (push) Successful in 19s
boundary-lint / ban-list lint (Lint (push) Successful in 19s
ci / test-health gate (push) Successful in 16s
ci / mutation test (broker) (push) Has been skipped
Release Publish (Gitea session_helper) / verify-release-tag (push) Successful in 17s
ci / rust debug (push) Successful in 2m40s
ci / rust release (push) Successful in 2m45s
ci / python (push) Successful in 1m37s
Release Publish (Gitea session_helper) / publish-linux-x86_64 (push) Successful in 4m21s
User trace (v0.7.40 session) revealed a write echo loop that fires
every time a Sessions cache file is opened or its formatter runs:
23:05:36.236 hydrate file/read writes remote bytes to local cache
23:05:36.284 local_watcher.change_detected (= our own write)
23:05:41.619 watcher → _save_remote_file_for_workspace → file/write
pushes the same bytes back to the remote
23:05:41.629 ... and re-enqueues sessions_format_then_pipeline_after_save
23:05:41.646 exec/once for the new formatter run starts
23:05:41.905 Sublime aborts (formatter in flight)
Root cause: ``_RECENT_SELF_SAVE_REMOTE_PATHS`` (the cooldown the
local watcher uses to filter our own pushes) was only marked in
``_force_overwrite_remote`` and the regular ``file/write`` path —
not in any of the three places where Sessions writes remote bytes
into the local cache. So every cache materialisation looked like a
genuine user edit to the watcher.
Fix: call ``_mark_recent_self_save(remote_path)`` immediately after
each successful ``open_remote_file_into_local_cache`` call:
* ``_apply_hydrate_result`` — sidebar-placeholder hydrate finish path.
* ``_open_remote_file_for_workspace`` worker — Open Remote File +
on-demand fetch.
* ``_refresh_local_cache_after_format`` — re-download after a
successful remote formatter run.
The 5-second cooldown is the same one save echoes already use, so no
new tunable. New test
``test_refresh_local_cache_after_format_marks_self_save_for_watcher``
pins the format-refresh leg; the hydrate / on-demand legs share the
identical one-line pattern.
This is not the root cause of the intermittent macOS abort itself
(the same ``pointer being freed was not allocated`` signature
predates the watcher per the user report), but it removes a steady
stream of spurious file/write + format/lint round-trips that was
clearly increasing the FFI traffic surface area on every file open.
A planned follow-up will replace the four overlapping mechanisms
(``_RECENT_SELF_SAVE_REMOTE_PATHS``, ``_track_g_remote_ref_fingerprints``,
``_track_g_local_branch_baseline``, the ad-hoc
``_ON_DEMAND_FETCH_BYPASS`` flag) with a single origin-tagged
last-write-wins log so this whole class of "we wrote it ourselves"
filtering is unified.
1,368 tests pass; coverage 80.69% (gate=80%).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
64 lines
1.1 KiB
TOML
64 lines
1.1 KiB
TOML
[project]
|
|
name = "sessions-sublime"
|
|
version = "0.7.41"
|
|
description = "Sublime-facing Python code for Sessions."
|
|
requires-python = ">=3.8"
|
|
license = {text = "MIT"}
|
|
authors = [{name = "Myeongseon Choi", email = "key262yek@gmail.com"}]
|
|
urls = {Homepage = "https://git.teahaven.kr/sublime-rs/sessions", Repository = "https://git.teahaven.kr/sublime-rs/sessions"}
|
|
|
|
[dependency-groups]
|
|
dev = [
|
|
"pre-commit",
|
|
"pytest",
|
|
"pytest-cov",
|
|
"ruff",
|
|
]
|
|
|
|
[tool.pytest.ini_options]
|
|
testpaths = ["sublime/tests"]
|
|
|
|
[tool.coverage.run]
|
|
source = ["sublime/sessions"]
|
|
omit = ["sublime/tests/*"]
|
|
|
|
[tool.coverage.report]
|
|
show_missing = true
|
|
skip_empty = true
|
|
exclude_lines = [
|
|
"pragma: no cover",
|
|
"if TYPE_CHECKING:",
|
|
"raise NotImplementedError",
|
|
]
|
|
|
|
[tool.uv]
|
|
package = false
|
|
|
|
[tool.ruff]
|
|
line-length = 88
|
|
target-version = "py38"
|
|
|
|
[tool.ruff.lint]
|
|
select = [
|
|
"E",
|
|
"F",
|
|
"I",
|
|
"B",
|
|
"D100",
|
|
"D101",
|
|
"D102",
|
|
"D103",
|
|
"D417",
|
|
]
|
|
|
|
[tool.ruff.lint.pydocstyle]
|
|
convention = "google"
|
|
|
|
[tool.ruff.lint.per-file-ignores]
|
|
"sublime/tests/*.py" = ["D100", "D103"]
|
|
"scripts/*.py" = ["D100", "D101", "D102", "D103"]
|
|
|
|
[tool.ruff.format]
|
|
quote-style = "double"
|
|
indent-style = "space"
|