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,399 @@
1
+ from __future__ import annotations
2
+
3
+ """HTML template for cost dashboard.
4
+
5
+ This module generates a beautiful, interactive HTML dashboard for cost analysis.
6
+ Separated from main CLI code for maintainability and testability.
7
+ """
8
+
9
+
10
+ from datetime import datetime
11
+ from typing import TYPE_CHECKING, Any
12
+
13
+ if TYPE_CHECKING:
14
+ from htmlgraph.cli.analytics import CostSummary
15
+
16
+
17
+ def generate_html(summary: CostSummary) -> str:
18
+ """Generate HTML dashboard from cost summary.
19
+
20
+ Args:
21
+ summary: Validated cost summary data
22
+
23
+ Returns:
24
+ Complete HTML document as string
25
+ """
26
+ # Calculate derived metrics
27
+ total_cost = summary.total_cost_tokens
28
+ avg_cost = summary.avg_cost_per_event
29
+ delegation_pct = summary.delegation_percentage
30
+ cost_usd = summary.estimated_cost_usd
31
+
32
+ # Sort tools by cost
33
+ sorted_tools = sorted(
34
+ summary.tool_costs.items(),
35
+ key=lambda x: x[1].total_tokens,
36
+ reverse=True,
37
+ )
38
+
39
+ # Sort sessions by cost
40
+ sorted_sessions = sorted(
41
+ summary.session_costs.items(),
42
+ key=lambda x: x[1].total_tokens,
43
+ reverse=True,
44
+ )
45
+
46
+ # Build tool cost rows
47
+ tool_rows = _build_tool_rows(sorted_tools, total_cost)
48
+
49
+ # Build session cost rows
50
+ session_rows = _build_session_rows(sorted_sessions, total_cost)
51
+
52
+ # Build insights
53
+ insights = _build_insights_html(delegation_pct, sorted_tools, total_cost)
54
+
55
+ # Generate complete HTML
56
+ return f"""<!DOCTYPE html>
57
+ <html lang="en">
58
+ <head>
59
+ <meta charset="UTF-8">
60
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
61
+ <title>HtmlGraph Cost Dashboard</title>
62
+ <style>
63
+ {_get_css_styles()}
64
+ </style>
65
+ </head>
66
+ <body>
67
+ <div class="container">
68
+ <header>
69
+ <h1>💰 HtmlGraph Cost Dashboard</h1>
70
+ <p class="timestamp">Generated: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</p>
71
+ <div class="metrics">
72
+ <div class="metric">
73
+ <div class="metric-label">Total Cost</div>
74
+ <div class="metric-value">{total_cost:,}<span class="metric-unit">tokens</span></div>
75
+ </div>
76
+ <div class="metric success">
77
+ <div class="metric-label">Estimated USD</div>
78
+ <div class="metric-value">${cost_usd:.2f}</div>
79
+ </div>
80
+ <div class="metric">
81
+ <div class="metric-label">Average Cost</div>
82
+ <div class="metric-value">{avg_cost:,.0f}<span class="metric-unit">tokens</span></div>
83
+ </div>
84
+ <div class="metric success">
85
+ <div class="metric-label">Delegation Rate</div>
86
+ <div class="metric-value">{delegation_pct:.1f}%</div>
87
+ </div>
88
+ </div>
89
+ </header>
90
+
91
+ <section>
92
+ <h2>📊 Cost by Tool</h2>
93
+ <table>
94
+ <thead>
95
+ <tr>
96
+ <th>Tool</th>
97
+ <th>Count</th>
98
+ <th>Total Tokens</th>
99
+ <th>% of Total</th>
100
+ </tr>
101
+ </thead>
102
+ <tbody>
103
+ {tool_rows}
104
+ </tbody>
105
+ </table>
106
+ </section>
107
+
108
+ <section>
109
+ <h2>🔄 Cost by Session</h2>
110
+ <table>
111
+ <thead>
112
+ <tr>
113
+ <th>Session ID</th>
114
+ <th>Count</th>
115
+ <th>Total Tokens</th>
116
+ <th>% of Total</th>
117
+ </tr>
118
+ </thead>
119
+ <tbody>
120
+ {session_rows}
121
+ </tbody>
122
+ </table>
123
+ </section>
124
+
125
+ <section>
126
+ <h2>💡 Insights & Recommendations</h2>
127
+ <div class="insights">
128
+ {insights}
129
+ </div>
130
+ </section>
131
+
132
+ <div class="footer">
133
+ <p>HtmlGraph Cost Attribution Dashboard | Real-time cost tracking and optimization</p>
134
+ </div>
135
+ </div>
136
+ </body>
137
+ </html>"""
138
+
139
+
140
+ def _build_tool_rows(sorted_tools: list[tuple[str, Any]], total_cost: int) -> str:
141
+ """Build HTML table rows for tool costs."""
142
+ if not sorted_tools or total_cost == 0:
143
+ return '<tr><td colspan="4" class="cell">No data available</td></tr>'
144
+
145
+ rows = []
146
+ for tool, data in sorted_tools[:20]: # Top 20 tools
147
+ pct = data.total_tokens / total_cost * 100
148
+ rows.append(
149
+ f"""
150
+ <tr>
151
+ <td class="cell">{tool}</td>
152
+ <td class="cell number">{data.count}</td>
153
+ <td class="cell number">{data.total_tokens:,}</td>
154
+ <td class="cell number">{pct:.1f}%</td>
155
+ </tr>"""
156
+ )
157
+ return "".join(rows)
158
+
159
+
160
+ def _build_session_rows(sorted_sessions: list[tuple[str, Any]], total_cost: int) -> str:
161
+ """Build HTML table rows for session costs."""
162
+ if not sorted_sessions or total_cost == 0:
163
+ return '<tr><td colspan="4" class="cell">No data available</td></tr>'
164
+
165
+ rows = []
166
+ for session, data in sorted_sessions[:20]: # Top 20 sessions
167
+ pct = data.total_tokens / total_cost * 100
168
+ session_display = session[:12] + "..." if len(session) > 12 else session
169
+ rows.append(
170
+ f"""
171
+ <tr>
172
+ <td class="cell">{session_display}</td>
173
+ <td class="cell number">{data.count}</td>
174
+ <td class="cell number">{data.total_tokens:,}</td>
175
+ <td class="cell number">{pct:.1f}%</td>
176
+ </tr>"""
177
+ )
178
+ return "".join(rows)
179
+
180
+
181
+ def _build_insights_html(
182
+ delegation_pct: float, sorted_tools: list[tuple[str, Any]], total_cost: int
183
+ ) -> str:
184
+ """Build insights and recommendations section."""
185
+ insights = []
186
+
187
+ # Delegation insight
188
+ delegation_msg = (
189
+ "Continue delegation for cost efficiency!"
190
+ if delegation_pct > 50
191
+ else "Consider delegating more operations to reduce costs."
192
+ )
193
+ insights.append(
194
+ f"""
195
+ <div class="insight">
196
+ <div class="insight-title">✓ Delegation Usage</div>
197
+ <div class="insight-text">
198
+ You're delegating {delegation_pct:.1f}% of operations.
199
+ {delegation_msg}
200
+ </div>
201
+ </div>"""
202
+ )
203
+
204
+ # Top cost driver insight
205
+ if sorted_tools and total_cost > 0:
206
+ top_tool, top_data = sorted_tools[0]
207
+ top_pct = top_data.total_tokens / total_cost * 100
208
+ insights.append(
209
+ f"""
210
+ <div class="insight">
211
+ <div class="insight-title">🎯 Top Cost Driver</div>
212
+ <div class="insight-text">
213
+ {top_tool} accounts for {top_pct:.1f}% of total cost.
214
+ Review if this tool usage is optimal.
215
+ </div>
216
+ </div>"""
217
+ )
218
+
219
+ # Parallelization insight
220
+ insights.append(
221
+ """
222
+ <div class="insight">
223
+ <div class="insight-title">📈 Parallelization Opportunity</div>
224
+ <div class="insight-text">
225
+ Parallel Task() calls can reduce overall execution time by ~40%.
226
+ Look for independent operations that can run simultaneously.
227
+ </div>
228
+ </div>"""
229
+ )
230
+
231
+ return "".join(insights)
232
+
233
+
234
+ def _get_css_styles() -> str:
235
+ """Get CSS styles for the dashboard.
236
+
237
+ Extracted to separate function for maintainability.
238
+ """
239
+ return """ * {
240
+ margin: 0;
241
+ padding: 0;
242
+ box-sizing: border-box;
243
+ }
244
+
245
+ body {
246
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
247
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
248
+ min-height: 100vh;
249
+ padding: 40px 20px;
250
+ }
251
+
252
+ .container {
253
+ max-width: 1400px;
254
+ margin: 0 auto;
255
+ }
256
+
257
+ header {
258
+ background: white;
259
+ border-radius: 12px;
260
+ padding: 30px;
261
+ margin-bottom: 30px;
262
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
263
+ }
264
+
265
+ h1 {
266
+ color: #667eea;
267
+ margin-bottom: 10px;
268
+ font-size: 28px;
269
+ }
270
+
271
+ .timestamp {
272
+ color: #999;
273
+ font-size: 12px;
274
+ }
275
+
276
+ .metrics {
277
+ display: grid;
278
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
279
+ gap: 20px;
280
+ margin-top: 20px;
281
+ }
282
+
283
+ .metric {
284
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
285
+ color: white;
286
+ padding: 20px;
287
+ border-radius: 8px;
288
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
289
+ }
290
+
291
+ .metric-label {
292
+ font-size: 12px;
293
+ opacity: 0.9;
294
+ margin-bottom: 8px;
295
+ text-transform: uppercase;
296
+ letter-spacing: 1px;
297
+ }
298
+
299
+ .metric-value {
300
+ font-size: 32px;
301
+ font-weight: bold;
302
+ }
303
+
304
+ .metric-unit {
305
+ font-size: 14px;
306
+ opacity: 0.8;
307
+ margin-left: 8px;
308
+ }
309
+
310
+ .metric.warning {
311
+ background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
312
+ }
313
+
314
+ .metric.success {
315
+ background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
316
+ }
317
+
318
+ section {
319
+ background: white;
320
+ border-radius: 12px;
321
+ padding: 30px;
322
+ margin-bottom: 30px;
323
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
324
+ }
325
+
326
+ h2 {
327
+ color: #333;
328
+ margin-bottom: 20px;
329
+ font-size: 20px;
330
+ border-bottom: 2px solid #667eea;
331
+ padding-bottom: 10px;
332
+ }
333
+
334
+ table {
335
+ width: 100%;
336
+ border-collapse: collapse;
337
+ }
338
+
339
+ th {
340
+ background: #f5f5f5;
341
+ padding: 12px;
342
+ text-align: left;
343
+ font-weight: 600;
344
+ color: #333;
345
+ border-bottom: 2px solid #ddd;
346
+ }
347
+
348
+ td {
349
+ padding: 12px;
350
+ border-bottom: 1px solid #eee;
351
+ }
352
+
353
+ td.cell {
354
+ color: #333;
355
+ }
356
+
357
+ td.number {
358
+ text-align: right;
359
+ font-family: 'Monaco', 'Courier New', monospace;
360
+ color: #667eea;
361
+ font-weight: 500;
362
+ }
363
+
364
+ tr:hover {
365
+ background: #f9f9f9;
366
+ }
367
+
368
+ .insights {
369
+ display: grid;
370
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
371
+ gap: 20px;
372
+ margin-top: 20px;
373
+ }
374
+
375
+ .insight {
376
+ background: #f0f4ff;
377
+ border-left: 4px solid #667eea;
378
+ padding: 16px;
379
+ border-radius: 4px;
380
+ }
381
+
382
+ .insight-title {
383
+ font-weight: 600;
384
+ color: #333;
385
+ margin-bottom: 8px;
386
+ }
387
+
388
+ .insight-text {
389
+ color: #666;
390
+ font-size: 14px;
391
+ line-height: 1.6;
392
+ }
393
+
394
+ .footer {
395
+ text-align: center;
396
+ color: #999;
397
+ font-size: 12px;
398
+ margin-top: 40px;
399
+ }"""
@@ -0,0 +1,239 @@
1
+ from __future__ import annotations
2
+
3
+ """HtmlGraph CLI - Work management commands.
4
+
5
+ Commands for managing work items:
6
+ - Features: Work item tracking
7
+ - Sessions: Session management
8
+ - Tracks: Multi-feature planning
9
+ - Archives: Archival management
10
+ - Orchestrator: Claude Code integration
11
+ - Other work-related operations
12
+ """
13
+
14
+
15
+ from typing import TYPE_CHECKING
16
+
17
+ if TYPE_CHECKING:
18
+ from argparse import _SubParsersAction
19
+
20
+
21
+ def register_commands(subparsers: _SubParsersAction) -> None:
22
+ """Register work management commands with the argument parser.
23
+
24
+ Args:
25
+ subparsers: Subparser action from ArgumentParser.add_subparsers()
26
+ """
27
+ from htmlgraph.cli.work.browse import BrowseCommand
28
+ from htmlgraph.cli.work.features import register_feature_commands
29
+ from htmlgraph.cli.work.orchestration import (
30
+ register_archive_commands,
31
+ register_claude_commands,
32
+ register_orchestrator_commands,
33
+ )
34
+ from htmlgraph.cli.work.report import register_report_commands
35
+ from htmlgraph.cli.work.sessions import register_session_commands
36
+ from htmlgraph.cli.work.snapshot import SnapshotCommand
37
+ from htmlgraph.cli.work.tracks import register_track_commands
38
+
39
+ # Register all command groups
40
+ register_session_commands(subparsers)
41
+ register_feature_commands(subparsers)
42
+ register_track_commands(subparsers)
43
+ register_archive_commands(subparsers)
44
+ register_orchestrator_commands(subparsers)
45
+ register_claude_commands(subparsers)
46
+ register_report_commands(subparsers)
47
+
48
+ # Snapshot command
49
+ snapshot_parser = subparsers.add_parser(
50
+ "snapshot",
51
+ help="Output current graph state with refs",
52
+ )
53
+ snapshot_parser.add_argument(
54
+ "--output-format",
55
+ choices=["refs", "json", "text"],
56
+ default="refs",
57
+ help="Output format (default: refs)",
58
+ )
59
+ snapshot_parser.add_argument(
60
+ "--type",
61
+ help="Filter by type (feature, track, bug, spike, chore, epic, all)",
62
+ )
63
+ snapshot_parser.add_argument(
64
+ "--status",
65
+ help="Filter by status (todo, in_progress, blocked, done, all)",
66
+ )
67
+ snapshot_parser.add_argument(
68
+ "--track",
69
+ help="Show only items in a specific track (by track ID or ref)",
70
+ )
71
+ snapshot_parser.add_argument(
72
+ "--active",
73
+ action="store_true",
74
+ help="Show only TODO/IN_PROGRESS items (filters out metadata spikes)",
75
+ )
76
+ snapshot_parser.add_argument(
77
+ "--blockers",
78
+ action="store_true",
79
+ help="Show only critical/blocked items",
80
+ )
81
+ snapshot_parser.add_argument(
82
+ "--summary",
83
+ action="store_true",
84
+ help="Show counts and progress summary instead of listing all items",
85
+ )
86
+ snapshot_parser.add_argument(
87
+ "--my-work",
88
+ action="store_true",
89
+ help="Show items assigned to current agent",
90
+ )
91
+ snapshot_parser.set_defaults(func=SnapshotCommand.from_args)
92
+
93
+ # Browse command
94
+ browse_parser = subparsers.add_parser(
95
+ "browse",
96
+ help="Open dashboard in browser",
97
+ )
98
+ browse_parser.add_argument(
99
+ "--port",
100
+ type=int,
101
+ default=8080,
102
+ help="Server port (default: 8080)",
103
+ )
104
+ browse_parser.add_argument(
105
+ "--query-type",
106
+ help="Filter by type (feature, track, bug, spike, chore, epic)",
107
+ )
108
+ browse_parser.add_argument(
109
+ "--query-status",
110
+ help="Filter by status (todo, in_progress, blocked, done)",
111
+ )
112
+ browse_parser.set_defaults(func=BrowseCommand.from_args)
113
+
114
+
115
+ # Re-export all command classes for backward compatibility
116
+ from htmlgraph.cli.work.browse import BrowseCommand
117
+ from htmlgraph.cli.work.features import (
118
+ FeatureClaimCommand,
119
+ FeatureCompleteCommand,
120
+ FeatureCreateCommand,
121
+ FeatureListCommand,
122
+ FeaturePrimaryCommand,
123
+ FeatureReleaseCommand,
124
+ FeatureStartCommand,
125
+ )
126
+ from htmlgraph.cli.work.orchestration import (
127
+ ArchiveCreateCommand,
128
+ ArchiveListCommand,
129
+ ClaudeCommand,
130
+ OrchestratorDisableCommand,
131
+ OrchestratorEnableCommand,
132
+ OrchestratorResetViolationsCommand,
133
+ OrchestratorSetLevelCommand,
134
+ OrchestratorStatusCommand,
135
+ )
136
+ from htmlgraph.cli.work.report import SessionReportCommand
137
+ from htmlgraph.cli.work.sessions import (
138
+ SessionEndCommand,
139
+ SessionHandoffCommand,
140
+ SessionListCommand,
141
+ SessionStartCommand,
142
+ SessionStartInfoCommand,
143
+ )
144
+ from htmlgraph.cli.work.snapshot import SnapshotCommand
145
+ from htmlgraph.cli.work.tracks import (
146
+ TrackDeleteCommand,
147
+ TrackListCommand,
148
+ TrackNewCommand,
149
+ TrackPlanCommand,
150
+ TrackSpecCommand,
151
+ )
152
+
153
+ __all__ = [
154
+ "register_commands",
155
+ # Session commands
156
+ "SessionStartCommand",
157
+ "SessionEndCommand",
158
+ "SessionListCommand",
159
+ "SessionHandoffCommand",
160
+ "SessionStartInfoCommand",
161
+ # Report commands
162
+ "SessionReportCommand",
163
+ # Snapshot commands
164
+ "SnapshotCommand",
165
+ # Browse commands
166
+ "BrowseCommand",
167
+ # Feature commands
168
+ "FeatureListCommand",
169
+ "FeatureCreateCommand",
170
+ "FeatureStartCommand",
171
+ "FeatureCompleteCommand",
172
+ "FeatureClaimCommand",
173
+ "FeatureReleaseCommand",
174
+ "FeaturePrimaryCommand",
175
+ # Track commands
176
+ "TrackNewCommand",
177
+ "TrackListCommand",
178
+ "TrackSpecCommand",
179
+ "TrackPlanCommand",
180
+ "TrackDeleteCommand",
181
+ # Orchestration commands
182
+ "ArchiveCreateCommand",
183
+ "ArchiveListCommand",
184
+ "OrchestratorStatusCommand",
185
+ "OrchestratorEnableCommand",
186
+ "OrchestratorDisableCommand",
187
+ "OrchestratorResetViolationsCommand",
188
+ "OrchestratorSetLevelCommand",
189
+ "ClaudeCommand",
190
+ ]
191
+
192
+
193
+ # Convenience functions for backward compatibility with tests
194
+ def cmd_orchestrator_reset_violations(args: object) -> None:
195
+ """Reset violations command."""
196
+ from argparse import Namespace
197
+
198
+ if isinstance(args, Namespace):
199
+ cmd = OrchestratorResetViolationsCommand.from_args(args)
200
+ cmd.graph_dir = (
201
+ str(args.graph_dir) if hasattr(args, "graph_dir") else ".htmlgraph"
202
+ )
203
+ result = cmd.execute()
204
+ from htmlgraph.cli.base import TextFormatter
205
+
206
+ formatter = TextFormatter()
207
+ formatter.output(result)
208
+
209
+
210
+ def cmd_orchestrator_set_level(args: object) -> None:
211
+ """Set level command."""
212
+ from argparse import Namespace
213
+
214
+ if isinstance(args, Namespace):
215
+ cmd = OrchestratorSetLevelCommand.from_args(args)
216
+ cmd.graph_dir = (
217
+ str(args.graph_dir) if hasattr(args, "graph_dir") else ".htmlgraph"
218
+ )
219
+ result = cmd.execute()
220
+ from htmlgraph.cli.base import TextFormatter
221
+
222
+ formatter = TextFormatter()
223
+ formatter.output(result)
224
+
225
+
226
+ def cmd_orchestrator_status(args: object) -> None:
227
+ """Status command."""
228
+ from argparse import Namespace
229
+
230
+ if isinstance(args, Namespace):
231
+ cmd = OrchestratorStatusCommand.from_args(args)
232
+ cmd.graph_dir = (
233
+ str(args.graph_dir) if hasattr(args, "graph_dir") else ".htmlgraph"
234
+ )
235
+ result = cmd.execute()
236
+ from htmlgraph.cli.base import TextFormatter
237
+
238
+ formatter = TextFormatter()
239
+ formatter.output(result)