synap-git 2.1.3__tar.gz → 2.1.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. {synap_git-2.1.3 → synap_git-2.1.5}/CHANGELOG.md +10 -0
  2. {synap_git-2.1.3 → synap_git-2.1.5}/PKG-INFO +1 -1
  3. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/__init__.py +1 -1
  4. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/cli/main.py +3 -0
  5. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/indexer/daemon.py +16 -8
  6. {synap_git-2.1.3 → synap_git-2.1.5}/.gitignore +0 -0
  7. {synap_git-2.1.3 → synap_git-2.1.5}/.synap.example/README.md +0 -0
  8. {synap_git-2.1.3 → synap_git-2.1.5}/LICENSE.md +0 -0
  9. {synap_git-2.1.3 → synap_git-2.1.5}/README.md +0 -0
  10. {synap_git-2.1.3 → synap_git-2.1.5}/pyproject.toml +0 -0
  11. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/api/__init__.py +0 -0
  12. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/api/app.py +0 -0
  13. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/api/static/index.html +0 -0
  14. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/cli/__init__.py +0 -0
  15. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/cli/__main__.py +0 -0
  16. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/config.py +0 -0
  17. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/diagnostics/__init__.py +0 -0
  18. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/diagnostics/logger.py +0 -0
  19. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/diagnostics/tracing.py +0 -0
  20. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/embeddings/__init__.py +0 -0
  21. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/git/__init__.py +0 -0
  22. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/git/state.py +0 -0
  23. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/indexer/__init__.py +0 -0
  24. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/indexer/engine.py +0 -0
  25. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/indexer/scanner.py +0 -0
  26. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/indexer/wiki.py +0 -0
  27. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/mcp/__init__.py +0 -0
  28. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/mcp/server.py +0 -0
  29. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/parser/__init__.py +0 -0
  30. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/parser/registry.py +0 -0
  31. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/provider/anthropic.py +0 -0
  32. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/provider/base.py +0 -0
  33. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/provider/factory.py +0 -0
  34. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/provider/gemini.py +0 -0
  35. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/provider/ollama.py +0 -0
  36. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/provider/openai.py +0 -0
  37. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/provider/openrouter.py +0 -0
  38. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/py.typed +0 -0
  39. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/retrieval/__init__.py +0 -0
  40. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/retrieval/engine.py +0 -0
  41. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/retrieval/memory.py +0 -0
  42. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/storage/__init__.py +0 -0
  43. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/storage/sqlite.py +0 -0
  44. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/utils/__init__.py +0 -0
  45. {synap_git-2.1.3 → synap_git-2.1.5}/src/synap_git/utils/serialization.py +0 -0
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.1.5] - 2026-06-11
9
+
10
+ ### Refactored
11
+ - **Daemon Teardown**: Refactored the forceful SIGTERM daemon teardown logic to safely toggle via `force_exit=True` rather than a blanket catch-all. Makes programmatic `daemon.stop()` safer without blocking terminal UI interactions.
12
+
13
+ ## [2.1.4] - 2026-06-11
14
+
15
+ ### Fixed
16
+ - **Graceful Shutdown Hang**: Fixed an edge case where `synap stop` would time out and forcefully terminate due to `concurrent.futures` threads preventing immediate python process exit when handling embeddings. The CLI now safely flushes databases and exits instantly.
17
+
8
18
  ## [2.1.3] - 2026-06-11
9
19
 
10
20
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synap-git
3
- Version: 2.1.3
3
+ Version: 2.1.5
4
4
  Summary: Persistent structural context infrastructure for AI coding agents.
5
5
  Project-URL: Homepage, https://github.com/saahilpal/synap-git
6
6
  Project-URL: Repository, https://github.com/saahilpal/synap-git
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "2.1.3"
5
+ __version__ = "2.1.5"
@@ -718,6 +718,9 @@ def daemon_run(
718
718
  daemon = RuntimeDaemon(settings)
719
719
  asyncio.run(daemon.start())
720
720
 
721
+ # Forceful process exit to prevent atexit thread-join blocking
722
+ os._exit(0)
723
+
721
724
 
722
725
  @app.command()
723
726
  def stop(
@@ -100,14 +100,10 @@ class RuntimeDaemon:
100
100
  self._running = False
101
101
  self.logger.info("daemon_shutting_down")
102
102
  self._ui_server.should_exit = True
103
-
104
- from synap_git.config import RuntimeProfile
105
-
106
- if self.settings.profile == RuntimeProfile.TEST:
107
- self._ui_server.force_exit = True
103
+ self._ui_server.force_exit = True # Always force exit since daemon is terminating
108
104
 
109
105
  # Allow uvicorn and wiki worker to shut down gracefully
110
- timeout = self.settings.shutdown_timeout_seconds
106
+ timeout = 0.5
111
107
  self.logger.info("daemon_waiting_for_tasks", timeout=timeout)
112
108
 
113
109
  tasks = [server_task, wiki_worker_task]
@@ -127,11 +123,23 @@ class RuntimeDaemon:
127
123
  self._delete_heartbeat()
128
124
  self.logger.info("daemon_stopped")
129
125
 
130
- def stop(self) -> None:
126
+ def stop(self, force_exit: bool = False) -> None:
131
127
  if not self._stop_event.is_set():
132
128
  self.logger.info("daemon_stop_requested")
133
129
  self._stop_event.set()
134
130
 
131
+ # Force immediate cleanup and exit to avoid thread-join blocking
132
+ if force_exit:
133
+ try:
134
+ self.runtime.shutdown()
135
+ self._delete_heartbeat()
136
+ except Exception:
137
+ pass
138
+
139
+ import os
140
+
141
+ os._exit(0)
142
+
135
143
  def health(self) -> DaemonHealth:
136
144
  status = self.runtime.status()
137
145
  return DaemonHealth(
@@ -320,7 +328,7 @@ class RuntimeDaemon:
320
328
  loop = asyncio.get_running_loop()
321
329
  for sig in (signal.SIGINT, signal.SIGTERM):
322
330
  try:
323
- loop.add_signal_handler(sig, self.stop)
331
+ loop.add_signal_handler(sig, lambda: self.stop(force_exit=True))
324
332
  except NotImplementedError:
325
333
  continue
326
334
 
File without changes
File without changes
File without changes
File without changes