htmlgraph 0.26.24__py3-none-any.whl → 0.27.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.
- htmlgraph/__init__.py +23 -1
- htmlgraph/__init__.pyi +123 -0
- htmlgraph/agent_registry.py +2 -1
- htmlgraph/analytics/cli.py +3 -3
- htmlgraph/analytics/cost_analyzer.py +5 -1
- htmlgraph/analytics/cross_session.py +13 -9
- htmlgraph/analytics/dependency.py +10 -6
- htmlgraph/analytics/work_type.py +15 -11
- htmlgraph/analytics_index.py +2 -1
- htmlgraph/api/main.py +114 -51
- htmlgraph/api/templates/dashboard-redesign.html +3 -3
- htmlgraph/api/templates/dashboard.html +3 -3
- htmlgraph/api/templates/partials/work-items.html +613 -0
- htmlgraph/attribute_index.py +2 -1
- htmlgraph/builders/base.py +2 -1
- htmlgraph/builders/bug.py +2 -1
- htmlgraph/builders/chore.py +2 -1
- htmlgraph/builders/epic.py +2 -1
- htmlgraph/builders/feature.py +2 -1
- htmlgraph/builders/insight.py +2 -1
- htmlgraph/builders/metric.py +2 -1
- htmlgraph/builders/pattern.py +2 -1
- htmlgraph/builders/phase.py +2 -1
- htmlgraph/builders/spike.py +2 -1
- htmlgraph/builders/track.py +28 -1
- htmlgraph/cli/analytics.py +2 -1
- htmlgraph/cli/base.py +33 -8
- htmlgraph/cli/core.py +2 -1
- htmlgraph/cli/main.py +2 -1
- htmlgraph/cli/models.py +2 -1
- htmlgraph/cli/templates/cost_dashboard.py +2 -1
- htmlgraph/cli/work/__init__.py +76 -1
- htmlgraph/cli/work/browse.py +115 -0
- htmlgraph/cli/work/features.py +2 -1
- htmlgraph/cli/work/orchestration.py +2 -1
- htmlgraph/cli/work/report.py +2 -1
- htmlgraph/cli/work/sessions.py +2 -1
- htmlgraph/cli/work/snapshot.py +559 -0
- htmlgraph/cli/work/tracks.py +2 -1
- htmlgraph/collections/base.py +43 -4
- htmlgraph/collections/bug.py +2 -1
- htmlgraph/collections/chore.py +2 -1
- htmlgraph/collections/epic.py +2 -1
- htmlgraph/collections/feature.py +2 -1
- htmlgraph/collections/insight.py +2 -1
- htmlgraph/collections/metric.py +2 -1
- htmlgraph/collections/pattern.py +2 -1
- htmlgraph/collections/phase.py +2 -1
- htmlgraph/collections/session.py +12 -7
- htmlgraph/collections/spike.py +6 -1
- htmlgraph/collections/task_delegation.py +7 -2
- htmlgraph/collections/todo.py +14 -1
- htmlgraph/collections/traces.py +15 -10
- htmlgraph/context_analytics.py +2 -1
- htmlgraph/converter.py +11 -0
- htmlgraph/dependency_models.py +2 -1
- htmlgraph/edge_index.py +2 -1
- htmlgraph/event_log.py +81 -66
- htmlgraph/event_migration.py +2 -1
- htmlgraph/file_watcher.py +12 -8
- htmlgraph/find_api.py +2 -1
- htmlgraph/git_events.py +6 -2
- htmlgraph/hooks/cigs_pretool_enforcer.py +5 -1
- htmlgraph/hooks/drift_handler.py +3 -3
- htmlgraph/hooks/event_tracker.py +40 -61
- htmlgraph/hooks/installer.py +5 -1
- htmlgraph/hooks/orchestrator.py +92 -14
- htmlgraph/hooks/orchestrator_reflector.py +4 -0
- htmlgraph/hooks/post_tool_use_failure.py +7 -3
- htmlgraph/hooks/posttooluse.py +4 -0
- htmlgraph/hooks/prompt_analyzer.py +5 -5
- htmlgraph/hooks/session_handler.py +5 -2
- htmlgraph/hooks/session_summary.py +6 -2
- htmlgraph/hooks/validator.py +8 -4
- htmlgraph/ids.py +2 -1
- htmlgraph/learning.py +2 -1
- htmlgraph/mcp_server.py +2 -1
- htmlgraph/models.py +18 -1
- htmlgraph/operations/analytics.py +2 -1
- htmlgraph/operations/bootstrap.py +2 -1
- htmlgraph/operations/events.py +2 -1
- htmlgraph/operations/fastapi_server.py +2 -1
- htmlgraph/operations/hooks.py +2 -1
- htmlgraph/operations/initialization.py +2 -1
- htmlgraph/operations/server.py +2 -1
- htmlgraph/orchestration/__init__.py +4 -0
- htmlgraph/orchestration/claude_launcher.py +23 -20
- htmlgraph/orchestration/command_builder.py +2 -1
- htmlgraph/orchestration/headless_spawner.py +6 -2
- htmlgraph/orchestration/model_selection.py +7 -3
- htmlgraph/orchestration/plugin_manager.py +25 -21
- htmlgraph/orchestration/spawner_event_tracker.py +383 -0
- htmlgraph/orchestration/spawners/claude.py +5 -2
- htmlgraph/orchestration/spawners/codex.py +12 -19
- htmlgraph/orchestration/spawners/copilot.py +13 -18
- htmlgraph/orchestration/spawners/gemini.py +12 -19
- htmlgraph/orchestration/subprocess_runner.py +6 -3
- htmlgraph/orchestration/task_coordination.py +16 -8
- htmlgraph/orchestrator.py +2 -1
- htmlgraph/parallel.py +2 -1
- htmlgraph/query_builder.py +2 -1
- htmlgraph/reflection.py +2 -1
- htmlgraph/refs.py +344 -0
- htmlgraph/repo_hash.py +2 -1
- htmlgraph/sdk/__init__.py +398 -0
- htmlgraph/sdk/__init__.pyi +14 -0
- htmlgraph/sdk/analytics/__init__.py +19 -0
- htmlgraph/sdk/analytics/engine.py +155 -0
- htmlgraph/sdk/analytics/helpers.py +178 -0
- htmlgraph/sdk/analytics/registry.py +109 -0
- htmlgraph/sdk/base.py +484 -0
- htmlgraph/sdk/constants.py +216 -0
- htmlgraph/sdk/core.pyi +308 -0
- htmlgraph/sdk/discovery.py +120 -0
- htmlgraph/sdk/help/__init__.py +12 -0
- htmlgraph/sdk/help/mixin.py +699 -0
- htmlgraph/sdk/mixins/__init__.py +15 -0
- htmlgraph/sdk/mixins/attribution.py +113 -0
- htmlgraph/sdk/mixins/mixin.py +410 -0
- htmlgraph/sdk/operations/__init__.py +12 -0
- htmlgraph/sdk/operations/mixin.py +427 -0
- htmlgraph/sdk/orchestration/__init__.py +17 -0
- htmlgraph/sdk/orchestration/coordinator.py +203 -0
- htmlgraph/sdk/orchestration/spawner.py +204 -0
- htmlgraph/sdk/planning/__init__.py +19 -0
- htmlgraph/sdk/planning/bottlenecks.py +93 -0
- htmlgraph/sdk/planning/mixin.py +211 -0
- htmlgraph/sdk/planning/parallel.py +186 -0
- htmlgraph/sdk/planning/queue.py +210 -0
- htmlgraph/sdk/planning/recommendations.py +87 -0
- htmlgraph/sdk/planning/smart_planning.py +319 -0
- htmlgraph/sdk/session/__init__.py +19 -0
- htmlgraph/sdk/session/continuity.py +57 -0
- htmlgraph/sdk/session/handoff.py +110 -0
- htmlgraph/sdk/session/info.py +309 -0
- htmlgraph/sdk/session/manager.py +103 -0
- htmlgraph/server.py +21 -17
- htmlgraph/session_manager.py +1 -7
- htmlgraph/session_warning.py +2 -1
- htmlgraph/sessions/handoff.py +10 -3
- htmlgraph/system_prompts.py +2 -1
- htmlgraph/track_builder.py +14 -1
- htmlgraph/transcript.py +2 -1
- htmlgraph/watch.py +2 -1
- htmlgraph/work_type_utils.py +2 -1
- {htmlgraph-0.26.24.dist-info → htmlgraph-0.27.0.dist-info}/METADATA +15 -1
- {htmlgraph-0.26.24.dist-info → htmlgraph-0.27.0.dist-info}/RECORD +154 -117
- htmlgraph/sdk.py +0 -3430
- {htmlgraph-0.26.24.data → htmlgraph-0.27.0.data}/data/htmlgraph/dashboard.html +0 -0
- {htmlgraph-0.26.24.data → htmlgraph-0.27.0.data}/data/htmlgraph/styles.css +0 -0
- {htmlgraph-0.26.24.data → htmlgraph-0.27.0.data}/data/htmlgraph/templates/AGENTS.md.template +0 -0
- {htmlgraph-0.26.24.data → htmlgraph-0.27.0.data}/data/htmlgraph/templates/CLAUDE.md.template +0 -0
- {htmlgraph-0.26.24.data → htmlgraph-0.27.0.data}/data/htmlgraph/templates/GEMINI.md.template +0 -0
- {htmlgraph-0.26.24.dist-info → htmlgraph-0.27.0.dist-info}/WHEEL +0 -0
- {htmlgraph-0.26.24.dist-info → htmlgraph-0.27.0.dist-info}/entry_points.txt +0 -0
htmlgraph/__init__.py
CHANGED
|
@@ -5,6 +5,28 @@ A lightweight graph database framework using HTML files as nodes,
|
|
|
5
5
|
hyperlinks as edges, and CSS selectors as the query language.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
import logging
|
|
9
|
+
|
|
10
|
+
from rich.console import Console
|
|
11
|
+
from rich.logging import RichHandler
|
|
12
|
+
|
|
13
|
+
# Configure Rich logging for entire SDK
|
|
14
|
+
# CRITICAL: Use stderr=True to prevent pollution of stdout (hooks output JSON to stdout)
|
|
15
|
+
logging.basicConfig(
|
|
16
|
+
handlers=[
|
|
17
|
+
RichHandler(
|
|
18
|
+
console=Console(stderr=True),
|
|
19
|
+
show_time=True,
|
|
20
|
+
show_level=True,
|
|
21
|
+
rich_tracebacks=True,
|
|
22
|
+
)
|
|
23
|
+
],
|
|
24
|
+
level=logging.INFO,
|
|
25
|
+
format="%(message)s",
|
|
26
|
+
datefmt="[%X]",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# SDK now lives in sdk/core.py - clean import from sdk package
|
|
8
30
|
from htmlgraph.agent_detection import detect_agent_name, get_agent_display_name
|
|
9
31
|
from htmlgraph.agents import AgentInterface
|
|
10
32
|
from htmlgraph.analytics import Analytics, DependencyAnalytics
|
|
@@ -96,7 +118,7 @@ from htmlgraph.types import (
|
|
|
96
118
|
)
|
|
97
119
|
from htmlgraph.work_type_utils import infer_work_type, infer_work_type_from_id
|
|
98
120
|
|
|
99
|
-
__version__ = "0.
|
|
121
|
+
__version__ = "0.27.0"
|
|
100
122
|
__all__ = [
|
|
101
123
|
# Exceptions
|
|
102
124
|
"HtmlGraphError",
|
htmlgraph/__init__.pyi
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Type stub for htmlgraph package.
|
|
3
|
+
|
|
4
|
+
This stub provides type information for mypy when the SDK class
|
|
5
|
+
is loaded dynamically via importlib at runtime.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from htmlgraph.agent_detection import detect_agent_name as detect_agent_name
|
|
9
|
+
from htmlgraph.agent_detection import get_agent_display_name as get_agent_display_name
|
|
10
|
+
from htmlgraph.agents import AgentInterface as AgentInterface
|
|
11
|
+
from htmlgraph.analytics import Analytics as Analytics
|
|
12
|
+
|
|
13
|
+
# Analytics
|
|
14
|
+
from htmlgraph.analytics import DependencyAnalytics as DependencyAnalytics
|
|
15
|
+
from htmlgraph.atomic_ops import AtomicFileWriter as AtomicFileWriter
|
|
16
|
+
from htmlgraph.atomic_ops import DirectoryLocker as DirectoryLocker
|
|
17
|
+
from htmlgraph.atomic_ops import atomic_rename as atomic_rename
|
|
18
|
+
from htmlgraph.atomic_ops import (
|
|
19
|
+
cleanup_orphaned_temp_files as cleanup_orphaned_temp_files,
|
|
20
|
+
)
|
|
21
|
+
from htmlgraph.atomic_ops import safe_temp_file as safe_temp_file
|
|
22
|
+
from htmlgraph.atomic_ops import validate_atomic_write as validate_atomic_write
|
|
23
|
+
from htmlgraph.builders import BaseBuilder as BaseBuilder
|
|
24
|
+
from htmlgraph.builders import FeatureBuilder as FeatureBuilder
|
|
25
|
+
from htmlgraph.builders import SpikeBuilder as SpikeBuilder
|
|
26
|
+
from htmlgraph.collections import BaseCollection as BaseCollection
|
|
27
|
+
|
|
28
|
+
# Collections
|
|
29
|
+
from htmlgraph.collections import FeatureCollection as FeatureCollection
|
|
30
|
+
from htmlgraph.collections import SpikeCollection as SpikeCollection
|
|
31
|
+
from htmlgraph.context_analytics import ContextAnalytics as ContextAnalytics
|
|
32
|
+
from htmlgraph.context_analytics import ContextUsage as ContextUsage
|
|
33
|
+
from htmlgraph.decorators import RetryError as RetryError
|
|
34
|
+
from htmlgraph.decorators import retry as retry
|
|
35
|
+
from htmlgraph.decorators import retry_async as retry_async
|
|
36
|
+
from htmlgraph.edge_index import EdgeIndex as EdgeIndex
|
|
37
|
+
from htmlgraph.edge_index import EdgeRef as EdgeRef
|
|
38
|
+
from htmlgraph.exceptions import ClaimConflictError as ClaimConflictError
|
|
39
|
+
from htmlgraph.exceptions import HtmlGraphError as HtmlGraphError
|
|
40
|
+
from htmlgraph.exceptions import NodeNotFoundError as NodeNotFoundError
|
|
41
|
+
from htmlgraph.exceptions import SessionNotFoundError as SessionNotFoundError
|
|
42
|
+
from htmlgraph.exceptions import ValidationError as ValidationError
|
|
43
|
+
from htmlgraph.find_api import FindAPI as FindAPI
|
|
44
|
+
from htmlgraph.find_api import find as find
|
|
45
|
+
from htmlgraph.find_api import find_all as find_all
|
|
46
|
+
from htmlgraph.graph import CompiledQuery as CompiledQuery
|
|
47
|
+
from htmlgraph.graph import HtmlGraph as HtmlGraph
|
|
48
|
+
from htmlgraph.ids import generate_hierarchical_id as generate_hierarchical_id
|
|
49
|
+
from htmlgraph.ids import generate_id as generate_id
|
|
50
|
+
from htmlgraph.ids import is_legacy_id as is_legacy_id
|
|
51
|
+
from htmlgraph.ids import is_valid_id as is_valid_id
|
|
52
|
+
from htmlgraph.ids import parse_id as parse_id
|
|
53
|
+
from htmlgraph.learning import LearningPersistence as LearningPersistence
|
|
54
|
+
from htmlgraph.learning import (
|
|
55
|
+
auto_persist_on_session_end as auto_persist_on_session_end,
|
|
56
|
+
)
|
|
57
|
+
from htmlgraph.models import ActivityEntry as ActivityEntry
|
|
58
|
+
from htmlgraph.models import AggregatedMetric as AggregatedMetric
|
|
59
|
+
from htmlgraph.models import Chore as Chore
|
|
60
|
+
from htmlgraph.models import ContextSnapshot as ContextSnapshot
|
|
61
|
+
from htmlgraph.models import Edge as Edge
|
|
62
|
+
from htmlgraph.models import Graph as Graph
|
|
63
|
+
from htmlgraph.models import MaintenanceType as MaintenanceType
|
|
64
|
+
from htmlgraph.models import Node as Node
|
|
65
|
+
from htmlgraph.models import Pattern as Pattern
|
|
66
|
+
from htmlgraph.models import Session as Session
|
|
67
|
+
from htmlgraph.models import SessionInsight as SessionInsight
|
|
68
|
+
from htmlgraph.models import Spike as Spike
|
|
69
|
+
from htmlgraph.models import SpikeType as SpikeType
|
|
70
|
+
from htmlgraph.models import Step as Step
|
|
71
|
+
from htmlgraph.models import WorkType as WorkType
|
|
72
|
+
from htmlgraph.orchestration import delegate_with_id as delegate_with_id
|
|
73
|
+
from htmlgraph.orchestration import generate_task_id as generate_task_id
|
|
74
|
+
from htmlgraph.orchestration import get_results_by_task_id as get_results_by_task_id
|
|
75
|
+
from htmlgraph.orchestration import parallel_delegate as parallel_delegate
|
|
76
|
+
from htmlgraph.orchestrator_mode import OrchestratorMode as OrchestratorMode
|
|
77
|
+
from htmlgraph.orchestrator_mode import (
|
|
78
|
+
OrchestratorModeManager as OrchestratorModeManager,
|
|
79
|
+
)
|
|
80
|
+
from htmlgraph.parallel import AggregateResult as AggregateResult
|
|
81
|
+
from htmlgraph.parallel import ParallelAnalysis as ParallelAnalysis
|
|
82
|
+
from htmlgraph.parallel import ParallelWorkflow as ParallelWorkflow
|
|
83
|
+
from htmlgraph.query_builder import Condition as Condition
|
|
84
|
+
from htmlgraph.query_builder import Operator as Operator
|
|
85
|
+
from htmlgraph.query_builder import QueryBuilder as QueryBuilder
|
|
86
|
+
from htmlgraph.reflection import ComputationalReflection as ComputationalReflection
|
|
87
|
+
from htmlgraph.reflection import get_reflection_context as get_reflection_context
|
|
88
|
+
from htmlgraph.repo_hash import RepoHash as RepoHash
|
|
89
|
+
from htmlgraph.sdk.core import SDK as SDK
|
|
90
|
+
from htmlgraph.server import serve as serve
|
|
91
|
+
from htmlgraph.session_manager import SessionManager as SessionManager
|
|
92
|
+
from htmlgraph.session_registry import SessionRegistry as SessionRegistry
|
|
93
|
+
from htmlgraph.types import ActiveWorkItem as ActiveWorkItem
|
|
94
|
+
from htmlgraph.types import AggregateResultsDict as AggregateResultsDict
|
|
95
|
+
from htmlgraph.types import BottleneckDict as BottleneckDict
|
|
96
|
+
from htmlgraph.types import FeatureSummary as FeatureSummary
|
|
97
|
+
from htmlgraph.types import HighRiskTask as HighRiskTask
|
|
98
|
+
from htmlgraph.types import ImpactAnalysisDict as ImpactAnalysisDict
|
|
99
|
+
from htmlgraph.types import OrchestrationResult as OrchestrationResult
|
|
100
|
+
from htmlgraph.types import ParallelGuidelines as ParallelGuidelines
|
|
101
|
+
from htmlgraph.types import ParallelPlanResult as ParallelPlanResult
|
|
102
|
+
from htmlgraph.types import ParallelWorkInfo as ParallelWorkInfo
|
|
103
|
+
from htmlgraph.types import PlanningContext as PlanningContext
|
|
104
|
+
from htmlgraph.types import ProjectStatus as ProjectStatus
|
|
105
|
+
from htmlgraph.types import RiskAssessmentDict as RiskAssessmentDict
|
|
106
|
+
from htmlgraph.types import SessionAnalytics as SessionAnalytics
|
|
107
|
+
from htmlgraph.types import SessionStartInfo as SessionStartInfo
|
|
108
|
+
from htmlgraph.types import SessionSummary as SessionSummary
|
|
109
|
+
from htmlgraph.types import SmartPlanResult as SmartPlanResult
|
|
110
|
+
from htmlgraph.types import SubagentPrompt as SubagentPrompt
|
|
111
|
+
from htmlgraph.types import TaskPrompt as TaskPrompt
|
|
112
|
+
from htmlgraph.types import TrackCreationResult as TrackCreationResult
|
|
113
|
+
from htmlgraph.types import WorkQueueItem as WorkQueueItem
|
|
114
|
+
from htmlgraph.types import WorkRecommendation as WorkRecommendation
|
|
115
|
+
from htmlgraph.work_type_utils import infer_work_type as infer_work_type
|
|
116
|
+
from htmlgraph.work_type_utils import infer_work_type_from_id as infer_work_type_from_id
|
|
117
|
+
|
|
118
|
+
__version__: str
|
|
119
|
+
|
|
120
|
+
# SDK is imported from htmlgraph.sdk.core (see import above)
|
|
121
|
+
# Re-exported here for backward compatibility
|
|
122
|
+
|
|
123
|
+
__all__: list[str]
|
htmlgraph/agent_registry.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
"""
|
|
2
4
|
Agent Registry - Manages agent capabilities and routing.
|
|
3
5
|
|
|
@@ -7,7 +9,6 @@ Provides:
|
|
|
7
9
|
- Capability matching for task routing
|
|
8
10
|
"""
|
|
9
11
|
|
|
10
|
-
from __future__ import annotations
|
|
11
12
|
|
|
12
13
|
import json
|
|
13
14
|
from dataclasses import dataclass, field
|
htmlgraph/analytics/cli.py
CHANGED
|
@@ -109,7 +109,7 @@ def _iter_with_progress(
|
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
def _display_session_analytics(
|
|
112
|
-
console: Console, sdk: SDK, session_id: str, graph_dir: str, quiet: bool
|
|
112
|
+
console: Console, sdk: "SDK", session_id: str, graph_dir: str, quiet: bool
|
|
113
113
|
) -> None:
|
|
114
114
|
"""Display analytics for a single session."""
|
|
115
115
|
from htmlgraph.converter import html_to_session
|
|
@@ -221,7 +221,7 @@ def _display_session_analytics(
|
|
|
221
221
|
|
|
222
222
|
def _display_recent_sessions(
|
|
223
223
|
console: Console,
|
|
224
|
-
sdk: SDK,
|
|
224
|
+
sdk: "SDK",
|
|
225
225
|
session_files: list[Path],
|
|
226
226
|
graph_dir: str,
|
|
227
227
|
quiet: bool,
|
|
@@ -286,7 +286,7 @@ def _display_recent_sessions(
|
|
|
286
286
|
|
|
287
287
|
def _display_project_analytics(
|
|
288
288
|
console: Console,
|
|
289
|
-
sdk: SDK,
|
|
289
|
+
sdk: "SDK",
|
|
290
290
|
session_files: list[Path],
|
|
291
291
|
graph_dir: str,
|
|
292
292
|
quiet: bool,
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
logger = logging.getLogger(__name__)
|
|
4
|
+
|
|
1
5
|
"""
|
|
2
6
|
CostAnalyzer for OTEL ROI Analysis - Phase 1.
|
|
3
7
|
|
|
@@ -15,7 +19,7 @@ Usage:
|
|
|
15
19
|
from htmlgraph.analytics.cost_analyzer import CostAnalyzer
|
|
16
20
|
analyzer = CostAnalyzer()
|
|
17
21
|
delegations = analyzer.get_task_delegations_with_costs()
|
|
18
|
-
|
|
22
|
+
logger.info(f"Total delegation cost: ${delegations['total_cost_usd']:.2f}")
|
|
19
23
|
"""
|
|
20
24
|
|
|
21
25
|
import sqlite3
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger(__name__)
|
|
6
|
+
|
|
1
7
|
"""
|
|
2
8
|
Cross-session analytics using Git commits as the continuity spine.
|
|
3
9
|
|
|
@@ -38,8 +44,6 @@ Example:
|
|
|
38
44
|
authors = cross.work_by_author(since_commit="abc123")
|
|
39
45
|
"""
|
|
40
46
|
|
|
41
|
-
from __future__ import annotations
|
|
42
|
-
|
|
43
47
|
import subprocess
|
|
44
48
|
from collections import defaultdict
|
|
45
49
|
from dataclasses import dataclass
|
|
@@ -147,8 +151,8 @@ class CrossSessionAnalytics:
|
|
|
147
151
|
... from_commit="HEAD~10",
|
|
148
152
|
... to_commit="HEAD"
|
|
149
153
|
... )
|
|
150
|
-
>>>
|
|
151
|
-
>>>
|
|
154
|
+
>>> logger.info(f"Total events: {report.total_events}")
|
|
155
|
+
>>> logger.info(f"Features: {', '.join(report.features)}")
|
|
152
156
|
"""
|
|
153
157
|
# Get commit list from Git
|
|
154
158
|
commits = self._get_commits_in_range(from_commit, to_commit)
|
|
@@ -273,7 +277,7 @@ class CrossSessionAnalytics:
|
|
|
273
277
|
|
|
274
278
|
Example:
|
|
275
279
|
>>> sessions = cross.sessions_for_feature("feature-auth")
|
|
276
|
-
>>>
|
|
280
|
+
>>> logger.info(f"Feature worked on in {len(sessions)} sessions")
|
|
277
281
|
"""
|
|
278
282
|
sessions = set()
|
|
279
283
|
|
|
@@ -320,8 +324,8 @@ class CrossSessionAnalytics:
|
|
|
320
324
|
|
|
321
325
|
Example:
|
|
322
326
|
>>> report = cross.feature_cross_session_report("feature-auth")
|
|
323
|
-
>>>
|
|
324
|
-
>>>
|
|
327
|
+
>>> logger.info(f"Implemented across {len(report.sessions)} sessions")
|
|
328
|
+
>>> logger.info(f"Duration: {report.duration_hours:.1f} hours")
|
|
325
329
|
"""
|
|
326
330
|
sessions = set()
|
|
327
331
|
commits = set()
|
|
@@ -395,7 +399,7 @@ class CrossSessionAnalytics:
|
|
|
395
399
|
Example:
|
|
396
400
|
>>> authors = cross.work_by_author(since_commit="v1.0.0")
|
|
397
401
|
>>> for email, stats in authors.items():
|
|
398
|
-
...
|
|
402
|
+
... logger.info(f"{email}: {stats['event_count']} events")
|
|
399
403
|
"""
|
|
400
404
|
authors: dict[str, dict[str, Any]] = defaultdict(
|
|
401
405
|
lambda: {
|
|
@@ -476,7 +480,7 @@ class CrossSessionAnalytics:
|
|
|
476
480
|
|
|
477
481
|
Example:
|
|
478
482
|
>>> commits = cross.commits_for_session("session-abc")
|
|
479
|
-
>>>
|
|
483
|
+
>>> logger.info(f"Session produced {len(commits)} commits")
|
|
480
484
|
"""
|
|
481
485
|
commits = set()
|
|
482
486
|
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger(__name__)
|
|
6
|
+
|
|
1
7
|
"""
|
|
2
8
|
Dependency-aware analytics for HtmlGraph.
|
|
3
9
|
|
|
@@ -9,8 +15,6 @@ Provides advanced graph analysis for project management:
|
|
|
9
15
|
- Work prioritization
|
|
10
16
|
"""
|
|
11
17
|
|
|
12
|
-
from __future__ import annotations
|
|
13
|
-
|
|
14
18
|
from collections import deque
|
|
15
19
|
from typing import TYPE_CHECKING
|
|
16
20
|
|
|
@@ -55,12 +59,12 @@ class DependencyAnalytics:
|
|
|
55
59
|
# Find bottlenecks (cached internally for performance)
|
|
56
60
|
bottlenecks = dep.find_bottlenecks(top_n=5)
|
|
57
61
|
for bn in bottlenecks:
|
|
58
|
-
|
|
62
|
+
logger.info(f"{bn.title} blocks {bn.transitive_blocking} features")
|
|
59
63
|
|
|
60
64
|
# Get work recommendations (reuses cached data)
|
|
61
65
|
recs = dep.recommend_next_tasks(agent_count=3)
|
|
62
66
|
for rec in recs.recommendations:
|
|
63
|
-
|
|
67
|
+
logger.info(f"Work on: {rec.title} (unlocks {len(rec.unlocks)} features)")
|
|
64
68
|
|
|
65
69
|
# After making graph changes, invalidate cache
|
|
66
70
|
sdk.features.update(feature_id, status="done")
|
|
@@ -201,7 +205,7 @@ class DependencyAnalytics:
|
|
|
201
205
|
|
|
202
206
|
Example:
|
|
203
207
|
report = dep.find_parallelizable_work(status="todo")
|
|
204
|
-
|
|
208
|
+
logger.info(f"Can work on {report.max_parallelism} features in parallel")
|
|
205
209
|
"""
|
|
206
210
|
# Get dependency levels (topological layers)
|
|
207
211
|
levels = self.dependency_levels(status_filter=[status])
|
|
@@ -456,7 +460,7 @@ class DependencyAnalytics:
|
|
|
456
460
|
Example:
|
|
457
461
|
recs = dep.recommend_next_tasks(agent_count=3)
|
|
458
462
|
for rec in recs.recommendations:
|
|
459
|
-
|
|
463
|
+
logger.info(f"Work on: {rec.title}")
|
|
460
464
|
"""
|
|
461
465
|
# Get all nodes with target status
|
|
462
466
|
candidates = [n for n in self.graph.nodes.values() if n.status == status]
|
htmlgraph/analytics/work_type.py
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger(__name__)
|
|
6
|
+
|
|
1
7
|
"""
|
|
2
8
|
Analytics API for HtmlGraph work type analysis.
|
|
3
9
|
|
|
@@ -25,8 +31,6 @@ Example:
|
|
|
25
31
|
# Returns: 25.5 (% of work spent on maintenance)
|
|
26
32
|
"""
|
|
27
33
|
|
|
28
|
-
from __future__ import annotations
|
|
29
|
-
|
|
30
34
|
from datetime import datetime, timezone
|
|
31
35
|
from typing import TYPE_CHECKING
|
|
32
36
|
|
|
@@ -97,7 +101,7 @@ class Analytics:
|
|
|
97
101
|
Example:
|
|
98
102
|
>>> analytics = sdk.analytics
|
|
99
103
|
>>> dist = analytics.work_type_distribution(session_id="session-123")
|
|
100
|
-
>>>
|
|
104
|
+
>>> logger.info("%s", dist)
|
|
101
105
|
{
|
|
102
106
|
"feature-implementation": 45.2,
|
|
103
107
|
"spike-investigation": 28.3,
|
|
@@ -163,11 +167,11 @@ class Analytics:
|
|
|
163
167
|
|
|
164
168
|
Example:
|
|
165
169
|
>>> ratio = sdk.analytics.spike_to_feature_ratio(session_id="session-123")
|
|
166
|
-
>>>
|
|
170
|
+
>>> logger.info(f"Spike-to-feature ratio: {ratio:.2f}")
|
|
167
171
|
Spike-to-feature ratio: 0.63
|
|
168
172
|
|
|
169
173
|
>>> if ratio > 0.5:
|
|
170
|
-
...
|
|
174
|
+
... logger.info("This was a research-heavy session")
|
|
171
175
|
"""
|
|
172
176
|
events = self._get_events(session_id, start_date, end_date)
|
|
173
177
|
|
|
@@ -221,11 +225,11 @@ class Analytics:
|
|
|
221
225
|
|
|
222
226
|
Example:
|
|
223
227
|
>>> burden = sdk.analytics.maintenance_burden(session_id="session-123")
|
|
224
|
-
>>>
|
|
228
|
+
>>> logger.info(f"Maintenance burden: {burden:.1f}%")
|
|
225
229
|
Maintenance burden: 32.5%
|
|
226
230
|
|
|
227
231
|
>>> if burden > 40:
|
|
228
|
-
...
|
|
232
|
+
... logger.info("⚠️ High maintenance burden - consider addressing technical debt")
|
|
229
233
|
"""
|
|
230
234
|
events = self._get_events(session_id, start_date, end_date)
|
|
231
235
|
|
|
@@ -276,7 +280,7 @@ class Analytics:
|
|
|
276
280
|
>>> spike_sessions = sdk.analytics.get_sessions_by_work_type(
|
|
277
281
|
... "spike-investigation"
|
|
278
282
|
... )
|
|
279
|
-
>>>
|
|
283
|
+
>>> logger.info(f"Found {len(spike_sessions)} exploratory sessions")
|
|
280
284
|
"""
|
|
281
285
|
session_nodes = self.sdk.sessions.all()
|
|
282
286
|
matching_sessions = []
|
|
@@ -316,7 +320,7 @@ class Analytics:
|
|
|
316
320
|
|
|
317
321
|
Example:
|
|
318
322
|
>>> breakdown = sdk.analytics.calculate_session_work_breakdown("session-123")
|
|
319
|
-
>>>
|
|
323
|
+
>>> logger.info("%s", breakdown)
|
|
320
324
|
{
|
|
321
325
|
"feature-implementation": 45,
|
|
322
326
|
"spike-investigation": 28,
|
|
@@ -344,7 +348,7 @@ class Analytics:
|
|
|
344
348
|
|
|
345
349
|
Example:
|
|
346
350
|
>>> primary = sdk.analytics.calculate_session_primary_work_type("session-123")
|
|
347
|
-
>>>
|
|
351
|
+
>>> logger.info(f"Primary work type: {primary}")
|
|
348
352
|
Primary work type: spike-investigation
|
|
349
353
|
"""
|
|
350
354
|
session = self._get_session(session_id)
|
|
@@ -399,7 +403,7 @@ class Analytics:
|
|
|
399
403
|
|
|
400
404
|
Example:
|
|
401
405
|
>>> metrics = sdk.analytics.transition_time_metrics(session_id="session-123")
|
|
402
|
-
>>>
|
|
406
|
+
>>> logger.info(f"Transition time: {metrics['transition_percent']:.1f}%")
|
|
403
407
|
Transition time: 15.3%
|
|
404
408
|
"""
|
|
405
409
|
from pathlib import Path
|
htmlgraph/analytics_index.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
"""
|
|
2
4
|
SQLite analytics index for HtmlGraph event logs.
|
|
3
5
|
|
|
@@ -5,7 +7,6 @@ This is a rebuildable cache/index for fast dashboard queries.
|
|
|
5
7
|
The canonical source of truth is the JSONL event log under `.htmlgraph/events/`.
|
|
6
8
|
"""
|
|
7
9
|
|
|
8
|
-
from __future__ import annotations
|
|
9
10
|
|
|
10
11
|
import json
|
|
11
12
|
import sqlite3
|