htmlgraph 0.9.3__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 (331) 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 +173 -17
  5. htmlgraph/__init__.pyi +123 -0
  6. htmlgraph/agent_detection.py +127 -0
  7. htmlgraph/agent_registry.py +45 -30
  8. htmlgraph/agents.py +160 -107
  9. htmlgraph/analytics/__init__.py +9 -2
  10. htmlgraph/analytics/cli.py +190 -51
  11. htmlgraph/analytics/cost_analyzer.py +391 -0
  12. htmlgraph/analytics/cost_monitor.py +664 -0
  13. htmlgraph/analytics/cost_reporter.py +675 -0
  14. htmlgraph/analytics/cross_session.py +617 -0
  15. htmlgraph/analytics/dependency.py +192 -100
  16. htmlgraph/analytics/pattern_learning.py +771 -0
  17. htmlgraph/analytics/session_graph.py +707 -0
  18. htmlgraph/analytics/strategic/__init__.py +80 -0
  19. htmlgraph/analytics/strategic/cost_optimizer.py +611 -0
  20. htmlgraph/analytics/strategic/pattern_detector.py +876 -0
  21. htmlgraph/analytics/strategic/preference_manager.py +709 -0
  22. htmlgraph/analytics/strategic/suggestion_engine.py +747 -0
  23. htmlgraph/analytics/work_type.py +190 -14
  24. htmlgraph/analytics_index.py +135 -51
  25. htmlgraph/api/__init__.py +3 -0
  26. htmlgraph/api/cost_alerts_websocket.py +416 -0
  27. htmlgraph/api/main.py +2498 -0
  28. htmlgraph/api/static/htmx.min.js +1 -0
  29. htmlgraph/api/static/style-redesign.css +1344 -0
  30. htmlgraph/api/static/style.css +1079 -0
  31. htmlgraph/api/templates/dashboard-redesign.html +1366 -0
  32. htmlgraph/api/templates/dashboard.html +794 -0
  33. htmlgraph/api/templates/partials/activity-feed-hierarchical.html +326 -0
  34. htmlgraph/api/templates/partials/activity-feed.html +1100 -0
  35. htmlgraph/api/templates/partials/agents-redesign.html +317 -0
  36. htmlgraph/api/templates/partials/agents.html +317 -0
  37. htmlgraph/api/templates/partials/event-traces.html +373 -0
  38. htmlgraph/api/templates/partials/features-kanban-redesign.html +509 -0
  39. htmlgraph/api/templates/partials/features.html +578 -0
  40. htmlgraph/api/templates/partials/metrics-redesign.html +346 -0
  41. htmlgraph/api/templates/partials/metrics.html +346 -0
  42. htmlgraph/api/templates/partials/orchestration-redesign.html +443 -0
  43. htmlgraph/api/templates/partials/orchestration.html +198 -0
  44. htmlgraph/api/templates/partials/spawners.html +375 -0
  45. htmlgraph/api/templates/partials/work-items.html +613 -0
  46. htmlgraph/api/websocket.py +538 -0
  47. htmlgraph/archive/__init__.py +24 -0
  48. htmlgraph/archive/bloom.py +234 -0
  49. htmlgraph/archive/fts.py +297 -0
  50. htmlgraph/archive/manager.py +583 -0
  51. htmlgraph/archive/search.py +244 -0
  52. htmlgraph/atomic_ops.py +560 -0
  53. htmlgraph/attribute_index.py +208 -0
  54. htmlgraph/bounded_paths.py +539 -0
  55. htmlgraph/builders/__init__.py +14 -0
  56. htmlgraph/builders/base.py +118 -29
  57. htmlgraph/builders/bug.py +150 -0
  58. htmlgraph/builders/chore.py +119 -0
  59. htmlgraph/builders/epic.py +150 -0
  60. htmlgraph/builders/feature.py +31 -6
  61. htmlgraph/builders/insight.py +195 -0
  62. htmlgraph/builders/metric.py +217 -0
  63. htmlgraph/builders/pattern.py +202 -0
  64. htmlgraph/builders/phase.py +162 -0
  65. htmlgraph/builders/spike.py +52 -19
  66. htmlgraph/builders/track.py +148 -72
  67. htmlgraph/cigs/__init__.py +81 -0
  68. htmlgraph/cigs/autonomy.py +385 -0
  69. htmlgraph/cigs/cost.py +475 -0
  70. htmlgraph/cigs/messages_basic.py +472 -0
  71. htmlgraph/cigs/messaging.py +365 -0
  72. htmlgraph/cigs/models.py +771 -0
  73. htmlgraph/cigs/pattern_storage.py +427 -0
  74. htmlgraph/cigs/patterns.py +503 -0
  75. htmlgraph/cigs/posttool_analyzer.py +234 -0
  76. htmlgraph/cigs/reporter.py +818 -0
  77. htmlgraph/cigs/tracker.py +317 -0
  78. htmlgraph/cli/.htmlgraph/.session-warning-state.json +6 -0
  79. htmlgraph/cli/.htmlgraph/agents.json +72 -0
  80. htmlgraph/cli/.htmlgraph/htmlgraph.db +0 -0
  81. htmlgraph/cli/__init__.py +42 -0
  82. htmlgraph/cli/__main__.py +6 -0
  83. htmlgraph/cli/analytics.py +1424 -0
  84. htmlgraph/cli/base.py +685 -0
  85. htmlgraph/cli/constants.py +206 -0
  86. htmlgraph/cli/core.py +954 -0
  87. htmlgraph/cli/main.py +147 -0
  88. htmlgraph/cli/models.py +475 -0
  89. htmlgraph/cli/templates/__init__.py +1 -0
  90. htmlgraph/cli/templates/cost_dashboard.py +399 -0
  91. htmlgraph/cli/work/__init__.py +239 -0
  92. htmlgraph/cli/work/browse.py +115 -0
  93. htmlgraph/cli/work/features.py +568 -0
  94. htmlgraph/cli/work/orchestration.py +676 -0
  95. htmlgraph/cli/work/report.py +728 -0
  96. htmlgraph/cli/work/sessions.py +466 -0
  97. htmlgraph/cli/work/snapshot.py +559 -0
  98. htmlgraph/cli/work/tracks.py +486 -0
  99. htmlgraph/cli_commands/__init__.py +1 -0
  100. htmlgraph/cli_commands/feature.py +195 -0
  101. htmlgraph/cli_framework.py +115 -0
  102. htmlgraph/collections/__init__.py +18 -0
  103. htmlgraph/collections/base.py +415 -98
  104. htmlgraph/collections/bug.py +53 -0
  105. htmlgraph/collections/chore.py +53 -0
  106. htmlgraph/collections/epic.py +53 -0
  107. htmlgraph/collections/feature.py +12 -26
  108. htmlgraph/collections/insight.py +100 -0
  109. htmlgraph/collections/metric.py +92 -0
  110. htmlgraph/collections/pattern.py +97 -0
  111. htmlgraph/collections/phase.py +53 -0
  112. htmlgraph/collections/session.py +194 -0
  113. htmlgraph/collections/spike.py +56 -16
  114. htmlgraph/collections/task_delegation.py +241 -0
  115. htmlgraph/collections/todo.py +511 -0
  116. htmlgraph/collections/traces.py +487 -0
  117. htmlgraph/config/cost_models.json +56 -0
  118. htmlgraph/config.py +190 -0
  119. htmlgraph/context_analytics.py +344 -0
  120. htmlgraph/converter.py +216 -28
  121. htmlgraph/cost_analysis/__init__.py +5 -0
  122. htmlgraph/cost_analysis/analyzer.py +438 -0
  123. htmlgraph/dashboard.html +2406 -307
  124. htmlgraph/dashboard.html.backup +6592 -0
  125. htmlgraph/dashboard.html.bak +7181 -0
  126. htmlgraph/dashboard.html.bak2 +7231 -0
  127. htmlgraph/dashboard.html.bak3 +7232 -0
  128. htmlgraph/db/__init__.py +38 -0
  129. htmlgraph/db/queries.py +790 -0
  130. htmlgraph/db/schema.py +1788 -0
  131. htmlgraph/decorators.py +317 -0
  132. htmlgraph/dependency_models.py +19 -2
  133. htmlgraph/deploy.py +142 -125
  134. htmlgraph/deployment_models.py +474 -0
  135. htmlgraph/docs/API_REFERENCE.md +841 -0
  136. htmlgraph/docs/HTTP_API.md +750 -0
  137. htmlgraph/docs/INTEGRATION_GUIDE.md +752 -0
  138. htmlgraph/docs/ORCHESTRATION_PATTERNS.md +717 -0
  139. htmlgraph/docs/README.md +532 -0
  140. htmlgraph/docs/__init__.py +77 -0
  141. htmlgraph/docs/docs_version.py +55 -0
  142. htmlgraph/docs/metadata.py +93 -0
  143. htmlgraph/docs/migrations.py +232 -0
  144. htmlgraph/docs/template_engine.py +143 -0
  145. htmlgraph/docs/templates/_sections/cli_reference.md.j2 +52 -0
  146. htmlgraph/docs/templates/_sections/core_concepts.md.j2 +29 -0
  147. htmlgraph/docs/templates/_sections/sdk_basics.md.j2 +69 -0
  148. htmlgraph/docs/templates/base_agents.md.j2 +78 -0
  149. htmlgraph/docs/templates/example_user_override.md.j2 +47 -0
  150. htmlgraph/docs/version_check.py +163 -0
  151. htmlgraph/edge_index.py +182 -27
  152. htmlgraph/error_handler.py +544 -0
  153. htmlgraph/event_log.py +100 -52
  154. htmlgraph/event_migration.py +13 -4
  155. htmlgraph/exceptions.py +49 -0
  156. htmlgraph/file_watcher.py +101 -28
  157. htmlgraph/find_api.py +75 -63
  158. htmlgraph/git_events.py +145 -63
  159. htmlgraph/graph.py +1122 -106
  160. htmlgraph/hooks/.htmlgraph/.session-warning-state.json +6 -0
  161. htmlgraph/hooks/.htmlgraph/agents.json +72 -0
  162. htmlgraph/hooks/.htmlgraph/index.sqlite +0 -0
  163. htmlgraph/hooks/__init__.py +45 -0
  164. htmlgraph/hooks/bootstrap.py +169 -0
  165. htmlgraph/hooks/cigs_pretool_enforcer.py +354 -0
  166. htmlgraph/hooks/concurrent_sessions.py +208 -0
  167. htmlgraph/hooks/context.py +350 -0
  168. htmlgraph/hooks/drift_handler.py +525 -0
  169. htmlgraph/hooks/event_tracker.py +1314 -0
  170. htmlgraph/hooks/git_commands.py +175 -0
  171. htmlgraph/hooks/hooks-config.example.json +12 -0
  172. htmlgraph/hooks/installer.py +343 -0
  173. htmlgraph/hooks/orchestrator.py +674 -0
  174. htmlgraph/hooks/orchestrator_reflector.py +223 -0
  175. htmlgraph/hooks/post-checkout.sh +28 -0
  176. htmlgraph/hooks/post-commit.sh +24 -0
  177. htmlgraph/hooks/post-merge.sh +26 -0
  178. htmlgraph/hooks/post_tool_use_failure.py +273 -0
  179. htmlgraph/hooks/post_tool_use_handler.py +257 -0
  180. htmlgraph/hooks/posttooluse.py +408 -0
  181. htmlgraph/hooks/pre-commit.sh +94 -0
  182. htmlgraph/hooks/pre-push.sh +28 -0
  183. htmlgraph/hooks/pretooluse.py +819 -0
  184. htmlgraph/hooks/prompt_analyzer.py +637 -0
  185. htmlgraph/hooks/session_handler.py +668 -0
  186. htmlgraph/hooks/session_summary.py +395 -0
  187. htmlgraph/hooks/state_manager.py +504 -0
  188. htmlgraph/hooks/subagent_detection.py +202 -0
  189. htmlgraph/hooks/subagent_stop.py +369 -0
  190. htmlgraph/hooks/task_enforcer.py +255 -0
  191. htmlgraph/hooks/task_validator.py +177 -0
  192. htmlgraph/hooks/validator.py +628 -0
  193. htmlgraph/ids.py +41 -27
  194. htmlgraph/index.d.ts +286 -0
  195. htmlgraph/learning.py +767 -0
  196. htmlgraph/mcp_server.py +69 -23
  197. htmlgraph/models.py +1586 -87
  198. htmlgraph/operations/README.md +62 -0
  199. htmlgraph/operations/__init__.py +79 -0
  200. htmlgraph/operations/analytics.py +339 -0
  201. htmlgraph/operations/bootstrap.py +289 -0
  202. htmlgraph/operations/events.py +244 -0
  203. htmlgraph/operations/fastapi_server.py +231 -0
  204. htmlgraph/operations/hooks.py +350 -0
  205. htmlgraph/operations/initialization.py +597 -0
  206. htmlgraph/operations/initialization.py.backup +228 -0
  207. htmlgraph/operations/server.py +303 -0
  208. htmlgraph/orchestration/__init__.py +58 -0
  209. htmlgraph/orchestration/claude_launcher.py +179 -0
  210. htmlgraph/orchestration/command_builder.py +72 -0
  211. htmlgraph/orchestration/headless_spawner.py +281 -0
  212. htmlgraph/orchestration/live_events.py +377 -0
  213. htmlgraph/orchestration/model_selection.py +327 -0
  214. htmlgraph/orchestration/plugin_manager.py +140 -0
  215. htmlgraph/orchestration/prompts.py +137 -0
  216. htmlgraph/orchestration/spawner_event_tracker.py +383 -0
  217. htmlgraph/orchestration/spawners/__init__.py +16 -0
  218. htmlgraph/orchestration/spawners/base.py +194 -0
  219. htmlgraph/orchestration/spawners/claude.py +173 -0
  220. htmlgraph/orchestration/spawners/codex.py +435 -0
  221. htmlgraph/orchestration/spawners/copilot.py +294 -0
  222. htmlgraph/orchestration/spawners/gemini.py +471 -0
  223. htmlgraph/orchestration/subprocess_runner.py +36 -0
  224. htmlgraph/orchestration/task_coordination.py +343 -0
  225. htmlgraph/orchestration.md +563 -0
  226. htmlgraph/orchestrator-system-prompt-optimized.txt +863 -0
  227. htmlgraph/orchestrator.py +669 -0
  228. htmlgraph/orchestrator_config.py +357 -0
  229. htmlgraph/orchestrator_mode.py +328 -0
  230. htmlgraph/orchestrator_validator.py +133 -0
  231. htmlgraph/parallel.py +646 -0
  232. htmlgraph/parser.py +160 -35
  233. htmlgraph/path_query.py +608 -0
  234. htmlgraph/pattern_matcher.py +636 -0
  235. htmlgraph/planning.py +147 -52
  236. htmlgraph/pydantic_models.py +476 -0
  237. htmlgraph/quality_gates.py +350 -0
  238. htmlgraph/query_builder.py +109 -72
  239. htmlgraph/query_composer.py +509 -0
  240. htmlgraph/reflection.py +443 -0
  241. htmlgraph/refs.py +344 -0
  242. htmlgraph/repo_hash.py +512 -0
  243. htmlgraph/repositories/__init__.py +292 -0
  244. htmlgraph/repositories/analytics_repository.py +455 -0
  245. htmlgraph/repositories/analytics_repository_standard.py +628 -0
  246. htmlgraph/repositories/feature_repository.py +581 -0
  247. htmlgraph/repositories/feature_repository_htmlfile.py +668 -0
  248. htmlgraph/repositories/feature_repository_memory.py +607 -0
  249. htmlgraph/repositories/feature_repository_sqlite.py +858 -0
  250. htmlgraph/repositories/filter_service.py +620 -0
  251. htmlgraph/repositories/filter_service_standard.py +445 -0
  252. htmlgraph/repositories/shared_cache.py +621 -0
  253. htmlgraph/repositories/shared_cache_memory.py +395 -0
  254. htmlgraph/repositories/track_repository.py +552 -0
  255. htmlgraph/repositories/track_repository_htmlfile.py +619 -0
  256. htmlgraph/repositories/track_repository_memory.py +508 -0
  257. htmlgraph/repositories/track_repository_sqlite.py +711 -0
  258. htmlgraph/routing.py +8 -19
  259. htmlgraph/scripts/deploy.py +1 -2
  260. htmlgraph/sdk/__init__.py +398 -0
  261. htmlgraph/sdk/__init__.pyi +14 -0
  262. htmlgraph/sdk/analytics/__init__.py +19 -0
  263. htmlgraph/sdk/analytics/engine.py +155 -0
  264. htmlgraph/sdk/analytics/helpers.py +178 -0
  265. htmlgraph/sdk/analytics/registry.py +109 -0
  266. htmlgraph/sdk/base.py +484 -0
  267. htmlgraph/sdk/constants.py +216 -0
  268. htmlgraph/sdk/core.pyi +308 -0
  269. htmlgraph/sdk/discovery.py +120 -0
  270. htmlgraph/sdk/help/__init__.py +12 -0
  271. htmlgraph/sdk/help/mixin.py +699 -0
  272. htmlgraph/sdk/mixins/__init__.py +15 -0
  273. htmlgraph/sdk/mixins/attribution.py +113 -0
  274. htmlgraph/sdk/mixins/mixin.py +410 -0
  275. htmlgraph/sdk/operations/__init__.py +12 -0
  276. htmlgraph/sdk/operations/mixin.py +427 -0
  277. htmlgraph/sdk/orchestration/__init__.py +17 -0
  278. htmlgraph/sdk/orchestration/coordinator.py +203 -0
  279. htmlgraph/sdk/orchestration/spawner.py +204 -0
  280. htmlgraph/sdk/planning/__init__.py +19 -0
  281. htmlgraph/sdk/planning/bottlenecks.py +93 -0
  282. htmlgraph/sdk/planning/mixin.py +211 -0
  283. htmlgraph/sdk/planning/parallel.py +186 -0
  284. htmlgraph/sdk/planning/queue.py +210 -0
  285. htmlgraph/sdk/planning/recommendations.py +87 -0
  286. htmlgraph/sdk/planning/smart_planning.py +319 -0
  287. htmlgraph/sdk/session/__init__.py +19 -0
  288. htmlgraph/sdk/session/continuity.py +57 -0
  289. htmlgraph/sdk/session/handoff.py +110 -0
  290. htmlgraph/sdk/session/info.py +309 -0
  291. htmlgraph/sdk/session/manager.py +103 -0
  292. htmlgraph/sdk/strategic/__init__.py +26 -0
  293. htmlgraph/sdk/strategic/mixin.py +563 -0
  294. htmlgraph/server.py +685 -180
  295. htmlgraph/services/__init__.py +10 -0
  296. htmlgraph/services/claiming.py +199 -0
  297. htmlgraph/session_hooks.py +300 -0
  298. htmlgraph/session_manager.py +1392 -175
  299. htmlgraph/session_registry.py +587 -0
  300. htmlgraph/session_state.py +436 -0
  301. htmlgraph/session_warning.py +201 -0
  302. htmlgraph/sessions/__init__.py +23 -0
  303. htmlgraph/sessions/handoff.py +756 -0
  304. htmlgraph/setup.py +34 -17
  305. htmlgraph/spike_index.py +143 -0
  306. htmlgraph/sync_docs.py +12 -15
  307. htmlgraph/system_prompts.py +450 -0
  308. htmlgraph/templates/AGENTS.md.template +366 -0
  309. htmlgraph/templates/CLAUDE.md.template +97 -0
  310. htmlgraph/templates/GEMINI.md.template +87 -0
  311. htmlgraph/templates/orchestration-view.html +350 -0
  312. htmlgraph/track_builder.py +146 -15
  313. htmlgraph/track_manager.py +69 -21
  314. htmlgraph/transcript.py +890 -0
  315. htmlgraph/transcript_analytics.py +699 -0
  316. htmlgraph/types.py +323 -0
  317. htmlgraph/validation.py +115 -0
  318. htmlgraph/watch.py +8 -5
  319. htmlgraph/work_type_utils.py +3 -2
  320. {htmlgraph-0.9.3.data → htmlgraph-0.27.5.data}/data/htmlgraph/dashboard.html +2406 -307
  321. htmlgraph-0.27.5.data/data/htmlgraph/templates/AGENTS.md.template +366 -0
  322. htmlgraph-0.27.5.data/data/htmlgraph/templates/CLAUDE.md.template +97 -0
  323. htmlgraph-0.27.5.data/data/htmlgraph/templates/GEMINI.md.template +87 -0
  324. {htmlgraph-0.9.3.dist-info → htmlgraph-0.27.5.dist-info}/METADATA +97 -64
  325. htmlgraph-0.27.5.dist-info/RECORD +337 -0
  326. {htmlgraph-0.9.3.dist-info → htmlgraph-0.27.5.dist-info}/entry_points.txt +1 -1
  327. htmlgraph/cli.py +0 -2688
  328. htmlgraph/sdk.py +0 -709
  329. htmlgraph-0.9.3.dist-info/RECORD +0 -61
  330. {htmlgraph-0.9.3.data → htmlgraph-0.27.5.data}/data/htmlgraph/styles.css +0 -0
  331. {htmlgraph-0.9.3.dist-info → htmlgraph-0.27.5.dist-info}/WHEEL +0 -0
@@ -0,0 +1,309 @@
1
+ """
2
+ Session info mixin for SDK - session start info and active work tracking.
3
+
4
+ Provides optimized methods for session context gathering.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import os
10
+ import subprocess
11
+ from typing import TYPE_CHECKING, Any
12
+
13
+ if TYPE_CHECKING:
14
+ from pathlib import Path
15
+
16
+ from htmlgraph.session_manager import SessionManager
17
+ from htmlgraph.types import ActiveWorkItem, SessionStartInfo
18
+
19
+
20
+ class SessionInfoMixin:
21
+ """
22
+ Mixin providing session info and active work methods to SDK.
23
+
24
+ Provides optimized methods for gathering session context in single calls.
25
+ Requires SDK instance with _directory, _agent_id, session_manager attributes.
26
+ """
27
+
28
+ _directory: Path
29
+ _agent_id: str | None
30
+ session_manager: SessionManager
31
+
32
+ def get_session_start_info(
33
+ self,
34
+ include_git_log: bool = True,
35
+ git_log_count: int = 5,
36
+ analytics_top_n: int = 3,
37
+ analytics_max_agents: int = 3,
38
+ ) -> SessionStartInfo:
39
+ """
40
+ Get comprehensive session start information in a single call.
41
+
42
+ Consolidates all information needed for session start into one method,
43
+ reducing context usage from 6+ tool calls to 1.
44
+
45
+ Args:
46
+ include_git_log: Include recent git commits (default: True)
47
+ git_log_count: Number of recent commits to include (default: 5)
48
+ analytics_top_n: Number of bottlenecks/recommendations (default: 3)
49
+ analytics_max_agents: Max agents for parallel work analysis (default: 3)
50
+
51
+ Returns:
52
+ Dict with comprehensive session start context:
53
+ - status: Project status (nodes, collections, WIP)
54
+ - active_work: Current active work item (if any)
55
+ - features: List of features with status
56
+ - sessions: Recent sessions
57
+ - git_log: Recent commits (if include_git_log=True)
58
+ - analytics: Strategic insights (bottlenecks, recommendations, parallel)
59
+
60
+ Note:
61
+ Returns empty dict {} if session context unavailable.
62
+ Always check for expected keys before accessing.
63
+
64
+ Example:
65
+ >>> sdk = SDK(agent="claude")
66
+ >>> info = sdk.get_session_start_info()
67
+ >>> logger.info(f"Project: {info['status']['total_nodes']} nodes")
68
+ >>> logger.info(f"WIP: {info['status']['in_progress_count']}")
69
+ >>> if info.get('active_work'):
70
+ ... logger.info(f"Active: {info['active_work']['title']}")
71
+ >>> for bn in info['analytics']['bottlenecks']:
72
+ ... logger.info(f"Bottleneck: {bn['title']}")
73
+ """
74
+ result: dict[str, Any] = {}
75
+
76
+ # 1. Project status
77
+ result["status"] = self.get_status() # type: ignore[attr-defined]
78
+
79
+ # 2. Active work item (validation status) - always include, even if None
80
+ result["active_work"] = self.get_active_work_item()
81
+
82
+ # 3. Features list (simplified)
83
+ features_list: list[dict[str, object]] = []
84
+ for feature in self.features.all(): # type: ignore[attr-defined]
85
+ features_list.append(
86
+ {
87
+ "id": feature.id,
88
+ "title": feature.title,
89
+ "status": feature.status,
90
+ "priority": feature.priority,
91
+ "steps_total": len(feature.steps),
92
+ "steps_completed": sum(1 for s in feature.steps if s.completed),
93
+ }
94
+ )
95
+ result["features"] = features_list
96
+
97
+ # 4. Sessions list (recent 20)
98
+ sessions_list: list[dict[str, Any]] = []
99
+ for session in self.sessions.all()[:20]: # type: ignore[attr-defined]
100
+ sessions_list.append(
101
+ {
102
+ "id": session.id,
103
+ "status": session.status,
104
+ "agent": session.properties.get("agent", "unknown"),
105
+ "event_count": session.properties.get("event_count", 0),
106
+ "started": session.created.isoformat()
107
+ if hasattr(session, "created")
108
+ else None,
109
+ }
110
+ )
111
+ result["sessions"] = sessions_list
112
+
113
+ # 5. Git log (if requested)
114
+ if include_git_log:
115
+ try:
116
+ git_result = subprocess.run(
117
+ ["git", "log", "--oneline", f"-{git_log_count}"],
118
+ capture_output=True,
119
+ text=True,
120
+ check=True,
121
+ cwd=self._directory.parent,
122
+ )
123
+ git_lines: list[str] = git_result.stdout.strip().split("\n")
124
+ result["git_log"] = git_lines
125
+ except (subprocess.CalledProcessError, FileNotFoundError):
126
+ empty_list: list[str] = []
127
+ result["git_log"] = empty_list
128
+
129
+ # 6. Strategic analytics
130
+ result["analytics"] = {
131
+ "bottlenecks": self.find_bottlenecks(top_n=analytics_top_n), # type: ignore[attr-defined]
132
+ "recommendations": self.recommend_next_work(agent_count=analytics_top_n), # type: ignore[attr-defined]
133
+ "parallel": self.get_parallel_work(max_agents=analytics_max_agents), # type: ignore[attr-defined]
134
+ }
135
+
136
+ return result # type: ignore[return-value]
137
+
138
+ def get_active_work_item(
139
+ self,
140
+ agent: str | None = None,
141
+ filter_by_agent: bool = False,
142
+ work_types: list[str] | None = None,
143
+ ) -> ActiveWorkItem | None:
144
+ """
145
+ Get the currently active work item (in-progress status).
146
+
147
+ This is used by the PreToolUse validation hook to check if code changes
148
+ have an active work item for attribution.
149
+
150
+ Args:
151
+ agent: Agent ID for filtering (optional)
152
+ filter_by_agent: If True, filter by agent. If False (default), return any active work item
153
+ work_types: Work item types to check (defaults to all: features, bugs, spikes, chores, epics)
154
+
155
+ Returns:
156
+ Dict with work item details or None if no active work item found:
157
+ - id: Work item ID
158
+ - title: Work item title
159
+ - type: Work item type (feature, bug, spike, chore, epic)
160
+ - status: Should be "in-progress"
161
+ - agent: Assigned agent
162
+ - steps_total: Total steps
163
+ - steps_completed: Completed steps
164
+ - auto_generated: (spikes only) True if auto-generated spike
165
+ - spike_subtype: (spikes only) "session-init" or "transition"
166
+
167
+ Example:
168
+ >>> sdk = SDK(agent="claude")
169
+ >>> # Get any active work item
170
+ >>> active = sdk.get_active_work_item()
171
+ >>> if active:
172
+ ... logger.info(f"Working on: {active['title']}")
173
+ ...
174
+ >>> # Get only this agent's active work item
175
+ >>> active = sdk.get_active_work_item(filter_by_agent=True)
176
+ """
177
+ # Default to all work item types
178
+ if work_types is None:
179
+ work_types = ["features", "bugs", "spikes", "chores", "epics"]
180
+
181
+ # Search across all work item types
182
+ # Separate real work items from auto-generated spikes
183
+ real_work_items: list[dict[str, Any]] = []
184
+ auto_spikes: list[dict[str, Any]] = []
185
+
186
+ for work_type in work_types:
187
+ collection = getattr(self, work_type, None)
188
+ if collection is None:
189
+ continue
190
+
191
+ # Query for in-progress items
192
+ in_progress = collection.where(status="in-progress")
193
+
194
+ for item in in_progress:
195
+ # Filter by agent if requested
196
+ if filter_by_agent:
197
+ agent_id = agent or self._agent_id
198
+ if agent_id and hasattr(item, "agent_assigned"):
199
+ if item.agent_assigned != agent_id:
200
+ continue
201
+
202
+ item_dict: dict[str, Any] = {
203
+ "id": item.id,
204
+ "title": item.title,
205
+ "type": item.type,
206
+ "status": item.status,
207
+ "agent": getattr(item, "agent_assigned", None),
208
+ "steps_total": len(item.steps) if hasattr(item, "steps") else 0,
209
+ "steps_completed": sum(1 for s in item.steps if s.completed)
210
+ if hasattr(item, "steps")
211
+ else 0,
212
+ }
213
+
214
+ # Add spike-specific fields for auto-spike detection
215
+ if item.type == "spike":
216
+ item_dict["auto_generated"] = getattr(item, "auto_generated", False)
217
+ item_dict["spike_subtype"] = getattr(item, "spike_subtype", None)
218
+
219
+ # Separate auto-spikes from real work
220
+ # Auto-spikes are temporary tracking items (session-init, transition, conversation-init)
221
+ is_auto_spike = item_dict["auto_generated"] and item_dict[
222
+ "spike_subtype"
223
+ ] in ("session-init", "transition", "conversation-init")
224
+
225
+ if is_auto_spike:
226
+ auto_spikes.append(item_dict)
227
+ else:
228
+ # Real user-created spike
229
+ real_work_items.append(item_dict)
230
+ else:
231
+ # Features, bugs, chores, epics are always real work
232
+ real_work_items.append(item_dict)
233
+
234
+ # Prioritize real work items over auto-spikes
235
+ # Auto-spikes should only show if there's NO other active work item
236
+ if real_work_items:
237
+ return real_work_items[0] # type: ignore[return-value]
238
+
239
+ if auto_spikes:
240
+ return auto_spikes[0] # type: ignore[return-value]
241
+
242
+ return None
243
+
244
+ def track_activity(
245
+ self,
246
+ tool: str,
247
+ summary: str,
248
+ file_paths: list[str] | None = None,
249
+ success: bool = True,
250
+ feature_id: str | None = None,
251
+ session_id: str | None = None,
252
+ parent_activity_id: str | None = None,
253
+ payload: dict[str, Any] | None = None,
254
+ ) -> Any:
255
+ """
256
+ Track an activity in the current or specified session.
257
+
258
+ Args:
259
+ tool: Tool name (Edit, Bash, Read, etc.)
260
+ summary: Human-readable summary of the activity
261
+ file_paths: Files involved in this activity
262
+ success: Whether the tool call succeeded
263
+ feature_id: Explicit feature ID (skips attribution if provided)
264
+ session_id: Session ID (defaults to parent session if available, then active session)
265
+ parent_activity_id: ID of parent activity (e.g., Skill/Task invocation)
266
+ payload: Optional rich payload data
267
+
268
+ Returns:
269
+ Created ActivityEntry with attribution
270
+
271
+ Example:
272
+ >>> sdk = SDK(agent="claude")
273
+ >>> entry = sdk.track_activity(
274
+ ... tool="CustomTool",
275
+ ... summary="Performed custom analysis",
276
+ ... file_paths=["src/main.py"],
277
+ ... success=True
278
+ ... )
279
+ >>> logger.info(f"Tracked: [{entry.tool}] {entry.summary}")
280
+ """
281
+ # Determine target session: explicit parameter > parent_session > active > none
282
+ if not session_id:
283
+ # Priority 1: Parent session (explicitly provided or from env var)
284
+ if hasattr(self, "_parent_session") and self._parent_session: # type: ignore[attr-defined]
285
+ session_id = self._parent_session # type: ignore[attr-defined]
286
+ else:
287
+ # Priority 2: Active session for this agent
288
+ active = self.session_manager.get_active_session(agent=self._agent_id)
289
+ if active:
290
+ session_id = active.id
291
+ else:
292
+ raise ValueError(
293
+ "No active session. Start one with sdk.start_session()"
294
+ )
295
+
296
+ # Get parent activity ID from environment if not provided
297
+ if not parent_activity_id:
298
+ parent_activity_id = os.getenv("HTMLGRAPH_PARENT_ACTIVITY")
299
+
300
+ return self.session_manager.track_activity(
301
+ session_id=session_id,
302
+ tool=tool,
303
+ summary=summary,
304
+ file_paths=file_paths,
305
+ success=success,
306
+ feature_id=feature_id,
307
+ parent_activity_id=parent_activity_id,
308
+ payload=payload,
309
+ )
@@ -0,0 +1,103 @@
1
+ """
2
+ SessionManager accessor and session creation/validation for SDK.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import TYPE_CHECKING, Any
8
+
9
+ if TYPE_CHECKING:
10
+ from htmlgraph.session_manager import SessionManager
11
+
12
+
13
+ class SessionManagerMixin:
14
+ """
15
+ Provides SessionManager accessor and session lifecycle operations.
16
+
17
+ Attributes accessed by mixins:
18
+ session_manager: SessionManager instance
19
+ _db: HtmlGraphDB instance
20
+ _agent_id: Agent identifier
21
+ _parent_session: Parent session ID (if nested)
22
+ """
23
+
24
+ session_manager: SessionManager
25
+
26
+ def _ensure_session_exists(
27
+ self, session_id: str, parent_event_id: str | None = None
28
+ ) -> None:
29
+ """
30
+ Create a session record if it doesn't exist.
31
+
32
+ Args:
33
+ session_id: Session ID to ensure exists
34
+ parent_event_id: Event that spawned this session (optional)
35
+ """
36
+ if not self._db.connection: # type: ignore[attr-defined]
37
+ self._db.connect() # type: ignore[attr-defined]
38
+
39
+ cursor = self._db.connection.cursor() # type: ignore[attr-defined,union-attr]
40
+ cursor.execute(
41
+ "SELECT COUNT(*) FROM sessions WHERE session_id = ?", (session_id,)
42
+ )
43
+ exists = cursor.fetchone()[0] > 0
44
+
45
+ if not exists:
46
+ # Create session record
47
+ self._db.insert_session( # type: ignore[attr-defined]
48
+ session_id=session_id,
49
+ agent_assigned=self._agent_id, # type: ignore[attr-defined]
50
+ is_subagent=self._parent_session is not None, # type: ignore[attr-defined]
51
+ parent_session_id=self._parent_session, # type: ignore[attr-defined]
52
+ parent_event_id=parent_event_id,
53
+ )
54
+
55
+ def start_session(
56
+ self,
57
+ session_id: str | None = None,
58
+ title: str | None = None,
59
+ agent: str | None = None,
60
+ ) -> Any:
61
+ """
62
+ Start a new session.
63
+
64
+ Args:
65
+ session_id: Optional session ID
66
+ title: Optional session title
67
+ agent: Optional agent override (defaults to SDK agent)
68
+
69
+ Returns:
70
+ New Session instance
71
+ """
72
+ return self.session_manager.start_session(
73
+ session_id=session_id,
74
+ agent=agent or self._agent_id or "cli", # type: ignore[attr-defined]
75
+ title=title,
76
+ parent_session_id=self._parent_session, # type: ignore[attr-defined]
77
+ )
78
+
79
+ def end_session(
80
+ self,
81
+ session_id: str,
82
+ handoff_notes: str | None = None,
83
+ recommended_next: str | None = None,
84
+ blockers: list[str] | None = None,
85
+ ) -> Any:
86
+ """
87
+ End a session.
88
+
89
+ Args:
90
+ session_id: Session ID to end
91
+ handoff_notes: Optional handoff notes
92
+ recommended_next: Optional recommendations
93
+ blockers: Optional blockers
94
+
95
+ Returns:
96
+ Ended Session instance
97
+ """
98
+ return self.session_manager.end_session(
99
+ session_id=session_id,
100
+ handoff_notes=handoff_notes,
101
+ recommended_next=recommended_next,
102
+ blockers=blockers,
103
+ )
@@ -0,0 +1,26 @@
1
+ """
2
+ Strategic Analytics SDK Integration - Phase 3
3
+
4
+ Provides SDK mixin for accessing strategic analytics capabilities:
5
+ - Pattern detection and retrieval
6
+ - Suggestion generation
7
+ - Preference management
8
+ - Cost optimization
9
+
10
+ Usage:
11
+ from htmlgraph import SDK
12
+
13
+ sdk = SDK(agent="claude")
14
+
15
+ # Access strategic analytics
16
+ patterns = sdk.strategic.detect_patterns()
17
+ suggestions = sdk.strategic.get_suggestions()
18
+ preferences = sdk.strategic.get_preferences()
19
+
20
+ # Record feedback
21
+ sdk.strategic.record_feedback(suggestion_id, accepted=True)
22
+ """
23
+
24
+ from htmlgraph.sdk.strategic.mixin import StrategicAnalyticsMixin
25
+
26
+ __all__ = ["StrategicAnalyticsMixin"]