htmlgraph 0.24.1__py3-none-any.whl → 0.25.0__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 (103) hide show
  1. htmlgraph/__init__.py +20 -1
  2. htmlgraph/agent_detection.py +26 -10
  3. htmlgraph/analytics/cross_session.py +4 -3
  4. htmlgraph/analytics/work_type.py +52 -16
  5. htmlgraph/analytics_index.py +51 -19
  6. htmlgraph/api/__init__.py +3 -0
  7. htmlgraph/api/main.py +2115 -0
  8. htmlgraph/api/static/htmx.min.js +1 -0
  9. htmlgraph/api/static/style-redesign.css +1344 -0
  10. htmlgraph/api/static/style.css +1079 -0
  11. htmlgraph/api/templates/dashboard-redesign.html +812 -0
  12. htmlgraph/api/templates/dashboard.html +783 -0
  13. htmlgraph/api/templates/partials/activity-feed-hierarchical.html +326 -0
  14. htmlgraph/api/templates/partials/activity-feed.html +570 -0
  15. htmlgraph/api/templates/partials/agents-redesign.html +317 -0
  16. htmlgraph/api/templates/partials/agents.html +317 -0
  17. htmlgraph/api/templates/partials/event-traces.html +373 -0
  18. htmlgraph/api/templates/partials/features-kanban-redesign.html +509 -0
  19. htmlgraph/api/templates/partials/features.html +509 -0
  20. htmlgraph/api/templates/partials/metrics-redesign.html +346 -0
  21. htmlgraph/api/templates/partials/metrics.html +346 -0
  22. htmlgraph/api/templates/partials/orchestration-redesign.html +443 -0
  23. htmlgraph/api/templates/partials/orchestration.html +163 -0
  24. htmlgraph/api/templates/partials/spawners.html +375 -0
  25. htmlgraph/atomic_ops.py +560 -0
  26. htmlgraph/builders/base.py +55 -1
  27. htmlgraph/builders/bug.py +17 -2
  28. htmlgraph/builders/chore.py +17 -2
  29. htmlgraph/builders/epic.py +17 -2
  30. htmlgraph/builders/feature.py +25 -2
  31. htmlgraph/builders/phase.py +17 -2
  32. htmlgraph/builders/spike.py +27 -2
  33. htmlgraph/builders/track.py +14 -0
  34. htmlgraph/cigs/__init__.py +4 -0
  35. htmlgraph/cigs/reporter.py +818 -0
  36. htmlgraph/cli.py +1427 -401
  37. htmlgraph/cli_commands/__init__.py +1 -0
  38. htmlgraph/cli_commands/feature.py +195 -0
  39. htmlgraph/cli_framework.py +115 -0
  40. htmlgraph/collections/__init__.py +2 -0
  41. htmlgraph/collections/base.py +21 -0
  42. htmlgraph/collections/session.py +189 -0
  43. htmlgraph/collections/spike.py +7 -1
  44. htmlgraph/collections/task_delegation.py +236 -0
  45. htmlgraph/collections/traces.py +482 -0
  46. htmlgraph/config.py +113 -0
  47. htmlgraph/converter.py +41 -0
  48. htmlgraph/cost_analysis/__init__.py +5 -0
  49. htmlgraph/cost_analysis/analyzer.py +438 -0
  50. htmlgraph/dashboard.html +3315 -492
  51. htmlgraph-0.24.1.data/data/htmlgraph/dashboard.html → htmlgraph/dashboard.html.backup +2246 -248
  52. htmlgraph/dashboard.html.bak +7181 -0
  53. htmlgraph/dashboard.html.bak2 +7231 -0
  54. htmlgraph/dashboard.html.bak3 +7232 -0
  55. htmlgraph/db/__init__.py +38 -0
  56. htmlgraph/db/queries.py +790 -0
  57. htmlgraph/db/schema.py +1334 -0
  58. htmlgraph/deploy.py +26 -27
  59. htmlgraph/docs/API_REFERENCE.md +841 -0
  60. htmlgraph/docs/HTTP_API.md +750 -0
  61. htmlgraph/docs/INTEGRATION_GUIDE.md +752 -0
  62. htmlgraph/docs/ORCHESTRATION_PATTERNS.md +710 -0
  63. htmlgraph/docs/README.md +533 -0
  64. htmlgraph/docs/version_check.py +3 -1
  65. htmlgraph/error_handler.py +544 -0
  66. htmlgraph/event_log.py +2 -0
  67. htmlgraph/hooks/__init__.py +8 -0
  68. htmlgraph/hooks/bootstrap.py +169 -0
  69. htmlgraph/hooks/context.py +271 -0
  70. htmlgraph/hooks/drift_handler.py +521 -0
  71. htmlgraph/hooks/event_tracker.py +405 -15
  72. htmlgraph/hooks/post_tool_use_handler.py +257 -0
  73. htmlgraph/hooks/pretooluse.py +476 -6
  74. htmlgraph/hooks/prompt_analyzer.py +648 -0
  75. htmlgraph/hooks/session_handler.py +583 -0
  76. htmlgraph/hooks/state_manager.py +501 -0
  77. htmlgraph/hooks/subagent_stop.py +309 -0
  78. htmlgraph/hooks/task_enforcer.py +39 -0
  79. htmlgraph/models.py +111 -15
  80. htmlgraph/operations/fastapi_server.py +230 -0
  81. htmlgraph/orchestration/headless_spawner.py +22 -14
  82. htmlgraph/pydantic_models.py +476 -0
  83. htmlgraph/quality_gates.py +350 -0
  84. htmlgraph/repo_hash.py +511 -0
  85. htmlgraph/sdk.py +348 -10
  86. htmlgraph/server.py +194 -0
  87. htmlgraph/session_hooks.py +300 -0
  88. htmlgraph/session_manager.py +131 -1
  89. htmlgraph/session_registry.py +587 -0
  90. htmlgraph/session_state.py +436 -0
  91. htmlgraph/system_prompts.py +449 -0
  92. htmlgraph/templates/orchestration-view.html +350 -0
  93. htmlgraph/track_builder.py +19 -0
  94. htmlgraph/validation.py +115 -0
  95. htmlgraph-0.25.0.data/data/htmlgraph/dashboard.html +7417 -0
  96. {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/METADATA +91 -64
  97. {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/RECORD +103 -42
  98. {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/styles.css +0 -0
  99. {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/templates/AGENTS.md.template +0 -0
  100. {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/templates/CLAUDE.md.template +0 -0
  101. {htmlgraph-0.24.1.data → htmlgraph-0.25.0.data}/data/htmlgraph/templates/GEMINI.md.template +0 -0
  102. {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/WHEEL +0 -0
  103. {htmlgraph-0.24.1.dist-info → htmlgraph-0.25.0.dist-info}/entry_points.txt +0 -0
@@ -8,10 +8,10 @@ child features and milestones.
8
8
  from __future__ import annotations
9
9
 
10
10
  from datetime import date
11
- from typing import TYPE_CHECKING
11
+ from typing import TYPE_CHECKING, Any
12
12
 
13
13
  if TYPE_CHECKING:
14
- pass
14
+ from htmlgraph.sdk import SDK
15
15
 
16
16
  from htmlgraph.builders.base import BaseBuilder
17
17
 
@@ -38,6 +38,21 @@ class EpicBuilder(BaseBuilder["EpicBuilder"]):
38
38
 
39
39
  node_type = "epic"
40
40
 
41
+ def __init__(self, sdk: SDK, title: str, **kwargs: Any):
42
+ """Initialize epic builder with agent attribution."""
43
+ super().__init__(sdk, title, **kwargs)
44
+ # Auto-assign agent from SDK for work tracking
45
+ if sdk._agent_id:
46
+ self._data["agent_assigned"] = sdk._agent_id
47
+ elif "agent_assigned" not in self._data:
48
+ # Log warning if agent not assigned (defensive check)
49
+ import logging
50
+
51
+ logging.warning(
52
+ f"Creating epic '{self._data.get('title', 'Unknown')}' without agent attribution. "
53
+ "Pass agent='name' to SDK() initialization."
54
+ )
55
+
41
56
  def add_child_feature(self, feature_id: str) -> EpicBuilder:
42
57
  """
43
58
  Add a feature as a child of this epic.
@@ -7,10 +7,10 @@ capability management.
7
7
 
8
8
  from __future__ import annotations
9
9
 
10
- from typing import TYPE_CHECKING
10
+ from typing import TYPE_CHECKING, Any
11
11
 
12
12
  if TYPE_CHECKING:
13
- pass
13
+ from htmlgraph.sdk import SDK
14
14
 
15
15
  from htmlgraph.builders.base import BaseBuilder
16
16
 
@@ -34,6 +34,29 @@ class FeatureBuilder(BaseBuilder["FeatureBuilder"]):
34
34
 
35
35
  node_type = "feature"
36
36
 
37
+ def __init__(self, sdk: SDK, title: str, **kwargs: Any):
38
+ """Initialize feature builder with agent attribution and validation."""
39
+ # Validate title before creating builder
40
+
41
+ stripped_title = title.strip() if title else ""
42
+ if not stripped_title:
43
+ raise ValueError("Feature title cannot be empty or whitespace only")
44
+ if len(stripped_title) < 3:
45
+ raise ValueError("Feature title must be at least 3 characters")
46
+
47
+ super().__init__(sdk, title, **kwargs)
48
+ # Auto-assign agent from SDK for work tracking
49
+ if sdk._agent_id:
50
+ self._data["agent_assigned"] = sdk._agent_id
51
+ elif "agent_assigned" not in self._data:
52
+ # Log warning if agent not assigned (defensive check)
53
+ import logging
54
+
55
+ logging.warning(
56
+ f"Creating feature '{self._data.get('title', 'Unknown')}' without agent attribution. "
57
+ "Pass agent='name' to SDK() initialization."
58
+ )
59
+
37
60
  def set_required_capabilities(self, capabilities: list[str]) -> FeatureBuilder:
38
61
  """
39
62
  Set required capabilities for this feature.
@@ -8,10 +8,10 @@ phase ordering and dependencies.
8
8
  from __future__ import annotations
9
9
 
10
10
  from datetime import date
11
- from typing import TYPE_CHECKING
11
+ from typing import TYPE_CHECKING, Any
12
12
 
13
13
  if TYPE_CHECKING:
14
- pass
14
+ from htmlgraph.sdk import SDK
15
15
 
16
16
  from htmlgraph.builders.base import BaseBuilder
17
17
 
@@ -37,6 +37,21 @@ class PhaseBuilder(BaseBuilder["PhaseBuilder"]):
37
37
 
38
38
  node_type = "phase"
39
39
 
40
+ def __init__(self, sdk: SDK, title: str, **kwargs: Any):
41
+ """Initialize phase builder with agent attribution."""
42
+ super().__init__(sdk, title, **kwargs)
43
+ # Auto-assign agent from SDK for work tracking
44
+ if sdk._agent_id:
45
+ self._data["agent_assigned"] = sdk._agent_id
46
+ elif "agent_assigned" not in self._data:
47
+ # Log warning if agent not assigned (defensive check)
48
+ import logging
49
+
50
+ logging.warning(
51
+ f"Creating phase '{self._data.get('title', 'Unknown')}' without agent attribution. "
52
+ "Pass agent='name' to SDK() initialization."
53
+ )
54
+
40
55
  def set_phase_number(self, number: int) -> PhaseBuilder:
41
56
  """
42
57
  Set the phase number for ordering.
@@ -48,6 +48,18 @@ class SpikeBuilder(BaseBuilder["SpikeBuilder"]):
48
48
  self._data["spike_type"] = SpikeType.GENERAL
49
49
  if "timebox_hours" not in self._data:
50
50
  self._data["timebox_hours"] = 4
51
+ # Auto-assign agent from SDK (critical for work tracking)
52
+ if sdk._agent_id:
53
+ self._data["agent_assigned"] = sdk._agent_id
54
+ elif "agent_assigned" not in self._data:
55
+ # This should never happen now because SDK enforces agent parameter,
56
+ # but log warning if it does occur (for debugging)
57
+ import logging
58
+
59
+ logging.warning(
60
+ f"Creating spike '{self._data.get('title', 'Unknown')}' without agent attribution. "
61
+ "This will make work tracking impossible. Pass agent='name' to SDK() initialization."
62
+ )
51
63
 
52
64
  def set_spike_type(self, spike_type: SpikeType) -> SpikeBuilder:
53
65
  """
@@ -86,15 +98,28 @@ class SpikeBuilder(BaseBuilder["SpikeBuilder"]):
86
98
  Set the findings/learnings from spike investigation.
87
99
 
88
100
  Args:
89
- findings: Summary of what was learned
101
+ findings: Summary of what was learned (must be non-empty, min 10 chars)
90
102
 
91
103
  Returns:
92
104
  Self for method chaining
93
105
 
106
+ Raises:
107
+ ValueError: If findings are empty or too short
108
+
94
109
  Example:
95
110
  >>> spike.set_findings("OAuth2 is best fit. Recommend Auth0.")
96
111
  """
97
- self._data["findings"] = findings
112
+ # Validate findings quality
113
+ stripped = findings.strip() if findings else ""
114
+ if not stripped:
115
+ raise ValueError(
116
+ "Findings cannot be empty. Provide meaningful investigation results."
117
+ )
118
+ if len(stripped) < 10:
119
+ raise ValueError(
120
+ "Findings must be at least 10 characters. Provide detailed results."
121
+ )
122
+ self._data["findings"] = stripped
98
123
  return self
99
124
 
100
125
  def set_decision(self, decision: str) -> SpikeBuilder:
@@ -679,3 +679,17 @@ class TrackBuilder:
679
679
  print(f" - Plan with {len(self._plan_phases)} phases, {total_tasks} tasks")
680
680
 
681
681
  return track
682
+
683
+ def save(self) -> Track:
684
+ """
685
+ Save/create the track (alias for create()).
686
+
687
+ Provides API consistency with other builders.
688
+
689
+ Returns:
690
+ Track object that was created
691
+
692
+ Example:
693
+ track = sdk.tracks.create("My Track").save()
694
+ """
695
+ return self.create()
@@ -10,6 +10,7 @@ Modules:
10
10
  - cost: Cost calculation and efficiency metrics
11
11
  - patterns: Anti-pattern detection and analysis
12
12
  - autonomy: Autonomy level management
13
+ - reporter: Dashboard generation for cost analysis
13
14
  """
14
15
 
15
16
  from htmlgraph.cigs.autonomy import AutonomyRecommender
@@ -42,6 +43,7 @@ from htmlgraph.cigs.patterns import (
42
43
  detect_patterns,
43
44
  )
44
45
  from htmlgraph.cigs.posttool_analyzer import CIGSPostToolAnalyzer
46
+ from htmlgraph.cigs.reporter import CostReporter
45
47
  from htmlgraph.cigs.tracker import ViolationTracker
46
48
 
47
49
  __all__ = [
@@ -74,4 +76,6 @@ __all__ = [
74
76
  "ViolationTracker",
75
77
  # PostTool Analysis
76
78
  "CIGSPostToolAnalyzer",
79
+ # Reporter
80
+ "CostReporter",
77
81
  ]