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,395 @@
1
+ import logging
2
+
3
+ logger = logging.getLogger(__name__)
4
+
5
+ """
6
+ Session Summary Module - CIGS Integration
7
+
8
+ Generates comprehensive session summaries with CIGS analytics at session end.
9
+ This module is loaded by the Stop hook.
10
+ """
11
+
12
+ import json
13
+ import os
14
+ import subprocess
15
+ import sys
16
+ from pathlib import Path
17
+ from typing import Any
18
+
19
+
20
+ def _resolve_project_dir(cwd: str | None = None) -> str:
21
+ """Resolve project directory (git root or cwd)."""
22
+ env_dir = os.environ.get("CLAUDE_PROJECT_DIR")
23
+ if env_dir:
24
+ return env_dir
25
+ start_dir = cwd or os.getcwd()
26
+ try:
27
+ result = subprocess.run(
28
+ ["git", "rev-parse", "--show-toplevel"],
29
+ capture_output=True,
30
+ text=True,
31
+ cwd=start_dir,
32
+ timeout=5,
33
+ )
34
+ if result.returncode == 0:
35
+ return result.stdout.strip()
36
+ except Exception:
37
+ pass
38
+ return start_dir
39
+
40
+
41
+ def _bootstrap_pythonpath(project_dir: str) -> None:
42
+ """Add local src/python to PYTHONPATH for CIGS imports."""
43
+ repo_src = Path(project_dir) / "src" / "python"
44
+ if repo_src.exists():
45
+ sys.path.insert(0, str(repo_src))
46
+
47
+
48
+ # Try to import CIGS modules
49
+ try:
50
+ project_dir_for_import = _resolve_project_dir()
51
+ _bootstrap_pythonpath(project_dir_for_import)
52
+
53
+ from htmlgraph.cigs.autonomy import AutonomyRecommender
54
+ from htmlgraph.cigs.cost import CostCalculator
55
+ from htmlgraph.cigs.patterns import PatternDetector
56
+ from htmlgraph.cigs.tracker import ViolationTracker
57
+
58
+ CIGS_AVAILABLE = True
59
+ except Exception:
60
+ CIGS_AVAILABLE = False
61
+
62
+
63
+ class CIGSSessionSummarizer:
64
+ """
65
+ Generate comprehensive session summary with CIGS analytics.
66
+
67
+ Implements section 2.5 of CIGS design document:
68
+ - Load session violations from ViolationTracker
69
+ - Analyze session patterns using PatternDetector
70
+ - Calculate session costs
71
+ - Generate autonomy recommendation for next session
72
+ - Build comprehensive session summary
73
+ - Persist summary to .htmlgraph/cigs/session-summaries/{session_id}.json
74
+ """
75
+
76
+ def __init__(self, graph_dir: Path):
77
+ """Initialize session summarizer.
78
+
79
+ Args:
80
+ graph_dir: Path to .htmlgraph directory
81
+ """
82
+ if not CIGS_AVAILABLE:
83
+ raise RuntimeError("CIGS modules not available")
84
+
85
+ self.graph_dir = Path(graph_dir)
86
+ self.cigs_dir = self.graph_dir / "cigs"
87
+ self.summaries_dir = self.cigs_dir / "session-summaries"
88
+
89
+ # Ensure directories exist
90
+ self.summaries_dir.mkdir(parents=True, exist_ok=True)
91
+
92
+ # Initialize CIGS components
93
+ self.tracker = ViolationTracker(graph_dir)
94
+ self.pattern_detector = PatternDetector()
95
+ self.cost_calculator = CostCalculator()
96
+ self.autonomy_recommender = AutonomyRecommender()
97
+
98
+ def summarize(self, session_id: str | None = None) -> dict:
99
+ """
100
+ Generate comprehensive session summary.
101
+
102
+ Args:
103
+ session_id: Session ID (defaults to current/active session)
104
+
105
+ Returns:
106
+ Hook response with session summary
107
+ """
108
+ # Get session violations
109
+ violations = self.tracker.get_session_violations(session_id)
110
+
111
+ # Detect patterns from recent violations
112
+ patterns = self._detect_patterns(violations.violations)
113
+
114
+ # Calculate cost metrics
115
+ costs = self._calculate_costs(violations)
116
+
117
+ # Generate autonomy recommendation for next session
118
+ autonomy_rec = self.autonomy_recommender.recommend(
119
+ violations=violations,
120
+ patterns=patterns,
121
+ compliance_history=self._get_compliance_history(),
122
+ )
123
+
124
+ # Build summary text
125
+ summary_text = self._build_summary_text(
126
+ violations, patterns, costs, autonomy_rec
127
+ )
128
+
129
+ # Persist summary for future reference
130
+ self._persist_summary(
131
+ violations.session_id,
132
+ {
133
+ "session_id": violations.session_id,
134
+ "violations": violations.to_dict(),
135
+ "patterns": [p.to_dict() for p in patterns],
136
+ "costs": costs,
137
+ "autonomy_recommendation": autonomy_rec.to_dict(),
138
+ },
139
+ )
140
+
141
+ return {
142
+ "hookSpecificOutput": {
143
+ "hookEventName": "Stop",
144
+ "additionalContext": summary_text,
145
+ }
146
+ }
147
+
148
+ def _detect_patterns(self, violation_records: list) -> list:
149
+ """
150
+ Detect behavioral patterns from violation records.
151
+
152
+ Args:
153
+ violation_records: List of ViolationRecord instances
154
+
155
+ Returns:
156
+ List of detected PatternRecord instances
157
+ """
158
+ if not violation_records:
159
+ return []
160
+
161
+ # Convert violations to tool history format
162
+ history: list[dict[str, Any]] = []
163
+ for v in violation_records:
164
+ history.append(
165
+ {
166
+ "tool": v.tool,
167
+ "command": v.tool_params.get("command", ""),
168
+ "file_path": v.tool_params.get("file_path", ""),
169
+ "prompt": v.tool_params.get("prompt", ""),
170
+ "timestamp": v.timestamp,
171
+ }
172
+ )
173
+
174
+ # Detect all patterns
175
+ patterns = self.pattern_detector.detect_all_patterns(history)
176
+ return patterns # type: ignore[no-any-return]
177
+
178
+ def _calculate_costs(self, violations: Any) -> dict:
179
+ """
180
+ Calculate cost metrics from violations.
181
+
182
+ Args:
183
+ violations: SessionViolationSummary
184
+
185
+ Returns:
186
+ Dictionary with cost metrics
187
+ """
188
+ total_tokens = sum(v.actual_cost_tokens for v in violations.violations)
189
+ optimal_tokens = sum(v.optimal_cost_tokens for v in violations.violations)
190
+ waste_tokens = violations.total_waste_tokens
191
+
192
+ if total_tokens > 0:
193
+ waste_percentage = (waste_tokens / total_tokens) * 100
194
+ efficiency_score = (optimal_tokens / total_tokens) * 100
195
+ else:
196
+ waste_percentage = 0.0
197
+ efficiency_score = 100.0
198
+
199
+ return {
200
+ "total_tokens": total_tokens,
201
+ "optimal_tokens": optimal_tokens,
202
+ "waste_tokens": waste_tokens,
203
+ "waste_percentage": waste_percentage,
204
+ "efficiency_score": efficiency_score,
205
+ }
206
+
207
+ def _get_compliance_history(self) -> list[float]:
208
+ """
209
+ Get compliance history from last 5 sessions.
210
+
211
+ Returns:
212
+ List of compliance rates (0.0-1.0)
213
+ """
214
+ # Get recent violations (last 5 sessions)
215
+ recent = self.tracker.get_recent_violations(sessions=5)
216
+
217
+ # Group by session and calculate compliance rates
218
+ sessions: dict[str, list] = {}
219
+ for v in recent:
220
+ if v.session_id not in sessions:
221
+ sessions[v.session_id] = []
222
+ sessions[v.session_id].append(v)
223
+
224
+ # Calculate compliance rate per session
225
+ compliance_rates = []
226
+ for session_id, session_violations in sessions.items():
227
+ total_violations = len(session_violations)
228
+ # Compliance rate: 1.0 = no violations, decreases with more violations
229
+ compliance_rate = max(0.0, 1.0 - (total_violations / 5.0))
230
+ compliance_rates.append(compliance_rate)
231
+
232
+ return compliance_rates[-5:] if compliance_rates else [1.0]
233
+
234
+ def _build_summary_text(
235
+ self, violations: Any, patterns: Any, costs: Any, autonomy_rec: Any
236
+ ) -> str:
237
+ """
238
+ Build human-readable session summary.
239
+
240
+ Args:
241
+ violations: SessionViolationSummary
242
+ patterns: List of PatternRecord instances
243
+ costs: Cost metrics dictionary
244
+ autonomy_rec: AutonomyLevel recommendation
245
+
246
+ Returns:
247
+ Formatted markdown summary
248
+ """
249
+ # Compliance rate
250
+ compliance_pct = violations.compliance_rate * 100
251
+
252
+ # Circuit breaker status
253
+ breaker_status = (
254
+ "🚨 TRIGGERED" if violations.circuit_breaker_triggered else "✅ OK"
255
+ )
256
+
257
+ # Format violations by type
258
+ violations_detail = ""
259
+ if violations.violations_by_type:
260
+ for vtype, count in violations.violations_by_type.items():
261
+ violations_detail += f" - {vtype}: {count}\n"
262
+ else:
263
+ violations_detail = " - No violations detected\n"
264
+
265
+ # Format detected patterns
266
+ patterns_text = self._format_patterns(patterns)
267
+
268
+ # Format anti-patterns
269
+ anti_patterns_text = self._format_anti_patterns(patterns)
270
+
271
+ # Build summary
272
+ summary = f"""## 📊 CIGS Session Summary
273
+
274
+ ### Delegation Metrics
275
+ - **Compliance Rate:** {compliance_pct:.0f}%
276
+ - **Violations:** {violations.total_violations} (circuit breaker threshold: 3)
277
+ - **Circuit Breaker:** {breaker_status}
278
+
279
+ ### Violation Breakdown
280
+ {violations_detail}
281
+
282
+ ### Cost Analysis
283
+ - **Total Context Used:** {costs["total_tokens"]} tokens
284
+ - **Estimated Waste:** {costs["waste_tokens"]} tokens ({costs["waste_percentage"]:.1f}%)
285
+ - **Optimal Path Cost:** {costs["optimal_tokens"]} tokens
286
+ - **Efficiency Score:** {costs["efficiency_score"]:.0f}/100
287
+
288
+ {patterns_text}
289
+
290
+ {anti_patterns_text}
291
+
292
+ ### Autonomy Recommendation
293
+ **Next Session Level:** {autonomy_rec.level.upper()}
294
+ **Messaging Intensity:** {autonomy_rec.messaging_intensity}
295
+ **Enforcement Mode:** {autonomy_rec.enforcement_mode}
296
+
297
+ **Reason:** {autonomy_rec.reason}
298
+
299
+ ### Learning Applied
300
+ - ✅ Violation patterns added to detection model
301
+ - ✅ Cost predictions updated with actual session data
302
+ - ✅ Messaging intensity adjusted for next session: {autonomy_rec.messaging_intensity}
303
+ - ✅ Session summary persisted to `.htmlgraph/cigs/session-summaries/`
304
+
305
+ ---
306
+
307
+ **Next Steps:**
308
+ 1. Review detected anti-patterns (if any) and adjust workflow
309
+ 2. Your autonomy level for next session: **{autonomy_rec.level.upper()}**
310
+ 3. Guidance intensity: **{autonomy_rec.messaging_intensity}**
311
+ """
312
+
313
+ return summary
314
+
315
+ def _format_patterns(self, patterns: list) -> str:
316
+ """Format detected good patterns."""
317
+ good_patterns = [p for p in patterns if p.pattern_type == "good-pattern"]
318
+
319
+ if not good_patterns:
320
+ return "### Detected Patterns\n- No significant patterns detected"
321
+
322
+ text = "### Detected Patterns\n"
323
+ for p in good_patterns:
324
+ text += f"- ✅ **{p.name}**: {p.description}\n"
325
+ text += f" - Occurrences: {p.occurrence_count}\n"
326
+
327
+ return text
328
+
329
+ def _format_anti_patterns(self, patterns: list) -> str:
330
+ """Format detected anti-patterns with remediation."""
331
+ anti_patterns = [p for p in patterns if p.pattern_type == "anti-pattern"]
332
+
333
+ if not anti_patterns:
334
+ return "### Anti-Patterns Identified\n- ✅ No anti-patterns detected"
335
+
336
+ text = "### Anti-Patterns Identified\n"
337
+ for p in anti_patterns:
338
+ text += f"- ⚠️ **{p.name}**: {p.description}\n"
339
+ text += f" - Occurrences: {p.occurrence_count}\n"
340
+ if p.correct_approach:
341
+ text += f" - **Correct Approach:** {p.correct_approach}\n"
342
+ if p.delegation_suggestion:
343
+ text += f" - **Suggested Delegation:** {p.delegation_suggestion}\n"
344
+
345
+ return text
346
+
347
+ def _persist_summary(self, session_id: str, summary_data: dict) -> None:
348
+ """
349
+ Persist session summary to file for future reference.
350
+
351
+ Args:
352
+ session_id: Session identifier
353
+ summary_data: Summary dictionary to persist
354
+ """
355
+ try:
356
+ summary_file = self.summaries_dir / f"{session_id}.json"
357
+ with open(summary_file, "w") as f:
358
+ json.dump(summary_data, f, indent=2, default=str)
359
+ except Exception as e:
360
+ logger.warning(f"Warning: Failed to persist summary: {e}")
361
+
362
+
363
+ def main() -> None:
364
+ """Hook entry point for script wrapper."""
365
+ # Check if tracking is disabled
366
+ if os.environ.get("HTMLGRAPH_DISABLE_TRACKING") == "1":
367
+ print(json.dumps({"continue": True}))
368
+ sys.exit(0)
369
+
370
+ try:
371
+ hook_input = json.load(sys.stdin)
372
+ except json.JSONDecodeError:
373
+ hook_input = {}
374
+
375
+ session_id = hook_input.get("session_id") or os.environ.get("CLAUDE_SESSION_ID")
376
+ cwd = hook_input.get("cwd")
377
+ project_dir = _resolve_project_dir(cwd if cwd else None)
378
+ graph_dir = Path(project_dir) / ".htmlgraph"
379
+
380
+ # Check if CIGS is enabled (disabled by default for now)
381
+ cigs_enabled = os.environ.get("HTMLGRAPH_CIGS_ENABLED") == "1"
382
+
383
+ if not cigs_enabled or not CIGS_AVAILABLE:
384
+ # CIGS not enabled or not available, just output empty response
385
+ print(json.dumps({"continue": True}))
386
+ return
387
+
388
+ # Generate CIGS session summary
389
+ try:
390
+ summarizer = CIGSSessionSummarizer(graph_dir)
391
+ result = summarizer.summarize(session_id)
392
+ print(json.dumps(result))
393
+ except Exception as e:
394
+ logger.warning(f"Warning: Could not generate CIGS summary: {e}")
395
+ print(json.dumps({"continue": True}))