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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. htmlgraph/.htmlgraph/.session-warning-state.json +6 -0
  2. htmlgraph/.htmlgraph/agents.json +72 -0
  3. htmlgraph/.htmlgraph/htmlgraph.db +0 -0
  4. htmlgraph/__init__.py +51 -1
  5. htmlgraph/__init__.pyi +123 -0
  6. htmlgraph/agent_detection.py +26 -10
  7. htmlgraph/agent_registry.py +2 -1
  8. htmlgraph/analytics/__init__.py +8 -1
  9. htmlgraph/analytics/cli.py +86 -20
  10. htmlgraph/analytics/cost_analyzer.py +391 -0
  11. htmlgraph/analytics/cost_monitor.py +664 -0
  12. htmlgraph/analytics/cost_reporter.py +675 -0
  13. htmlgraph/analytics/cross_session.py +617 -0
  14. htmlgraph/analytics/dependency.py +10 -6
  15. htmlgraph/analytics/pattern_learning.py +771 -0
  16. htmlgraph/analytics/session_graph.py +707 -0
  17. htmlgraph/analytics/strategic/__init__.py +80 -0
  18. htmlgraph/analytics/strategic/cost_optimizer.py +611 -0
  19. htmlgraph/analytics/strategic/pattern_detector.py +876 -0
  20. htmlgraph/analytics/strategic/preference_manager.py +709 -0
  21. htmlgraph/analytics/strategic/suggestion_engine.py +747 -0
  22. htmlgraph/analytics/work_type.py +67 -27
  23. htmlgraph/analytics_index.py +53 -20
  24. htmlgraph/api/__init__.py +3 -0
  25. htmlgraph/api/cost_alerts_websocket.py +416 -0
  26. htmlgraph/api/main.py +2498 -0
  27. htmlgraph/api/static/htmx.min.js +1 -0
  28. htmlgraph/api/static/style-redesign.css +1344 -0
  29. htmlgraph/api/static/style.css +1079 -0
  30. htmlgraph/api/templates/dashboard-redesign.html +1366 -0
  31. htmlgraph/api/templates/dashboard.html +794 -0
  32. htmlgraph/api/templates/partials/activity-feed-hierarchical.html +326 -0
  33. htmlgraph/api/templates/partials/activity-feed.html +1100 -0
  34. htmlgraph/api/templates/partials/agents-redesign.html +317 -0
  35. htmlgraph/api/templates/partials/agents.html +317 -0
  36. htmlgraph/api/templates/partials/event-traces.html +373 -0
  37. htmlgraph/api/templates/partials/features-kanban-redesign.html +509 -0
  38. htmlgraph/api/templates/partials/features.html +578 -0
  39. htmlgraph/api/templates/partials/metrics-redesign.html +346 -0
  40. htmlgraph/api/templates/partials/metrics.html +346 -0
  41. htmlgraph/api/templates/partials/orchestration-redesign.html +443 -0
  42. htmlgraph/api/templates/partials/orchestration.html +198 -0
  43. htmlgraph/api/templates/partials/spawners.html +375 -0
  44. htmlgraph/api/templates/partials/work-items.html +613 -0
  45. htmlgraph/api/websocket.py +538 -0
  46. htmlgraph/archive/__init__.py +24 -0
  47. htmlgraph/archive/bloom.py +234 -0
  48. htmlgraph/archive/fts.py +297 -0
  49. htmlgraph/archive/manager.py +583 -0
  50. htmlgraph/archive/search.py +244 -0
  51. htmlgraph/atomic_ops.py +560 -0
  52. htmlgraph/attribute_index.py +2 -1
  53. htmlgraph/bounded_paths.py +539 -0
  54. htmlgraph/builders/base.py +57 -2
  55. htmlgraph/builders/bug.py +19 -3
  56. htmlgraph/builders/chore.py +19 -3
  57. htmlgraph/builders/epic.py +19 -3
  58. htmlgraph/builders/feature.py +27 -3
  59. htmlgraph/builders/insight.py +2 -1
  60. htmlgraph/builders/metric.py +2 -1
  61. htmlgraph/builders/pattern.py +2 -1
  62. htmlgraph/builders/phase.py +19 -3
  63. htmlgraph/builders/spike.py +29 -3
  64. htmlgraph/builders/track.py +42 -1
  65. htmlgraph/cigs/__init__.py +81 -0
  66. htmlgraph/cigs/autonomy.py +385 -0
  67. htmlgraph/cigs/cost.py +475 -0
  68. htmlgraph/cigs/messages_basic.py +472 -0
  69. htmlgraph/cigs/messaging.py +365 -0
  70. htmlgraph/cigs/models.py +771 -0
  71. htmlgraph/cigs/pattern_storage.py +427 -0
  72. htmlgraph/cigs/patterns.py +503 -0
  73. htmlgraph/cigs/posttool_analyzer.py +234 -0
  74. htmlgraph/cigs/reporter.py +818 -0
  75. htmlgraph/cigs/tracker.py +317 -0
  76. htmlgraph/cli/.htmlgraph/.session-warning-state.json +6 -0
  77. htmlgraph/cli/.htmlgraph/agents.json +72 -0
  78. htmlgraph/cli/.htmlgraph/htmlgraph.db +0 -0
  79. htmlgraph/cli/__init__.py +42 -0
  80. htmlgraph/cli/__main__.py +6 -0
  81. htmlgraph/cli/analytics.py +1424 -0
  82. htmlgraph/cli/base.py +685 -0
  83. htmlgraph/cli/constants.py +206 -0
  84. htmlgraph/cli/core.py +954 -0
  85. htmlgraph/cli/main.py +147 -0
  86. htmlgraph/cli/models.py +475 -0
  87. htmlgraph/cli/templates/__init__.py +1 -0
  88. htmlgraph/cli/templates/cost_dashboard.py +399 -0
  89. htmlgraph/cli/work/__init__.py +239 -0
  90. htmlgraph/cli/work/browse.py +115 -0
  91. htmlgraph/cli/work/features.py +568 -0
  92. htmlgraph/cli/work/orchestration.py +676 -0
  93. htmlgraph/cli/work/report.py +728 -0
  94. htmlgraph/cli/work/sessions.py +466 -0
  95. htmlgraph/cli/work/snapshot.py +559 -0
  96. htmlgraph/cli/work/tracks.py +486 -0
  97. htmlgraph/cli_commands/__init__.py +1 -0
  98. htmlgraph/cli_commands/feature.py +195 -0
  99. htmlgraph/cli_framework.py +115 -0
  100. htmlgraph/collections/__init__.py +2 -0
  101. htmlgraph/collections/base.py +197 -14
  102. htmlgraph/collections/bug.py +2 -1
  103. htmlgraph/collections/chore.py +2 -1
  104. htmlgraph/collections/epic.py +2 -1
  105. htmlgraph/collections/feature.py +2 -1
  106. htmlgraph/collections/insight.py +2 -1
  107. htmlgraph/collections/metric.py +2 -1
  108. htmlgraph/collections/pattern.py +2 -1
  109. htmlgraph/collections/phase.py +2 -1
  110. htmlgraph/collections/session.py +194 -0
  111. htmlgraph/collections/spike.py +13 -2
  112. htmlgraph/collections/task_delegation.py +241 -0
  113. htmlgraph/collections/todo.py +14 -1
  114. htmlgraph/collections/traces.py +487 -0
  115. htmlgraph/config/cost_models.json +56 -0
  116. htmlgraph/config.py +190 -0
  117. htmlgraph/context_analytics.py +2 -1
  118. htmlgraph/converter.py +116 -7
  119. htmlgraph/cost_analysis/__init__.py +5 -0
  120. htmlgraph/cost_analysis/analyzer.py +438 -0
  121. htmlgraph/dashboard.html +2246 -248
  122. htmlgraph/dashboard.html.backup +6592 -0
  123. htmlgraph/dashboard.html.bak +7181 -0
  124. htmlgraph/dashboard.html.bak2 +7231 -0
  125. htmlgraph/dashboard.html.bak3 +7232 -0
  126. htmlgraph/db/__init__.py +38 -0
  127. htmlgraph/db/queries.py +790 -0
  128. htmlgraph/db/schema.py +1788 -0
  129. htmlgraph/decorators.py +317 -0
  130. htmlgraph/dependency_models.py +2 -1
  131. htmlgraph/deploy.py +26 -27
  132. htmlgraph/docs/API_REFERENCE.md +841 -0
  133. htmlgraph/docs/HTTP_API.md +750 -0
  134. htmlgraph/docs/INTEGRATION_GUIDE.md +752 -0
  135. htmlgraph/docs/ORCHESTRATION_PATTERNS.md +717 -0
  136. htmlgraph/docs/README.md +532 -0
  137. htmlgraph/docs/__init__.py +77 -0
  138. htmlgraph/docs/docs_version.py +55 -0
  139. htmlgraph/docs/metadata.py +93 -0
  140. htmlgraph/docs/migrations.py +232 -0
  141. htmlgraph/docs/template_engine.py +143 -0
  142. htmlgraph/docs/templates/_sections/cli_reference.md.j2 +52 -0
  143. htmlgraph/docs/templates/_sections/core_concepts.md.j2 +29 -0
  144. htmlgraph/docs/templates/_sections/sdk_basics.md.j2 +69 -0
  145. htmlgraph/docs/templates/base_agents.md.j2 +78 -0
  146. htmlgraph/docs/templates/example_user_override.md.j2 +47 -0
  147. htmlgraph/docs/version_check.py +163 -0
  148. htmlgraph/edge_index.py +2 -1
  149. htmlgraph/error_handler.py +544 -0
  150. htmlgraph/event_log.py +86 -37
  151. htmlgraph/event_migration.py +2 -1
  152. htmlgraph/file_watcher.py +12 -8
  153. htmlgraph/find_api.py +2 -1
  154. htmlgraph/git_events.py +67 -9
  155. htmlgraph/hooks/.htmlgraph/.session-warning-state.json +6 -0
  156. htmlgraph/hooks/.htmlgraph/agents.json +72 -0
  157. htmlgraph/hooks/.htmlgraph/index.sqlite +0 -0
  158. htmlgraph/hooks/__init__.py +8 -0
  159. htmlgraph/hooks/bootstrap.py +169 -0
  160. htmlgraph/hooks/cigs_pretool_enforcer.py +354 -0
  161. htmlgraph/hooks/concurrent_sessions.py +208 -0
  162. htmlgraph/hooks/context.py +350 -0
  163. htmlgraph/hooks/drift_handler.py +525 -0
  164. htmlgraph/hooks/event_tracker.py +790 -99
  165. htmlgraph/hooks/git_commands.py +175 -0
  166. htmlgraph/hooks/installer.py +5 -1
  167. htmlgraph/hooks/orchestrator.py +327 -76
  168. htmlgraph/hooks/orchestrator_reflector.py +31 -4
  169. htmlgraph/hooks/post_tool_use_failure.py +32 -7
  170. htmlgraph/hooks/post_tool_use_handler.py +257 -0
  171. htmlgraph/hooks/posttooluse.py +92 -19
  172. htmlgraph/hooks/pretooluse.py +527 -7
  173. htmlgraph/hooks/prompt_analyzer.py +637 -0
  174. htmlgraph/hooks/session_handler.py +668 -0
  175. htmlgraph/hooks/session_summary.py +395 -0
  176. htmlgraph/hooks/state_manager.py +504 -0
  177. htmlgraph/hooks/subagent_detection.py +202 -0
  178. htmlgraph/hooks/subagent_stop.py +369 -0
  179. htmlgraph/hooks/task_enforcer.py +99 -4
  180. htmlgraph/hooks/validator.py +212 -91
  181. htmlgraph/ids.py +2 -1
  182. htmlgraph/learning.py +125 -100
  183. htmlgraph/mcp_server.py +2 -1
  184. htmlgraph/models.py +217 -18
  185. htmlgraph/operations/README.md +62 -0
  186. htmlgraph/operations/__init__.py +79 -0
  187. htmlgraph/operations/analytics.py +339 -0
  188. htmlgraph/operations/bootstrap.py +289 -0
  189. htmlgraph/operations/events.py +244 -0
  190. htmlgraph/operations/fastapi_server.py +231 -0
  191. htmlgraph/operations/hooks.py +350 -0
  192. htmlgraph/operations/initialization.py +597 -0
  193. htmlgraph/operations/initialization.py.backup +228 -0
  194. htmlgraph/operations/server.py +303 -0
  195. htmlgraph/orchestration/__init__.py +58 -0
  196. htmlgraph/orchestration/claude_launcher.py +179 -0
  197. htmlgraph/orchestration/command_builder.py +72 -0
  198. htmlgraph/orchestration/headless_spawner.py +281 -0
  199. htmlgraph/orchestration/live_events.py +377 -0
  200. htmlgraph/orchestration/model_selection.py +327 -0
  201. htmlgraph/orchestration/plugin_manager.py +140 -0
  202. htmlgraph/orchestration/prompts.py +137 -0
  203. htmlgraph/orchestration/spawner_event_tracker.py +383 -0
  204. htmlgraph/orchestration/spawners/__init__.py +16 -0
  205. htmlgraph/orchestration/spawners/base.py +194 -0
  206. htmlgraph/orchestration/spawners/claude.py +173 -0
  207. htmlgraph/orchestration/spawners/codex.py +435 -0
  208. htmlgraph/orchestration/spawners/copilot.py +294 -0
  209. htmlgraph/orchestration/spawners/gemini.py +471 -0
  210. htmlgraph/orchestration/subprocess_runner.py +36 -0
  211. htmlgraph/{orchestration.py → orchestration/task_coordination.py} +16 -8
  212. htmlgraph/orchestration.md +563 -0
  213. htmlgraph/orchestrator-system-prompt-optimized.txt +863 -0
  214. htmlgraph/orchestrator.py +2 -1
  215. htmlgraph/orchestrator_config.py +357 -0
  216. htmlgraph/orchestrator_mode.py +115 -4
  217. htmlgraph/parallel.py +2 -1
  218. htmlgraph/parser.py +86 -6
  219. htmlgraph/path_query.py +608 -0
  220. htmlgraph/pattern_matcher.py +636 -0
  221. htmlgraph/pydantic_models.py +476 -0
  222. htmlgraph/quality_gates.py +350 -0
  223. htmlgraph/query_builder.py +2 -1
  224. htmlgraph/query_composer.py +509 -0
  225. htmlgraph/reflection.py +443 -0
  226. htmlgraph/refs.py +344 -0
  227. htmlgraph/repo_hash.py +512 -0
  228. htmlgraph/repositories/__init__.py +292 -0
  229. htmlgraph/repositories/analytics_repository.py +455 -0
  230. htmlgraph/repositories/analytics_repository_standard.py +628 -0
  231. htmlgraph/repositories/feature_repository.py +581 -0
  232. htmlgraph/repositories/feature_repository_htmlfile.py +668 -0
  233. htmlgraph/repositories/feature_repository_memory.py +607 -0
  234. htmlgraph/repositories/feature_repository_sqlite.py +858 -0
  235. htmlgraph/repositories/filter_service.py +620 -0
  236. htmlgraph/repositories/filter_service_standard.py +445 -0
  237. htmlgraph/repositories/shared_cache.py +621 -0
  238. htmlgraph/repositories/shared_cache_memory.py +395 -0
  239. htmlgraph/repositories/track_repository.py +552 -0
  240. htmlgraph/repositories/track_repository_htmlfile.py +619 -0
  241. htmlgraph/repositories/track_repository_memory.py +508 -0
  242. htmlgraph/repositories/track_repository_sqlite.py +711 -0
  243. htmlgraph/sdk/__init__.py +398 -0
  244. htmlgraph/sdk/__init__.pyi +14 -0
  245. htmlgraph/sdk/analytics/__init__.py +19 -0
  246. htmlgraph/sdk/analytics/engine.py +155 -0
  247. htmlgraph/sdk/analytics/helpers.py +178 -0
  248. htmlgraph/sdk/analytics/registry.py +109 -0
  249. htmlgraph/sdk/base.py +484 -0
  250. htmlgraph/sdk/constants.py +216 -0
  251. htmlgraph/sdk/core.pyi +308 -0
  252. htmlgraph/sdk/discovery.py +120 -0
  253. htmlgraph/sdk/help/__init__.py +12 -0
  254. htmlgraph/sdk/help/mixin.py +699 -0
  255. htmlgraph/sdk/mixins/__init__.py +15 -0
  256. htmlgraph/sdk/mixins/attribution.py +113 -0
  257. htmlgraph/sdk/mixins/mixin.py +410 -0
  258. htmlgraph/sdk/operations/__init__.py +12 -0
  259. htmlgraph/sdk/operations/mixin.py +427 -0
  260. htmlgraph/sdk/orchestration/__init__.py +17 -0
  261. htmlgraph/sdk/orchestration/coordinator.py +203 -0
  262. htmlgraph/sdk/orchestration/spawner.py +204 -0
  263. htmlgraph/sdk/planning/__init__.py +19 -0
  264. htmlgraph/sdk/planning/bottlenecks.py +93 -0
  265. htmlgraph/sdk/planning/mixin.py +211 -0
  266. htmlgraph/sdk/planning/parallel.py +186 -0
  267. htmlgraph/sdk/planning/queue.py +210 -0
  268. htmlgraph/sdk/planning/recommendations.py +87 -0
  269. htmlgraph/sdk/planning/smart_planning.py +319 -0
  270. htmlgraph/sdk/session/__init__.py +19 -0
  271. htmlgraph/sdk/session/continuity.py +57 -0
  272. htmlgraph/sdk/session/handoff.py +110 -0
  273. htmlgraph/sdk/session/info.py +309 -0
  274. htmlgraph/sdk/session/manager.py +103 -0
  275. htmlgraph/sdk/strategic/__init__.py +26 -0
  276. htmlgraph/sdk/strategic/mixin.py +563 -0
  277. htmlgraph/server.py +295 -107
  278. htmlgraph/session_hooks.py +300 -0
  279. htmlgraph/session_manager.py +285 -3
  280. htmlgraph/session_registry.py +587 -0
  281. htmlgraph/session_state.py +436 -0
  282. htmlgraph/session_warning.py +2 -1
  283. htmlgraph/sessions/__init__.py +23 -0
  284. htmlgraph/sessions/handoff.py +756 -0
  285. htmlgraph/system_prompts.py +450 -0
  286. htmlgraph/templates/orchestration-view.html +350 -0
  287. htmlgraph/track_builder.py +33 -1
  288. htmlgraph/track_manager.py +38 -0
  289. htmlgraph/transcript.py +18 -5
  290. htmlgraph/validation.py +115 -0
  291. htmlgraph/watch.py +2 -1
  292. htmlgraph/work_type_utils.py +2 -1
  293. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/dashboard.html +2246 -248
  294. {htmlgraph-0.20.1.dist-info → htmlgraph-0.27.5.dist-info}/METADATA +95 -64
  295. htmlgraph-0.27.5.dist-info/RECORD +337 -0
  296. {htmlgraph-0.20.1.dist-info → htmlgraph-0.27.5.dist-info}/entry_points.txt +1 -1
  297. htmlgraph/cli.py +0 -4839
  298. htmlgraph/sdk.py +0 -2359
  299. htmlgraph-0.20.1.dist-info/RECORD +0 -118
  300. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/styles.css +0 -0
  301. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/templates/AGENTS.md.template +0 -0
  302. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/templates/CLAUDE.md.template +0 -0
  303. {htmlgraph-0.20.1.data → htmlgraph-0.27.5.data}/data/htmlgraph/templates/GEMINI.md.template +0 -0
  304. {htmlgraph-0.20.1.dist-info → htmlgraph-0.27.5.dist-info}/WHEEL +0 -0
@@ -0,0 +1,350 @@
1
+ <!-- Orchestration View Component
2
+ Displays agent delegation chains and coordination topology.
3
+ Fetches from /api/orchestration endpoint.
4
+ -->
5
+
6
+ <div id="orchestration-view" class="orchestration-container">
7
+ <div class="orchestration-header">
8
+ <h2>Agent Orchestration</h2>
9
+ <p class="subtitle">Delegation chains and agent coordination</p>
10
+ </div>
11
+
12
+ <div class="orchestration-metrics">
13
+ <div class="metric-card">
14
+ <div class="metric-label">Total Delegations</div>
15
+ <div class="metric-value" id="delegation-count">0</div>
16
+ </div>
17
+ <div class="metric-card">
18
+ <div class="metric-label">Unique Agents</div>
19
+ <div class="metric-value" id="unique-agents">0</div>
20
+ </div>
21
+ <div class="metric-card">
22
+ <div class="metric-label">Active Agents</div>
23
+ <div class="metric-value" id="agent-list">—</div>
24
+ </div>
25
+ </div>
26
+
27
+ <div class="orchestration-chains" id="delegation-chains">
28
+ <div class="empty-state">
29
+ <p>No delegation events recorded yet.</p>
30
+ <p class="hint">Delegation events will appear here when Task() calls are made.</p>
31
+ </div>
32
+ </div>
33
+
34
+ <div class="orchestration-legend">
35
+ <div class="legend-item">
36
+ <span class="status-badge pending"></span>
37
+ <span>Pending</span>
38
+ </div>
39
+ <div class="legend-item">
40
+ <span class="status-badge accepted"></span>
41
+ <span>Accepted</span>
42
+ </div>
43
+ <div class="legend-item">
44
+ <span class="status-badge completed"></span>
45
+ <span>Completed</span>
46
+ </div>
47
+ <div class="legend-item">
48
+ <span class="status-badge failed"></span>
49
+ <span>Failed</span>
50
+ </div>
51
+ </div>
52
+ </div>
53
+
54
+ <style>
55
+ .orchestration-container {
56
+ padding: 2rem;
57
+ background: var(--bg-secondary);
58
+ border: 1px solid var(--border);
59
+ border-radius: 4px;
60
+ }
61
+
62
+ .orchestration-header {
63
+ margin-bottom: 2rem;
64
+ border-bottom: 2px solid var(--border);
65
+ padding-bottom: 1rem;
66
+ }
67
+
68
+ .orchestration-header h2 {
69
+ font-size: 1.5rem;
70
+ color: var(--text-primary);
71
+ margin-bottom: 0.5rem;
72
+ font-weight: 600;
73
+ }
74
+
75
+ .orchestration-header .subtitle {
76
+ color: var(--text-secondary);
77
+ font-size: 0.9rem;
78
+ }
79
+
80
+ .orchestration-metrics {
81
+ display: grid;
82
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
83
+ gap: 1rem;
84
+ margin-bottom: 2rem;
85
+ }
86
+
87
+ .metric-card {
88
+ background: var(--bg-tertiary);
89
+ border: 1px solid var(--border);
90
+ border-radius: 4px;
91
+ padding: 1.5rem;
92
+ text-align: center;
93
+ }
94
+
95
+ .metric-label {
96
+ color: var(--text-secondary);
97
+ font-size: 0.9rem;
98
+ margin-bottom: 0.5rem;
99
+ text-transform: uppercase;
100
+ letter-spacing: 0.05em;
101
+ }
102
+
103
+ .metric-value {
104
+ font-size: 2rem;
105
+ font-weight: 700;
106
+ color: var(--accent);
107
+ font-family: 'JetBrains Mono', monospace;
108
+ }
109
+
110
+ .orchestration-chains {
111
+ margin-bottom: 2rem;
112
+ }
113
+
114
+ .empty-state {
115
+ text-align: center;
116
+ padding: 3rem 1rem;
117
+ color: var(--text-secondary);
118
+ }
119
+
120
+ .empty-state p {
121
+ margin-bottom: 0.5rem;
122
+ }
123
+
124
+ .empty-state .hint {
125
+ font-size: 0.85rem;
126
+ color: var(--text-muted);
127
+ font-style: italic;
128
+ }
129
+
130
+ .delegation-chain {
131
+ margin-bottom: 1.5rem;
132
+ border-left: 3px solid var(--status-active);
133
+ padding-left: 1rem;
134
+ }
135
+
136
+ .chain-from-agent {
137
+ font-weight: 600;
138
+ color: var(--text-primary);
139
+ font-size: 1rem;
140
+ margin-bottom: 0.5rem;
141
+ padding: 0.75rem;
142
+ background: rgba(41, 121, 255, 0.1);
143
+ border-radius: 4px;
144
+ border-left: 3px solid var(--status-active);
145
+ }
146
+
147
+ .chain-delegations {
148
+ margin-top: 0.5rem;
149
+ }
150
+
151
+ .delegation-item {
152
+ display: flex;
153
+ align-items: flex-start;
154
+ gap: 1rem;
155
+ padding: 0.75rem;
156
+ margin-bottom: 0.5rem;
157
+ background: var(--bg-tertiary);
158
+ border-radius: 3px;
159
+ border-left: 3px solid var(--status-active);
160
+ }
161
+
162
+ .delegation-arrow {
163
+ color: var(--text-secondary);
164
+ font-weight: bold;
165
+ min-width: 1rem;
166
+ text-align: center;
167
+ }
168
+
169
+ .delegation-details {
170
+ flex: 1;
171
+ }
172
+
173
+ .delegation-to-agent {
174
+ font-weight: 600;
175
+ color: var(--text-primary);
176
+ font-size: 0.95rem;
177
+ }
178
+
179
+ .delegation-task {
180
+ color: var(--text-secondary);
181
+ font-size: 0.85rem;
182
+ margin: 0.25rem 0;
183
+ font-family: 'JetBrains Mono', monospace;
184
+ }
185
+
186
+ .delegation-timestamp {
187
+ color: var(--text-muted);
188
+ font-size: 0.8rem;
189
+ margin-top: 0.25rem;
190
+ }
191
+
192
+ .status-badge {
193
+ display: inline-block;
194
+ width: 0.75rem;
195
+ height: 0.75rem;
196
+ border-radius: 50%;
197
+ margin-right: 0.5rem;
198
+ }
199
+
200
+ .status-badge.pending {
201
+ background: var(--status-todo);
202
+ }
203
+
204
+ .status-badge.accepted {
205
+ background: var(--status-active);
206
+ }
207
+
208
+ .status-badge.completed {
209
+ background: var(--status-done);
210
+ }
211
+
212
+ .status-badge.failed {
213
+ background: var(--status-blocked);
214
+ }
215
+
216
+ .delegation-status {
217
+ display: inline-flex;
218
+ align-items: center;
219
+ gap: 0.5rem;
220
+ font-size: 0.8rem;
221
+ padding: 0.25rem 0.5rem;
222
+ background: var(--bg-primary);
223
+ border-radius: 3px;
224
+ margin-left: auto;
225
+ text-transform: uppercase;
226
+ }
227
+
228
+ .orchestration-legend {
229
+ display: flex;
230
+ gap: 1.5rem;
231
+ padding: 1rem;
232
+ background: var(--bg-tertiary);
233
+ border-radius: 4px;
234
+ flex-wrap: wrap;
235
+ }
236
+
237
+ .legend-item {
238
+ display: flex;
239
+ align-items: center;
240
+ gap: 0.5rem;
241
+ font-size: 0.85rem;
242
+ color: var(--text-secondary);
243
+ }
244
+ </style>
245
+
246
+ <script>
247
+ function renderOrchestrationView(data) {
248
+ document.getElementById('delegation-count').textContent = data.delegation_count;
249
+ document.getElementById('unique-agents').textContent = data.unique_agents;
250
+ document.getElementById('agent-list').textContent = data.agents.join(', ') || '—';
251
+
252
+ const chainsContainer = document.getElementById('delegation-chains');
253
+
254
+ if (data.delegation_count === 0) {
255
+ chainsContainer.textContent = '';
256
+ const emptyDiv = document.createElement('div');
257
+ emptyDiv.className = 'empty-state';
258
+ emptyDiv.innerHTML = '<p>No delegation events recorded yet.</p><p class="hint">Delegation events will appear here when Task() calls are made.</p>';
259
+ chainsContainer.appendChild(emptyDiv);
260
+ return;
261
+ }
262
+
263
+ chainsContainer.textContent = '';
264
+
265
+ for (const fromAgent in data.delegation_chains) {
266
+ const delegations = data.delegation_chains[fromAgent];
267
+ const chainDiv = document.createElement('div');
268
+ chainDiv.className = 'delegation-chain';
269
+
270
+ const fromAgentDiv = document.createElement('div');
271
+ fromAgentDiv.className = 'chain-from-agent';
272
+ fromAgentDiv.textContent = fromAgent;
273
+ chainDiv.appendChild(fromAgentDiv);
274
+
275
+ const delegationsDiv = document.createElement('div');
276
+ delegationsDiv.className = 'chain-delegations';
277
+
278
+ for (const delegation of delegations) {
279
+ const itemDiv = document.createElement('div');
280
+ itemDiv.className = 'delegation-item';
281
+
282
+ const arrowDiv = document.createElement('div');
283
+ arrowDiv.className = 'delegation-arrow';
284
+ arrowDiv.textContent = '↓';
285
+ itemDiv.appendChild(arrowDiv);
286
+
287
+ const detailsDiv = document.createElement('div');
288
+ detailsDiv.className = 'delegation-details';
289
+
290
+ const toAgentDiv = document.createElement('div');
291
+ toAgentDiv.className = 'delegation-to-agent';
292
+ toAgentDiv.textContent = delegation.to_agent;
293
+ detailsDiv.appendChild(toAgentDiv);
294
+
295
+ const taskDiv = document.createElement('div');
296
+ taskDiv.className = 'delegation-task';
297
+ taskDiv.textContent = 'Task: ' + delegation.task;
298
+ detailsDiv.appendChild(taskDiv);
299
+
300
+ const timeDiv = document.createElement('div');
301
+ timeDiv.className = 'delegation-timestamp';
302
+ try {
303
+ const date = new Date(delegation.timestamp);
304
+ timeDiv.textContent = date.toLocaleString();
305
+ } catch {
306
+ timeDiv.textContent = delegation.timestamp || 'N/A';
307
+ }
308
+ detailsDiv.appendChild(timeDiv);
309
+
310
+ itemDiv.appendChild(detailsDiv);
311
+
312
+ const statusDiv = document.createElement('div');
313
+ statusDiv.className = 'delegation-status';
314
+ const badgeSpan = document.createElement('span');
315
+ badgeSpan.className = 'status-badge ' + (delegation.status || 'pending');
316
+ statusDiv.appendChild(badgeSpan);
317
+ const statusText = document.createTextNode((delegation.status || 'pending').charAt(0).toUpperCase() + (delegation.status || 'pending').slice(1));
318
+ statusDiv.appendChild(statusText);
319
+ itemDiv.appendChild(statusDiv);
320
+
321
+ delegationsDiv.appendChild(itemDiv);
322
+ }
323
+
324
+ chainDiv.appendChild(delegationsDiv);
325
+ chainsContainer.appendChild(chainDiv);
326
+ }
327
+ }
328
+
329
+ async function loadOrchestrationView() {
330
+ try {
331
+ const response = await fetch('/api/orchestration');
332
+ if (!response.ok) {
333
+ console.warn('Orchestration view not available');
334
+ return;
335
+ }
336
+ const data = await response.json();
337
+ renderOrchestrationView(data);
338
+ } catch (error) {
339
+ console.error('Failed to load orchestration view:', error);
340
+ }
341
+ }
342
+
343
+ if (document.readyState === 'loading') {
344
+ document.addEventListener('DOMContentLoaded', loadOrchestrationView);
345
+ } else {
346
+ loadOrchestrationView();
347
+ }
348
+
349
+ setInterval(loadOrchestrationView, 10000);
350
+ </script>
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  """
2
4
  Track Builder and Collection for agent-friendly track creation.
3
5
 
@@ -5,7 +7,6 @@ Note: TrackBuilder has been moved to builders/track.py for better organization.
5
7
  This module now provides TrackCollection and re-exports TrackBuilder for backward compatibility.
6
8
  """
7
9
 
8
- from __future__ import annotations
9
10
 
10
11
  from collections.abc import Iterator
11
12
  from contextlib import contextmanager
@@ -31,6 +32,18 @@ class TrackCollection:
31
32
  self.collection_name = "tracks" # For backward compatibility
32
33
  self.id_prefix = "track"
33
34
  self._graph: HtmlGraph | None = None # Lazy-loaded
35
+ self._ref_manager: Any = None # Set by SDK during initialization
36
+
37
+ def set_ref_manager(self, ref_manager: Any) -> None:
38
+ """
39
+ Set the ref manager for this collection.
40
+
41
+ Called by SDK during initialization to enable short ref support.
42
+
43
+ Args:
44
+ ref_manager: RefManager instance from SDK
45
+ """
46
+ self._ref_manager = ref_manager
34
47
 
35
48
  def _ensure_graph(self) -> HtmlGraph:
36
49
  """Lazy-load the graph for tracks with multi-pattern support."""
@@ -113,6 +126,25 @@ class TrackCollection:
113
126
  # Auto-save on exit
114
127
  graph.update(node)
115
128
 
129
+ def create(self, title: str) -> TrackBuilder:
130
+ """
131
+ Create a new track with fluent interface.
132
+
133
+ Args:
134
+ title: Track title
135
+
136
+ Returns:
137
+ TrackBuilder for method chaining
138
+
139
+ Example:
140
+ track = sdk.tracks.create("Multi-Agent Collaboration") \\
141
+ .set_priority("high") \\
142
+ .save()
143
+ """
144
+ builder = TrackBuilder(self._sdk)
145
+ builder._title = title
146
+ return builder
147
+
116
148
  def builder(self) -> TrackBuilder:
117
149
  """
118
150
  Create a new track builder with fluent interface.
@@ -338,6 +338,44 @@ class TrackManager:
338
338
  track_id=track_id,
339
339
  )
340
340
 
341
+ def load_track(self, track_id: str) -> Track | None:
342
+ """
343
+ Load a track from disk.
344
+
345
+ Supports both consolidated (single .html file) and directory-based tracks.
346
+
347
+ Args:
348
+ track_id: Track ID
349
+
350
+ Returns:
351
+ Track instance or None if not found
352
+ """
353
+ track_path = self.get_track_path(track_id)
354
+ if track_path is None:
355
+ return None
356
+
357
+ # For now, return a basic Track instance
358
+ # TODO: Parse HTML back to Track using justhtml
359
+ if track_path.is_file():
360
+ # Consolidated format - single file
361
+ return Track(
362
+ id=track_id,
363
+ title=f"Track {track_id}",
364
+ description="Loaded from consolidated format",
365
+ )
366
+ else:
367
+ # Directory format - check for spec and plan
368
+ spec_exists = (track_path / "spec.html").exists()
369
+ plan_exists = (track_path / "plan.html").exists()
370
+
371
+ return Track(
372
+ id=track_id,
373
+ title=f"Track {track_id}",
374
+ description="Loaded from directory format",
375
+ has_spec=spec_exists,
376
+ has_plan=plan_exists,
377
+ )
378
+
341
379
  def list_tracks(self) -> list[str]:
342
380
  """
343
381
  List all track IDs.
htmlgraph/transcript.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  """
2
4
  Claude Code Transcript Integration.
3
5
 
@@ -21,7 +23,6 @@ References:
21
23
  - https://github.com/simonw/claude-code-transcripts
22
24
  """
23
25
 
24
- from __future__ import annotations
25
26
 
26
27
  import json
27
28
  from collections.abc import Iterator
@@ -588,14 +589,26 @@ class TranscriptReader:
588
589
  Returns:
589
590
  List of TranscriptSession objects, newest first
590
591
  """
592
+ from datetime import timezone
593
+
594
+ def normalize_dt(dt: datetime | None) -> datetime:
595
+ """Normalize datetime to UTC for comparison."""
596
+ if dt is None:
597
+ return datetime.min.replace(tzinfo=timezone.utc)
598
+ if dt.tzinfo is None:
599
+ # Assume naive datetimes are UTC
600
+ return dt.replace(tzinfo=timezone.utc)
601
+ return dt.astimezone(timezone.utc)
602
+
591
603
  sessions: list[TranscriptSession] = []
592
604
 
593
605
  for path in self.list_transcript_files(project_path):
594
606
  session = self.read_transcript(path)
595
607
 
596
608
  # Filter by time
597
- if since and session.started_at and session.started_at < since:
598
- continue
609
+ if since and session.started_at:
610
+ if normalize_dt(session.started_at) < normalize_dt(since):
611
+ continue
599
612
 
600
613
  sessions.append(session)
601
614
 
@@ -604,8 +617,8 @@ class TranscriptReader:
604
617
  if deduplicate and sessions:
605
618
  sessions = self._deduplicate_context_snapshots(sessions)
606
619
 
607
- # Sort by start time, newest first
608
- sessions.sort(key=lambda s: s.started_at or datetime.min, reverse=True)
620
+ # Sort by start time, newest first (normalize for comparison)
621
+ sessions.sort(key=lambda s: normalize_dt(s.started_at), reverse=True)
609
622
 
610
623
  if limit:
611
624
  sessions = sessions[:limit]
@@ -0,0 +1,115 @@
1
+ """
2
+ Rich CLI validation error formatting and utilities.
3
+
4
+ Provides beautiful error display for Pydantic validation failures.
5
+ """
6
+
7
+ from collections.abc import Callable
8
+ from typing import TypeVar
9
+
10
+ from pydantic import ValidationError
11
+ from rich.console import Console
12
+
13
+ console = Console()
14
+
15
+ T = TypeVar("T")
16
+
17
+
18
+ def display_validation_error(error: ValidationError) -> None:
19
+ """
20
+ Display a Pydantic validation error in Rich format.
21
+
22
+ Args:
23
+ error: ValidationError from Pydantic model validation
24
+
25
+ Example:
26
+ try:
27
+ input_data = FeatureCreateInput(title="", priority="invalid")
28
+ except ValidationError as e:
29
+ display_validation_error(e)
30
+ """
31
+ console.print("[red]✗ Validation Error[/red]")
32
+ console.print()
33
+
34
+ for err in error.errors():
35
+ field = ".".join(str(loc) for loc in err["loc"])
36
+ msg = err["msg"]
37
+ error_type = err["type"]
38
+
39
+ # Color code by error type for better UX
40
+ if "at least" in msg.lower() or "at most" in msg.lower():
41
+ # Length/range constraint violation
42
+ console.print(f" [yellow]{field}:[/yellow] {msg}")
43
+ elif "must be" in msg.lower() or "is not valid" in msg.lower():
44
+ # Type/value constraint violation
45
+ console.print(f" [cyan]{field}:[/cyan] {msg}")
46
+ elif error_type == "string_pattern":
47
+ # Pattern validation failed
48
+ console.print(f" [magenta]{field}:[/magenta] {msg}")
49
+ else:
50
+ # Generic validation error
51
+ console.print(f" [red]{field}:[/red] {msg}")
52
+
53
+ console.print()
54
+
55
+
56
+ def validate_input(
57
+ validator_class: type[T],
58
+ **kwargs: object,
59
+ ) -> T | None:
60
+ """
61
+ Validate input and display rich error messages on failure.
62
+
63
+ Args:
64
+ validator_class: Pydantic model class to validate against
65
+ **kwargs: Input data to validate
66
+
67
+ Returns:
68
+ Validated model instance, or None if validation failed
69
+
70
+ Example:
71
+ input_data = validate_input(FeatureCreateInput, title="My Feature", priority="high")
72
+ if input_data is None:
73
+ sys.exit(1)
74
+ # Use input_data.title, input_data.priority, etc.
75
+ """
76
+ try:
77
+ return validator_class(**kwargs)
78
+ except ValidationError as e:
79
+ display_validation_error(e)
80
+ return None
81
+
82
+
83
+ def wrap_command_validation(func: Callable[..., None]) -> Callable[..., None]:
84
+ """
85
+ Decorator to wrap CLI command functions with validation error handling.
86
+
87
+ This decorator catches ValidationError and displays it in Rich format,
88
+ then exits gracefully.
89
+
90
+ Args:
91
+ func: CLI command function
92
+
93
+ Returns:
94
+ Wrapped function with validation error handling
95
+
96
+ Example:
97
+ @wrap_command_validation
98
+ def cmd_feature_create(args: argparse.Namespace) -> None:
99
+ input_data = FeatureCreateInput(
100
+ title=args.title,
101
+ priority=args.priority
102
+ )
103
+ # Rest of command logic
104
+ """
105
+
106
+ def wrapper(*args: object, **kwargs: object) -> None:
107
+ import sys
108
+
109
+ try:
110
+ return func(*args, **kwargs)
111
+ except ValidationError as e:
112
+ display_validation_error(e)
113
+ sys.exit(1)
114
+
115
+ return wrapper
htmlgraph/watch.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  """
2
4
  File-change watcher for HtmlGraph.
3
5
 
@@ -7,7 +9,6 @@ native "PostToolUse" hooks (e.g. editors/agents that write files directly).
7
9
  It batches filesystem changes and records them as activity events.
8
10
  """
9
11
 
10
- from __future__ import annotations
11
12
 
12
13
  import os
13
14
  import time
@@ -1,10 +1,11 @@
1
+ from __future__ import annotations
2
+
1
3
  """
2
4
  Utility functions for work type inference and classification.
3
5
 
4
6
  Provides automatic work type detection based on active work items.
5
7
  """
6
8
 
7
- from __future__ import annotations
8
9
 
9
10
  from typing import TYPE_CHECKING
10
11