htmlgraph 0.20.1__py3-none-any.whl → 0.27.5__py3-none-any.whl

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 (304) hide show
  1. htmlgraph/.htmlgraph/.session-warning-state.json +6 -0
  2. htmlgraph/.htmlgraph/agents.json +72 -0
  3. htmlgraph/.htmlgraph/htmlgraph.db +0 -0
  4. htmlgraph/__init__.py +51 -1
  5. htmlgraph/__init__.pyi +123 -0
  6. htmlgraph/agent_detection.py +26 -10
  7. htmlgraph/agent_registry.py +2 -1
  8. htmlgraph/analytics/__init__.py +8 -1
  9. htmlgraph/analytics/cli.py +86 -20
  10. htmlgraph/analytics/cost_analyzer.py +391 -0
  11. htmlgraph/analytics/cost_monitor.py +664 -0
  12. htmlgraph/analytics/cost_reporter.py +675 -0
  13. htmlgraph/analytics/cross_session.py +617 -0
  14. htmlgraph/analytics/dependency.py +10 -6
  15. htmlgraph/analytics/pattern_learning.py +771 -0
  16. htmlgraph/analytics/session_graph.py +707 -0
  17. htmlgraph/analytics/strategic/__init__.py +80 -0
  18. htmlgraph/analytics/strategic/cost_optimizer.py +611 -0
  19. htmlgraph/analytics/strategic/pattern_detector.py +876 -0
  20. htmlgraph/analytics/strategic/preference_manager.py +709 -0
  21. htmlgraph/analytics/strategic/suggestion_engine.py +747 -0
  22. htmlgraph/analytics/work_type.py +67 -27
  23. htmlgraph/analytics_index.py +53 -20
  24. htmlgraph/api/__init__.py +3 -0
  25. htmlgraph/api/cost_alerts_websocket.py +416 -0
  26. htmlgraph/api/main.py +2498 -0
  27. htmlgraph/api/static/htmx.min.js +1 -0
  28. htmlgraph/api/static/style-redesign.css +1344 -0
  29. htmlgraph/api/static/style.css +1079 -0
  30. htmlgraph/api/templates/dashboard-redesign.html +1366 -0
  31. htmlgraph/api/templates/dashboard.html +794 -0
  32. htmlgraph/api/templates/partials/activity-feed-hierarchical.html +326 -0
  33. htmlgraph/api/templates/partials/activity-feed.html +1100 -0
  34. htmlgraph/api/templates/partials/agents-redesign.html +317 -0
  35. htmlgraph/api/templates/partials/agents.html +317 -0
  36. htmlgraph/api/templates/partials/event-traces.html +373 -0
  37. htmlgraph/api/templates/partials/features-kanban-redesign.html +509 -0
  38. htmlgraph/api/templates/partials/features.html +578 -0
  39. htmlgraph/api/templates/partials/metrics-redesign.html +346 -0
  40. htmlgraph/api/templates/partials/metrics.html +346 -0
  41. htmlgraph/api/templates/partials/orchestration-redesign.html +443 -0
  42. htmlgraph/api/templates/partials/orchestration.html +198 -0
  43. htmlgraph/api/templates/partials/spawners.html +375 -0
  44. htmlgraph/api/templates/partials/work-items.html +613 -0
  45. htmlgraph/api/websocket.py +538 -0
  46. htmlgraph/archive/__init__.py +24 -0
  47. htmlgraph/archive/bloom.py +234 -0
  48. htmlgraph/archive/fts.py +297 -0
  49. htmlgraph/archive/manager.py +583 -0
  50. htmlgraph/archive/search.py +244 -0
  51. htmlgraph/atomic_ops.py +560 -0
  52. htmlgraph/attribute_index.py +2 -1
  53. htmlgraph/bounded_paths.py +539 -0
  54. htmlgraph/builders/base.py +57 -2
  55. htmlgraph/builders/bug.py +19 -3
  56. htmlgraph/builders/chore.py +19 -3
  57. htmlgraph/builders/epic.py +19 -3
  58. htmlgraph/builders/feature.py +27 -3
  59. htmlgraph/builders/insight.py +2 -1
  60. htmlgraph/builders/metric.py +2 -1
  61. htmlgraph/builders/pattern.py +2 -1
  62. htmlgraph/builders/phase.py +19 -3
  63. htmlgraph/builders/spike.py +29 -3
  64. htmlgraph/builders/track.py +42 -1
  65. htmlgraph/cigs/__init__.py +81 -0
  66. htmlgraph/cigs/autonomy.py +385 -0
  67. htmlgraph/cigs/cost.py +475 -0
  68. htmlgraph/cigs/messages_basic.py +472 -0
  69. htmlgraph/cigs/messaging.py +365 -0
  70. htmlgraph/cigs/models.py +771 -0
  71. htmlgraph/cigs/pattern_storage.py +427 -0
  72. htmlgraph/cigs/patterns.py +503 -0
  73. htmlgraph/cigs/posttool_analyzer.py +234 -0
  74. htmlgraph/cigs/reporter.py +818 -0
  75. htmlgraph/cigs/tracker.py +317 -0
  76. htmlgraph/cli/.htmlgraph/.session-warning-state.json +6 -0
  77. htmlgraph/cli/.htmlgraph/agents.json +72 -0
  78. htmlgraph/cli/.htmlgraph/htmlgraph.db +0 -0
  79. htmlgraph/cli/__init__.py +42 -0
  80. htmlgraph/cli/__main__.py +6 -0
  81. htmlgraph/cli/analytics.py +1424 -0
  82. htmlgraph/cli/base.py +685 -0
  83. htmlgraph/cli/constants.py +206 -0
  84. htmlgraph/cli/core.py +954 -0
  85. htmlgraph/cli/main.py +147 -0
  86. htmlgraph/cli/models.py +475 -0
  87. htmlgraph/cli/templates/__init__.py +1 -0
  88. htmlgraph/cli/templates/cost_dashboard.py +399 -0
  89. htmlgraph/cli/work/__init__.py +239 -0
  90. htmlgraph/cli/work/browse.py +115 -0
  91. htmlgraph/cli/work/features.py +568 -0
  92. htmlgraph/cli/work/orchestration.py +676 -0
  93. htmlgraph/cli/work/report.py +728 -0
  94. htmlgraph/cli/work/sessions.py +466 -0
  95. htmlgraph/cli/work/snapshot.py +559 -0
  96. htmlgraph/cli/work/tracks.py +486 -0
  97. htmlgraph/cli_commands/__init__.py +1 -0
  98. htmlgraph/cli_commands/feature.py +195 -0
  99. htmlgraph/cli_framework.py +115 -0
  100. htmlgraph/collections/__init__.py +2 -0
  101. htmlgraph/collections/base.py +197 -14
  102. htmlgraph/collections/bug.py +2 -1
  103. htmlgraph/collections/chore.py +2 -1
  104. htmlgraph/collections/epic.py +2 -1
  105. htmlgraph/collections/feature.py +2 -1
  106. htmlgraph/collections/insight.py +2 -1
  107. htmlgraph/collections/metric.py +2 -1
  108. htmlgraph/collections/pattern.py +2 -1
  109. htmlgraph/collections/phase.py +2 -1
  110. htmlgraph/collections/session.py +194 -0
  111. htmlgraph/collections/spike.py +13 -2
  112. htmlgraph/collections/task_delegation.py +241 -0
  113. htmlgraph/collections/todo.py +14 -1
  114. htmlgraph/collections/traces.py +487 -0
  115. htmlgraph/config/cost_models.json +56 -0
  116. htmlgraph/config.py +190 -0
  117. htmlgraph/context_analytics.py +2 -1
  118. htmlgraph/converter.py +116 -7
  119. htmlgraph/cost_analysis/__init__.py +5 -0
  120. htmlgraph/cost_analysis/analyzer.py +438 -0
  121. htmlgraph/dashboard.html +2246 -248
  122. htmlgraph/dashboard.html.backup +6592 -0
  123. htmlgraph/dashboard.html.bak +7181 -0
  124. htmlgraph/dashboard.html.bak2 +7231 -0
  125. htmlgraph/dashboard.html.bak3 +7232 -0
  126. htmlgraph/db/__init__.py +38 -0
  127. htmlgraph/db/queries.py +790 -0
  128. htmlgraph/db/schema.py +1788 -0
  129. htmlgraph/decorators.py +317 -0
  130. htmlgraph/dependency_models.py +2 -1
  131. htmlgraph/deploy.py +26 -27
  132. htmlgraph/docs/API_REFERENCE.md +841 -0
  133. htmlgraph/docs/HTTP_API.md +750 -0
  134. htmlgraph/docs/INTEGRATION_GUIDE.md +752 -0
  135. htmlgraph/docs/ORCHESTRATION_PATTERNS.md +717 -0
  136. htmlgraph/docs/README.md +532 -0
  137. htmlgraph/docs/__init__.py +77 -0
  138. htmlgraph/docs/docs_version.py +55 -0
  139. htmlgraph/docs/metadata.py +93 -0
  140. htmlgraph/docs/migrations.py +232 -0
  141. htmlgraph/docs/template_engine.py +143 -0
  142. htmlgraph/docs/templates/_sections/cli_reference.md.j2 +52 -0
  143. htmlgraph/docs/templates/_sections/core_concepts.md.j2 +29 -0
  144. htmlgraph/docs/templates/_sections/sdk_basics.md.j2 +69 -0
  145. htmlgraph/docs/templates/base_agents.md.j2 +78 -0
  146. htmlgraph/docs/templates/example_user_override.md.j2 +47 -0
  147. htmlgraph/docs/version_check.py +163 -0
  148. htmlgraph/edge_index.py +2 -1
  149. htmlgraph/error_handler.py +544 -0
  150. htmlgraph/event_log.py +86 -37
  151. htmlgraph/event_migration.py +2 -1
  152. htmlgraph/file_watcher.py +12 -8
  153. htmlgraph/find_api.py +2 -1
  154. htmlgraph/git_events.py +67 -9
  155. htmlgraph/hooks/.htmlgraph/.session-warning-state.json +6 -0
  156. htmlgraph/hooks/.htmlgraph/agents.json +72 -0
  157. htmlgraph/hooks/.htmlgraph/index.sqlite +0 -0
  158. htmlgraph/hooks/__init__.py +8 -0
  159. htmlgraph/hooks/bootstrap.py +169 -0
  160. htmlgraph/hooks/cigs_pretool_enforcer.py +354 -0
  161. htmlgraph/hooks/concurrent_sessions.py +208 -0
  162. htmlgraph/hooks/context.py +350 -0
  163. htmlgraph/hooks/drift_handler.py +525 -0
  164. htmlgraph/hooks/event_tracker.py +790 -99
  165. htmlgraph/hooks/git_commands.py +175 -0
  166. htmlgraph/hooks/installer.py +5 -1
  167. htmlgraph/hooks/orchestrator.py +327 -76
  168. htmlgraph/hooks/orchestrator_reflector.py +31 -4
  169. htmlgraph/hooks/post_tool_use_failure.py +32 -7
  170. htmlgraph/hooks/post_tool_use_handler.py +257 -0
  171. htmlgraph/hooks/posttooluse.py +92 -19
  172. htmlgraph/hooks/pretooluse.py +527 -7
  173. htmlgraph/hooks/prompt_analyzer.py +637 -0
  174. htmlgraph/hooks/session_handler.py +668 -0
  175. htmlgraph/hooks/session_summary.py +395 -0
  176. htmlgraph/hooks/state_manager.py +504 -0
  177. htmlgraph/hooks/subagent_detection.py +202 -0
  178. htmlgraph/hooks/subagent_stop.py +369 -0
  179. htmlgraph/hooks/task_enforcer.py +99 -4
  180. htmlgraph/hooks/validator.py +212 -91
  181. htmlgraph/ids.py +2 -1
  182. htmlgraph/learning.py +125 -100
  183. htmlgraph/mcp_server.py +2 -1
  184. htmlgraph/models.py +217 -18
  185. htmlgraph/operations/README.md +62 -0
  186. htmlgraph/operations/__init__.py +79 -0
  187. htmlgraph/operations/analytics.py +339 -0
  188. htmlgraph/operations/bootstrap.py +289 -0
  189. htmlgraph/operations/events.py +244 -0
  190. htmlgraph/operations/fastapi_server.py +231 -0
  191. htmlgraph/operations/hooks.py +350 -0
  192. htmlgraph/operations/initialization.py +597 -0
  193. htmlgraph/operations/initialization.py.backup +228 -0
  194. htmlgraph/operations/server.py +303 -0
  195. htmlgraph/orchestration/__init__.py +58 -0
  196. htmlgraph/orchestration/claude_launcher.py +179 -0
  197. htmlgraph/orchestration/command_builder.py +72 -0
  198. htmlgraph/orchestration/headless_spawner.py +281 -0
  199. htmlgraph/orchestration/live_events.py +377 -0
  200. htmlgraph/orchestration/model_selection.py +327 -0
  201. htmlgraph/orchestration/plugin_manager.py +140 -0
  202. htmlgraph/orchestration/prompts.py +137 -0
  203. htmlgraph/orchestration/spawner_event_tracker.py +383 -0
  204. htmlgraph/orchestration/spawners/__init__.py +16 -0
  205. htmlgraph/orchestration/spawners/base.py +194 -0
  206. htmlgraph/orchestration/spawners/claude.py +173 -0
  207. htmlgraph/orchestration/spawners/codex.py +435 -0
  208. htmlgraph/orchestration/spawners/copilot.py +294 -0
  209. htmlgraph/orchestration/spawners/gemini.py +471 -0
  210. htmlgraph/orchestration/subprocess_runner.py +36 -0
  211. htmlgraph/{orchestration.py → orchestration/task_coordination.py} +16 -8
  212. htmlgraph/orchestration.md +563 -0
  213. htmlgraph/orchestrator-system-prompt-optimized.txt +863 -0
  214. htmlgraph/orchestrator.py +2 -1
  215. htmlgraph/orchestrator_config.py +357 -0
  216. htmlgraph/orchestrator_mode.py +115 -4
  217. htmlgraph/parallel.py +2 -1
  218. htmlgraph/parser.py +86 -6
  219. htmlgraph/path_query.py +608 -0
  220. htmlgraph/pattern_matcher.py +636 -0
  221. htmlgraph/pydantic_models.py +476 -0
  222. htmlgraph/quality_gates.py +350 -0
  223. htmlgraph/query_builder.py +2 -1
  224. htmlgraph/query_composer.py +509 -0
  225. htmlgraph/reflection.py +443 -0
  226. htmlgraph/refs.py +344 -0
  227. htmlgraph/repo_hash.py +512 -0
  228. htmlgraph/repositories/__init__.py +292 -0
  229. htmlgraph/repositories/analytics_repository.py +455 -0
  230. htmlgraph/repositories/analytics_repository_standard.py +628 -0
  231. htmlgraph/repositories/feature_repository.py +581 -0
  232. htmlgraph/repositories/feature_repository_htmlfile.py +668 -0
  233. htmlgraph/repositories/feature_repository_memory.py +607 -0
  234. htmlgraph/repositories/feature_repository_sqlite.py +858 -0
  235. htmlgraph/repositories/filter_service.py +620 -0
  236. htmlgraph/repositories/filter_service_standard.py +445 -0
  237. htmlgraph/repositories/shared_cache.py +621 -0
  238. htmlgraph/repositories/shared_cache_memory.py +395 -0
  239. htmlgraph/repositories/track_repository.py +552 -0
  240. htmlgraph/repositories/track_repository_htmlfile.py +619 -0
  241. htmlgraph/repositories/track_repository_memory.py +508 -0
  242. htmlgraph/repositories/track_repository_sqlite.py +711 -0
  243. htmlgraph/sdk/__init__.py +398 -0
  244. htmlgraph/sdk/__init__.pyi +14 -0
  245. htmlgraph/sdk/analytics/__init__.py +19 -0
  246. htmlgraph/sdk/analytics/engine.py +155 -0
  247. htmlgraph/sdk/analytics/helpers.py +178 -0
  248. htmlgraph/sdk/analytics/registry.py +109 -0
  249. htmlgraph/sdk/base.py +484 -0
  250. htmlgraph/sdk/constants.py +216 -0
  251. htmlgraph/sdk/core.pyi +308 -0
  252. htmlgraph/sdk/discovery.py +120 -0
  253. htmlgraph/sdk/help/__init__.py +12 -0
  254. htmlgraph/sdk/help/mixin.py +699 -0
  255. htmlgraph/sdk/mixins/__init__.py +15 -0
  256. htmlgraph/sdk/mixins/attribution.py +113 -0
  257. htmlgraph/sdk/mixins/mixin.py +410 -0
  258. htmlgraph/sdk/operations/__init__.py +12 -0
  259. htmlgraph/sdk/operations/mixin.py +427 -0
  260. htmlgraph/sdk/orchestration/__init__.py +17 -0
  261. htmlgraph/sdk/orchestration/coordinator.py +203 -0
  262. htmlgraph/sdk/orchestration/spawner.py +204 -0
  263. htmlgraph/sdk/planning/__init__.py +19 -0
  264. htmlgraph/sdk/planning/bottlenecks.py +93 -0
  265. htmlgraph/sdk/planning/mixin.py +211 -0
  266. htmlgraph/sdk/planning/parallel.py +186 -0
  267. htmlgraph/sdk/planning/queue.py +210 -0
  268. htmlgraph/sdk/planning/recommendations.py +87 -0
  269. htmlgraph/sdk/planning/smart_planning.py +319 -0
  270. htmlgraph/sdk/session/__init__.py +19 -0
  271. htmlgraph/sdk/session/continuity.py +57 -0
  272. htmlgraph/sdk/session/handoff.py +110 -0
  273. htmlgraph/sdk/session/info.py +309 -0
  274. htmlgraph/sdk/session/manager.py +103 -0
  275. htmlgraph/sdk/strategic/__init__.py +26 -0
  276. htmlgraph/sdk/strategic/mixin.py +563 -0
  277. htmlgraph/server.py +295 -107
  278. htmlgraph/session_hooks.py +300 -0
  279. htmlgraph/session_manager.py +285 -3
  280. htmlgraph/session_registry.py +587 -0
  281. htmlgraph/session_state.py +436 -0
  282. htmlgraph/session_warning.py +2 -1
  283. htmlgraph/sessions/__init__.py +23 -0
  284. htmlgraph/sessions/handoff.py +756 -0
  285. htmlgraph/system_prompts.py +450 -0
  286. htmlgraph/templates/orchestration-view.html +350 -0
  287. htmlgraph/track_builder.py +33 -1
  288. htmlgraph/track_manager.py +38 -0
  289. htmlgraph/transcript.py +18 -5
  290. htmlgraph/validation.py +115 -0
  291. htmlgraph/watch.py +2 -1
  292. htmlgraph/work_type_utils.py +2 -1
  293. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/dashboard.html +2246 -248
  294. {htmlgraph-0.20.1.dist-info → htmlgraph-0.27.5.dist-info}/METADATA +95 -64
  295. htmlgraph-0.27.5.dist-info/RECORD +337 -0
  296. {htmlgraph-0.20.1.dist-info → htmlgraph-0.27.5.dist-info}/entry_points.txt +1 -1
  297. htmlgraph/cli.py +0 -4839
  298. htmlgraph/sdk.py +0 -2359
  299. htmlgraph-0.20.1.dist-info/RECORD +0 -118
  300. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/styles.css +0 -0
  301. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/templates/AGENTS.md.template +0 -0
  302. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/templates/CLAUDE.md.template +0 -0
  303. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/templates/GEMINI.md.template +0 -0
  304. {htmlgraph-0.20.1.dist-info → htmlgraph-0.27.5.dist-info}/WHEEL +0 -0
@@ -0,0 +1,621 @@
1
+ """
2
+ SharedCache - Unified caching layer for all HtmlGraph operations.
3
+
4
+ Consolidates 16+ separate cache implementations.
5
+ Provides:
6
+ - Centralized cache with LRU eviction
7
+ - TTL-based expiration
8
+ - Pattern-based invalidation
9
+ - Thread-safe singleton access
10
+ - Metrics and observability
11
+
12
+ All implementations MUST pass SharedCacheComplianceTests.
13
+ """
14
+
15
+ from abc import ABC, abstractmethod
16
+ from collections.abc import Callable
17
+ from enum import Enum
18
+ from typing import TYPE_CHECKING, Any
19
+
20
+ if TYPE_CHECKING:
21
+ pass # For forward references
22
+
23
+
24
+ class CacheInvalidationPattern(Enum):
25
+ """Cache invalidation patterns."""
26
+
27
+ SINGLE_KEY = "single" # Invalidate one key
28
+ PREFIX_PATTERN = "prefix" # Invalidate keys matching prefix (e.g., "feature:*")
29
+ RESOURCE_CHANGED = "resource" # Invalidate all derived caches
30
+ CLEAR_ALL = "all" # Clear entire cache
31
+
32
+
33
+ def get_shared_cache() -> "SharedCache":
34
+ """
35
+ Get singleton instance of SharedCache.
36
+
37
+ Ensures only one cache instance across application.
38
+
39
+ Returns:
40
+ SharedCache singleton
41
+
42
+ Examples:
43
+ >>> cache = get_shared_cache()
44
+ >>> cache.set("mykey", value, ttl=3600)
45
+ >>> value = cache.get("mykey")
46
+ """
47
+ if not hasattr(get_shared_cache, "_instance"):
48
+ raise RuntimeError(
49
+ "SharedCache not initialized. Call initialize_shared_cache() first."
50
+ )
51
+ instance: SharedCache = get_shared_cache._instance # type: ignore[attr-defined]
52
+ return instance
53
+
54
+
55
+ class SharedCacheError(Exception):
56
+ """Base exception for cache operations."""
57
+
58
+ pass
59
+
60
+
61
+ class CacheKeyError(SharedCacheError):
62
+ """Raised when cache key is invalid."""
63
+
64
+ pass
65
+
66
+
67
+ class CacheCapacityError(SharedCacheError):
68
+ """Raised when cache reaches max capacity and can't evict."""
69
+
70
+ pass
71
+
72
+
73
+ class SharedCache(ABC):
74
+ """
75
+ Unified caching layer for all HtmlGraph data access.
76
+
77
+ Addresses cache fragmentation and invalidation gaps:
78
+ - 16+ separate cache implementations → 1 unified cache
79
+ - 4+ critical invalidation gaps → Centralized invalidation
80
+ - No cache coherence → Pattern-based invalidation
81
+ - No metrics → Built-in cache statistics
82
+
83
+ CONTRACT:
84
+ 1. **Coherence**: Cache always consistent with storage
85
+ 2. **Atomicity**: get/set operations are atomic
86
+ 3. **Isolation**: Concurrent access safe
87
+ 4. **Efficiency**: O(1) get/set, O(1) delete with O(n) patterns
88
+ 5. **Observability**: Metrics tracked automatically
89
+
90
+ INVALIDATION SIGNALS:
91
+ When underlying data changes, cache must be invalidated:
92
+ - Feature changed → invalidate "feature:*", "dependency:*", "analytics:*"
93
+ - Track changed → invalidate "track:*", "feature:*"
94
+ - Analytics invalidate → invalidate "dependency:*", "priority:*", "recommendation:*"
95
+
96
+ CACHE KEYS (Convention):
97
+ - "feature:{id}" - Individual feature
98
+ - "feature:list:{filter}" - Feature list with filter
99
+ - "track:{id}" - Individual track
100
+ - "dependency:{id}" - Dependency analysis
101
+ - "priority:{id}" - Priority score
102
+ - "recommendation:*" - Recommendations
103
+
104
+ PERFORMANCE:
105
+ - get(key): O(1) average
106
+ - set(key, value, ttl): O(1) average
107
+ - delete(key): O(1) average
108
+ - delete_pattern(pattern): O(n) where n = matching keys
109
+ - clear(): O(n) where n = total keys
110
+ - size(): O(1)
111
+
112
+ MEMORY MANAGEMENT:
113
+ - LRU (Least Recently Used) eviction when max_size exceeded
114
+ - TTL-based automatic expiration
115
+ - Configurable max cache size
116
+
117
+ THREAD SAFETY:
118
+ - Thread-safe for concurrent reads
119
+ - Thread-safe for concurrent writes (serialized)
120
+ - No deadlock risk
121
+ - Atomic operations (no partial states visible)
122
+ """
123
+
124
+ # ===== GET OPERATIONS =====
125
+
126
+ @abstractmethod
127
+ def get(self, key: str) -> Any | None:
128
+ """
129
+ Retrieve cached value by key.
130
+
131
+ Returns None if key not found or expired.
132
+ Updates LRU tracking (moves item to "most recently used").
133
+
134
+ Args:
135
+ key: Cache key (e.g., "feature:feat-001")
136
+
137
+ Returns:
138
+ Cached value if found and not expired, None otherwise
139
+
140
+ Raises:
141
+ CacheKeyError: If key format is invalid
142
+
143
+ Performance: O(1) average case
144
+
145
+ Examples:
146
+ >>> cache = get_shared_cache()
147
+ >>> value = cache.get("feature:feat-001")
148
+ >>> if value is None:
149
+ ... # Recompute and cache
150
+ ... value = load_feature("feat-001")
151
+ ... cache.set("feature:feat-001", value)
152
+ """
153
+ ...
154
+
155
+ @abstractmethod
156
+ def get_or_compute(
157
+ self, key: str, compute_fn: Callable[[], Any], ttl: int | None = None
158
+ ) -> Any:
159
+ """
160
+ Get cached value or compute and cache if missing.
161
+
162
+ Avoids cache-miss pattern boilerplate:
163
+ cache.get() → check None → compute → cache.set()
164
+
165
+ Args:
166
+ key: Cache key
167
+ compute_fn: Function taking no args, returns value to cache
168
+ ttl: Time-to-live in seconds (None = use default)
169
+
170
+ Returns:
171
+ Cached or newly computed value
172
+
173
+ Performance: O(1) if cached, O(?) if computed
174
+
175
+ Examples:
176
+ >>> def load_deps():
177
+ ... return analyze_dependencies("feat-001")
178
+ >>> deps = cache.get_or_compute("dependency:feat-001", load_deps)
179
+ """
180
+ ...
181
+
182
+ @abstractmethod
183
+ def exists(self, key: str) -> bool:
184
+ """
185
+ Check if key exists in cache.
186
+
187
+ Does NOT count as access for LRU purposes.
188
+
189
+ Args:
190
+ key: Cache key to check
191
+
192
+ Returns:
193
+ True if key exists and not expired, False otherwise
194
+
195
+ Performance: O(1)
196
+
197
+ Examples:
198
+ >>> if cache.exists("feature:feat-001"):
199
+ ... print("Already cached")
200
+ """
201
+ ...
202
+
203
+ # ===== SET OPERATIONS =====
204
+
205
+ @abstractmethod
206
+ def set(self, key: str, value: Any, ttl: int | None = None) -> None:
207
+ """
208
+ Cache a value with optional time-to-live.
209
+
210
+ If key exists, updates value and TTL.
211
+ If cache at max capacity, evicts LRU item.
212
+
213
+ Args:
214
+ key: Cache key (e.g., "feature:feat-001")
215
+ value: Value to cache (must be serializable)
216
+ ttl: Time-to-live in seconds (None = default)
217
+
218
+ Raises:
219
+ CacheKeyError: If key format invalid
220
+ CacheCapacityError: If can't make space
221
+
222
+ Performance: O(1) average case
223
+
224
+ Examples:
225
+ >>> feature = load_feature("feat-001")
226
+ >>> cache.set("feature:feat-001", feature, ttl=3600) # 1 hour
227
+ >>> cache.set("priority:feat-001", 0.95) # Use default TTL
228
+ """
229
+ ...
230
+
231
+ @abstractmethod
232
+ def set_many(self, items: dict[str, Any], ttl: int | None = None) -> None:
233
+ """
234
+ Cache multiple key-value pairs at once.
235
+
236
+ More efficient than multiple set() calls.
237
+
238
+ Args:
239
+ items: Dict of key -> value to cache
240
+ ttl: TTL for all items (None = default)
241
+
242
+ Performance: O(k) where k = items count
243
+
244
+ Examples:
245
+ >>> cache.set_many({
246
+ ... "feature:feat-001": feature1,
247
+ ... "feature:feat-002": feature2,
248
+ ... "feature:feat-003": feature3,
249
+ ... }, ttl=3600)
250
+ """
251
+ ...
252
+
253
+ # ===== DELETE OPERATIONS =====
254
+
255
+ @abstractmethod
256
+ def delete(self, key: str) -> bool:
257
+ """
258
+ Delete single cached value.
259
+
260
+ Args:
261
+ key: Cache key to delete
262
+
263
+ Returns:
264
+ True if deleted, False if not found
265
+
266
+ Performance: O(1)
267
+
268
+ Examples:
269
+ >>> cache.delete("feature:feat-001")
270
+ """
271
+ ...
272
+
273
+ @abstractmethod
274
+ def delete_pattern(self, pattern: str) -> int:
275
+ """
276
+ Delete all cached values matching pattern.
277
+
278
+ Patterns use prefix matching:
279
+ - "feature:*" → deletes all keys starting with "feature:"
280
+ - "dependency:feat-*" → deletes "dependency:feat-001", etc.
281
+
282
+ Args:
283
+ pattern: Prefix pattern to match (e.g., "feature:*")
284
+
285
+ Returns:
286
+ Number of keys deleted
287
+
288
+ Performance: O(n) where n = matching keys
289
+
290
+ Examples:
291
+ >>> # Invalidate all feature cache when features change
292
+ >>> count = cache.delete_pattern("feature:*")
293
+ >>> print(f"Invalidated {count} cached features")
294
+
295
+ >>> # Invalidate all analytics when dependencies change
296
+ >>> cache.delete_pattern("dependency:*")
297
+ >>> cache.delete_pattern("priority:*")
298
+ >>> cache.delete_pattern("recommendation:*")
299
+ """
300
+ ...
301
+
302
+ @abstractmethod
303
+ def clear(self) -> int:
304
+ """
305
+ Clear all cached values.
306
+
307
+ Args: None
308
+
309
+ Returns:
310
+ Number of items cleared
311
+
312
+ Examples:
313
+ >>> cache.clear()
314
+ """
315
+ ...
316
+
317
+ # ===== BATCH OPERATIONS =====
318
+
319
+ @abstractmethod
320
+ def get_many(self, keys: list[str]) -> dict[str, Any]:
321
+ """
322
+ Retrieve multiple cached values at once.
323
+
324
+ Returns only found keys (missing keys skipped).
325
+
326
+ Args:
327
+ keys: List of cache keys
328
+
329
+ Returns:
330
+ Dict of key -> value for found items
331
+
332
+ Performance: O(k) where k = keys count
333
+
334
+ Examples:
335
+ >>> values = cache.get_many([
336
+ ... "feature:feat-001",
337
+ ... "feature:feat-002",
338
+ ... "feature:feat-003",
339
+ ... ])
340
+ >>> for key, value in values.items():
341
+ ... print(f"{key}: {value}")
342
+ """
343
+ ...
344
+
345
+ @abstractmethod
346
+ def delete_many(self, keys: list[str]) -> int:
347
+ """
348
+ Delete multiple cached values at once.
349
+
350
+ Args:
351
+ keys: List of cache keys to delete
352
+
353
+ Returns:
354
+ Number of keys successfully deleted
355
+
356
+ Performance: O(k) where k = keys count
357
+
358
+ Examples:
359
+ >>> count = cache.delete_many([
360
+ ... "feature:feat-001",
361
+ ... "feature:feat-002",
362
+ ... ])
363
+ """
364
+ ...
365
+
366
+ # ===== INVALIDATION HELPERS =====
367
+
368
+ @abstractmethod
369
+ def invalidate_feature(self, feature_id: str) -> None:
370
+ """
371
+ Invalidate all caches related to a feature.
372
+
373
+ Convenience method that invalidates:
374
+ - Feature data: "feature:{id}"
375
+ - Feature lists: "feature:list:*"
376
+ - Dependencies: "dependency:{id}" + "dependency:*:blocking_for_{id}"
377
+ - Analytics: "priority:{id}", "recommendation:*"
378
+
379
+ Args:
380
+ feature_id: Feature ID to invalidate
381
+
382
+ Examples:
383
+ >>> # When feature changes
384
+ >>> cache.invalidate_feature("feat-001")
385
+ """
386
+ ...
387
+
388
+ @abstractmethod
389
+ def invalidate_track(self, track_id: str) -> None:
390
+ """
391
+ Invalidate all caches related to a track.
392
+
393
+ Invalidates:
394
+ - Track data: "track:{id}"
395
+ - Track features: "track:{id}:features"
396
+ - Analytics: cascades to feature invalidation
397
+
398
+ Args:
399
+ track_id: Track ID to invalidate
400
+
401
+ Examples:
402
+ >>> cache.invalidate_track("track-planning")
403
+ """
404
+ ...
405
+
406
+ @abstractmethod
407
+ def invalidate_analytics(self) -> None:
408
+ """
409
+ Invalidate all analytics caches.
410
+
411
+ Used when dependencies change or major data update occurs.
412
+
413
+ Invalidates:
414
+ - "dependency:*"
415
+ - "priority:*"
416
+ - "recommendation:*"
417
+ - "critical_path:*"
418
+ - "blocking:*"
419
+
420
+ Examples:
421
+ >>> # When dependencies added/removed
422
+ >>> cache.invalidate_analytics()
423
+ """
424
+ ...
425
+
426
+ # ===== OBSERVABILITY =====
427
+
428
+ @abstractmethod
429
+ def size(self) -> int:
430
+ """
431
+ Get current number of cached items.
432
+
433
+ Returns:
434
+ Count of items in cache
435
+
436
+ Performance: O(1)
437
+
438
+ Examples:
439
+ >>> print(f"Cache has {cache.size()} items")
440
+ """
441
+ ...
442
+
443
+ @abstractmethod
444
+ def stats(self) -> dict[str, Any]:
445
+ """
446
+ Get detailed cache statistics.
447
+
448
+ Returns dict with:
449
+ - hits: Total cache hits
450
+ - misses: Total cache misses
451
+ - hit_rate: Hit rate (0-1)
452
+ - evictions: Number of items evicted
453
+ - size: Current item count
454
+ - capacity: Max item count
455
+ - memory_bytes: Approximate memory usage
456
+ - avg_load_ms: Average load time for computed values
457
+
458
+ Returns:
459
+ Dict with cache metrics
460
+
461
+ Performance: O(1)
462
+
463
+ Examples:
464
+ >>> metrics = cache.stats()
465
+ >>> print(f"Hit rate: {metrics['hit_rate']:.1%}")
466
+ >>> print(f"Evictions: {metrics['evictions']}")
467
+ >>> print(f"Memory: {metrics['memory_bytes'] / 1024:.1f} KB")
468
+ """
469
+ ...
470
+
471
+ @abstractmethod
472
+ def reset_stats(self) -> None:
473
+ """
474
+ Reset cache statistics to zero.
475
+
476
+ Clears hit/miss counters but keeps cached data.
477
+
478
+ Examples:
479
+ >>> cache.reset_stats()
480
+ """
481
+ ...
482
+
483
+ # ===== CONFIGURATION =====
484
+
485
+ @abstractmethod
486
+ def configure(
487
+ self,
488
+ max_size: int | None = None,
489
+ default_ttl: int | None = None,
490
+ metrics_enabled: bool | None = None,
491
+ ) -> None:
492
+ """
493
+ Configure cache behavior.
494
+
495
+ Args:
496
+ max_size: Max cached items (default: 1000)
497
+ default_ttl: Default time-to-live in seconds (default: 3600)
498
+ metrics_enabled: Track stats automatically (default: True)
499
+
500
+ Examples:
501
+ >>> cache.configure(max_size=5000, default_ttl=7200)
502
+ """
503
+ ...
504
+
505
+ @abstractmethod
506
+ def is_configured(self) -> bool:
507
+ """
508
+ Check if cache is properly configured.
509
+
510
+ Returns:
511
+ True if cache is ready to use
512
+
513
+ Examples:
514
+ >>> if not cache.is_configured():
515
+ ... cache.configure(max_size=1000)
516
+ """
517
+ ...
518
+
519
+ # ===== DEBUG / UTILITY =====
520
+
521
+ @abstractmethod
522
+ def debug_info(self) -> dict[str, Any]:
523
+ """
524
+ Get detailed debug information.
525
+
526
+ Includes:
527
+ - All cached keys
528
+ - TTL for each key
529
+ - Access count for each key
530
+ - LRU order
531
+ - Memory per item
532
+
533
+ Returns:
534
+ Dict with detailed cache state
535
+
536
+ Examples:
537
+ >>> info = cache.debug_info()
538
+ >>> for key in info['keys']:
539
+ ... print(f"{key}: {info['memory'][key]} bytes")
540
+ """
541
+ ...
542
+
543
+ @abstractmethod
544
+ def validate_integrity(self) -> bool:
545
+ """
546
+ Validate cache internal consistency.
547
+
548
+ Checks:
549
+ - No expired items accessible
550
+ - LRU order correct
551
+ - Size tracking accurate
552
+ - All items parseable
553
+
554
+ Returns:
555
+ True if cache valid, False if corrupted
556
+
557
+ Examples:
558
+ >>> if not cache.validate_integrity():
559
+ ... cache.clear() # Rebuild
560
+ ... cache.reload()
561
+ """
562
+ ...
563
+
564
+ # ===== SINGLETON MANAGEMENT =====
565
+
566
+ @classmethod
567
+ @abstractmethod
568
+ def initialize(
569
+ cls, max_size: int = 1000, default_ttl: int = 3600, metrics_enabled: bool = True
570
+ ) -> "SharedCache":
571
+ """
572
+ Initialize singleton cache instance.
573
+
574
+ Must be called once at application startup.
575
+
576
+ Args:
577
+ max_size: Max cached items
578
+ default_ttl: Default time-to-live
579
+ metrics_enabled: Enable statistics tracking
580
+
581
+ Returns:
582
+ Initialized SharedCache singleton
583
+
584
+ Examples:
585
+ >>> cache = SharedCache.initialize(max_size=5000)
586
+ >>> # Later, get singleton:
587
+ >>> cache = get_shared_cache()
588
+ """
589
+ ...
590
+
591
+ @classmethod
592
+ @abstractmethod
593
+ def get_instance(cls) -> "SharedCache":
594
+ """
595
+ Get singleton instance.
596
+
597
+ Must call initialize() once before calling this.
598
+
599
+ Returns:
600
+ SharedCache singleton
601
+
602
+ Raises:
603
+ RuntimeError: If not initialized
604
+
605
+ Examples:
606
+ >>> cache = SharedCache.get_instance()
607
+ """
608
+ ...
609
+
610
+ @classmethod
611
+ @abstractmethod
612
+ def reset_instance(cls) -> None:
613
+ """
614
+ Reset singleton (for testing only).
615
+
616
+ Clears instance and forces re-initialization next time.
617
+
618
+ Examples:
619
+ >>> SharedCache.reset_instance() # Testing only
620
+ """
621
+ ...