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.
- htmlgraph/.htmlgraph/.session-warning-state.json +6 -0
- htmlgraph/.htmlgraph/agents.json +72 -0
- htmlgraph/.htmlgraph/htmlgraph.db +0 -0
- htmlgraph/__init__.py +173 -17
- htmlgraph/__init__.pyi +123 -0
- htmlgraph/agent_detection.py +127 -0
- htmlgraph/agent_registry.py +45 -30
- htmlgraph/agents.py +160 -107
- htmlgraph/analytics/__init__.py +9 -2
- htmlgraph/analytics/cli.py +190 -51
- htmlgraph/analytics/cost_analyzer.py +391 -0
- htmlgraph/analytics/cost_monitor.py +664 -0
- htmlgraph/analytics/cost_reporter.py +675 -0
- htmlgraph/analytics/cross_session.py +617 -0
- htmlgraph/analytics/dependency.py +192 -100
- htmlgraph/analytics/pattern_learning.py +771 -0
- htmlgraph/analytics/session_graph.py +707 -0
- htmlgraph/analytics/strategic/__init__.py +80 -0
- htmlgraph/analytics/strategic/cost_optimizer.py +611 -0
- htmlgraph/analytics/strategic/pattern_detector.py +876 -0
- htmlgraph/analytics/strategic/preference_manager.py +709 -0
- htmlgraph/analytics/strategic/suggestion_engine.py +747 -0
- htmlgraph/analytics/work_type.py +190 -14
- htmlgraph/analytics_index.py +135 -51
- htmlgraph/api/__init__.py +3 -0
- htmlgraph/api/cost_alerts_websocket.py +416 -0
- htmlgraph/api/main.py +2498 -0
- htmlgraph/api/static/htmx.min.js +1 -0
- htmlgraph/api/static/style-redesign.css +1344 -0
- htmlgraph/api/static/style.css +1079 -0
- htmlgraph/api/templates/dashboard-redesign.html +1366 -0
- htmlgraph/api/templates/dashboard.html +794 -0
- htmlgraph/api/templates/partials/activity-feed-hierarchical.html +326 -0
- htmlgraph/api/templates/partials/activity-feed.html +1100 -0
- htmlgraph/api/templates/partials/agents-redesign.html +317 -0
- htmlgraph/api/templates/partials/agents.html +317 -0
- htmlgraph/api/templates/partials/event-traces.html +373 -0
- htmlgraph/api/templates/partials/features-kanban-redesign.html +509 -0
- htmlgraph/api/templates/partials/features.html +578 -0
- htmlgraph/api/templates/partials/metrics-redesign.html +346 -0
- htmlgraph/api/templates/partials/metrics.html +346 -0
- htmlgraph/api/templates/partials/orchestration-redesign.html +443 -0
- htmlgraph/api/templates/partials/orchestration.html +198 -0
- htmlgraph/api/templates/partials/spawners.html +375 -0
- htmlgraph/api/templates/partials/work-items.html +613 -0
- htmlgraph/api/websocket.py +538 -0
- htmlgraph/archive/__init__.py +24 -0
- htmlgraph/archive/bloom.py +234 -0
- htmlgraph/archive/fts.py +297 -0
- htmlgraph/archive/manager.py +583 -0
- htmlgraph/archive/search.py +244 -0
- htmlgraph/atomic_ops.py +560 -0
- htmlgraph/attribute_index.py +208 -0
- htmlgraph/bounded_paths.py +539 -0
- htmlgraph/builders/__init__.py +14 -0
- htmlgraph/builders/base.py +118 -29
- htmlgraph/builders/bug.py +150 -0
- htmlgraph/builders/chore.py +119 -0
- htmlgraph/builders/epic.py +150 -0
- htmlgraph/builders/feature.py +31 -6
- htmlgraph/builders/insight.py +195 -0
- htmlgraph/builders/metric.py +217 -0
- htmlgraph/builders/pattern.py +202 -0
- htmlgraph/builders/phase.py +162 -0
- htmlgraph/builders/spike.py +52 -19
- htmlgraph/builders/track.py +148 -72
- htmlgraph/cigs/__init__.py +81 -0
- htmlgraph/cigs/autonomy.py +385 -0
- htmlgraph/cigs/cost.py +475 -0
- htmlgraph/cigs/messages_basic.py +472 -0
- htmlgraph/cigs/messaging.py +365 -0
- htmlgraph/cigs/models.py +771 -0
- htmlgraph/cigs/pattern_storage.py +427 -0
- htmlgraph/cigs/patterns.py +503 -0
- htmlgraph/cigs/posttool_analyzer.py +234 -0
- htmlgraph/cigs/reporter.py +818 -0
- htmlgraph/cigs/tracker.py +317 -0
- htmlgraph/cli/.htmlgraph/.session-warning-state.json +6 -0
- htmlgraph/cli/.htmlgraph/agents.json +72 -0
- htmlgraph/cli/.htmlgraph/htmlgraph.db +0 -0
- htmlgraph/cli/__init__.py +42 -0
- htmlgraph/cli/__main__.py +6 -0
- htmlgraph/cli/analytics.py +1424 -0
- htmlgraph/cli/base.py +685 -0
- htmlgraph/cli/constants.py +206 -0
- htmlgraph/cli/core.py +954 -0
- htmlgraph/cli/main.py +147 -0
- htmlgraph/cli/models.py +475 -0
- htmlgraph/cli/templates/__init__.py +1 -0
- htmlgraph/cli/templates/cost_dashboard.py +399 -0
- htmlgraph/cli/work/__init__.py +239 -0
- htmlgraph/cli/work/browse.py +115 -0
- htmlgraph/cli/work/features.py +568 -0
- htmlgraph/cli/work/orchestration.py +676 -0
- htmlgraph/cli/work/report.py +728 -0
- htmlgraph/cli/work/sessions.py +466 -0
- htmlgraph/cli/work/snapshot.py +559 -0
- htmlgraph/cli/work/tracks.py +486 -0
- htmlgraph/cli_commands/__init__.py +1 -0
- htmlgraph/cli_commands/feature.py +195 -0
- htmlgraph/cli_framework.py +115 -0
- htmlgraph/collections/__init__.py +18 -0
- htmlgraph/collections/base.py +415 -98
- htmlgraph/collections/bug.py +53 -0
- htmlgraph/collections/chore.py +53 -0
- htmlgraph/collections/epic.py +53 -0
- htmlgraph/collections/feature.py +12 -26
- htmlgraph/collections/insight.py +100 -0
- htmlgraph/collections/metric.py +92 -0
- htmlgraph/collections/pattern.py +97 -0
- htmlgraph/collections/phase.py +53 -0
- htmlgraph/collections/session.py +194 -0
- htmlgraph/collections/spike.py +56 -16
- htmlgraph/collections/task_delegation.py +241 -0
- htmlgraph/collections/todo.py +511 -0
- htmlgraph/collections/traces.py +487 -0
- htmlgraph/config/cost_models.json +56 -0
- htmlgraph/config.py +190 -0
- htmlgraph/context_analytics.py +344 -0
- htmlgraph/converter.py +216 -28
- htmlgraph/cost_analysis/__init__.py +5 -0
- htmlgraph/cost_analysis/analyzer.py +438 -0
- htmlgraph/dashboard.html +2406 -307
- htmlgraph/dashboard.html.backup +6592 -0
- htmlgraph/dashboard.html.bak +7181 -0
- htmlgraph/dashboard.html.bak2 +7231 -0
- htmlgraph/dashboard.html.bak3 +7232 -0
- htmlgraph/db/__init__.py +38 -0
- htmlgraph/db/queries.py +790 -0
- htmlgraph/db/schema.py +1788 -0
- htmlgraph/decorators.py +317 -0
- htmlgraph/dependency_models.py +19 -2
- htmlgraph/deploy.py +142 -125
- htmlgraph/deployment_models.py +474 -0
- htmlgraph/docs/API_REFERENCE.md +841 -0
- htmlgraph/docs/HTTP_API.md +750 -0
- htmlgraph/docs/INTEGRATION_GUIDE.md +752 -0
- htmlgraph/docs/ORCHESTRATION_PATTERNS.md +717 -0
- htmlgraph/docs/README.md +532 -0
- htmlgraph/docs/__init__.py +77 -0
- htmlgraph/docs/docs_version.py +55 -0
- htmlgraph/docs/metadata.py +93 -0
- htmlgraph/docs/migrations.py +232 -0
- htmlgraph/docs/template_engine.py +143 -0
- htmlgraph/docs/templates/_sections/cli_reference.md.j2 +52 -0
- htmlgraph/docs/templates/_sections/core_concepts.md.j2 +29 -0
- htmlgraph/docs/templates/_sections/sdk_basics.md.j2 +69 -0
- htmlgraph/docs/templates/base_agents.md.j2 +78 -0
- htmlgraph/docs/templates/example_user_override.md.j2 +47 -0
- htmlgraph/docs/version_check.py +163 -0
- htmlgraph/edge_index.py +182 -27
- htmlgraph/error_handler.py +544 -0
- htmlgraph/event_log.py +100 -52
- htmlgraph/event_migration.py +13 -4
- htmlgraph/exceptions.py +49 -0
- htmlgraph/file_watcher.py +101 -28
- htmlgraph/find_api.py +75 -63
- htmlgraph/git_events.py +145 -63
- htmlgraph/graph.py +1122 -106
- htmlgraph/hooks/.htmlgraph/.session-warning-state.json +6 -0
- htmlgraph/hooks/.htmlgraph/agents.json +72 -0
- htmlgraph/hooks/.htmlgraph/index.sqlite +0 -0
- htmlgraph/hooks/__init__.py +45 -0
- htmlgraph/hooks/bootstrap.py +169 -0
- htmlgraph/hooks/cigs_pretool_enforcer.py +354 -0
- htmlgraph/hooks/concurrent_sessions.py +208 -0
- htmlgraph/hooks/context.py +350 -0
- htmlgraph/hooks/drift_handler.py +525 -0
- htmlgraph/hooks/event_tracker.py +1314 -0
- htmlgraph/hooks/git_commands.py +175 -0
- htmlgraph/hooks/hooks-config.example.json +12 -0
- htmlgraph/hooks/installer.py +343 -0
- htmlgraph/hooks/orchestrator.py +674 -0
- htmlgraph/hooks/orchestrator_reflector.py +223 -0
- htmlgraph/hooks/post-checkout.sh +28 -0
- htmlgraph/hooks/post-commit.sh +24 -0
- htmlgraph/hooks/post-merge.sh +26 -0
- htmlgraph/hooks/post_tool_use_failure.py +273 -0
- htmlgraph/hooks/post_tool_use_handler.py +257 -0
- htmlgraph/hooks/posttooluse.py +408 -0
- htmlgraph/hooks/pre-commit.sh +94 -0
- htmlgraph/hooks/pre-push.sh +28 -0
- htmlgraph/hooks/pretooluse.py +819 -0
- htmlgraph/hooks/prompt_analyzer.py +637 -0
- htmlgraph/hooks/session_handler.py +668 -0
- htmlgraph/hooks/session_summary.py +395 -0
- htmlgraph/hooks/state_manager.py +504 -0
- htmlgraph/hooks/subagent_detection.py +202 -0
- htmlgraph/hooks/subagent_stop.py +369 -0
- htmlgraph/hooks/task_enforcer.py +255 -0
- htmlgraph/hooks/task_validator.py +177 -0
- htmlgraph/hooks/validator.py +628 -0
- htmlgraph/ids.py +41 -27
- htmlgraph/index.d.ts +286 -0
- htmlgraph/learning.py +767 -0
- htmlgraph/mcp_server.py +69 -23
- htmlgraph/models.py +1586 -87
- htmlgraph/operations/README.md +62 -0
- htmlgraph/operations/__init__.py +79 -0
- htmlgraph/operations/analytics.py +339 -0
- htmlgraph/operations/bootstrap.py +289 -0
- htmlgraph/operations/events.py +244 -0
- htmlgraph/operations/fastapi_server.py +231 -0
- htmlgraph/operations/hooks.py +350 -0
- htmlgraph/operations/initialization.py +597 -0
- htmlgraph/operations/initialization.py.backup +228 -0
- htmlgraph/operations/server.py +303 -0
- htmlgraph/orchestration/__init__.py +58 -0
- htmlgraph/orchestration/claude_launcher.py +179 -0
- htmlgraph/orchestration/command_builder.py +72 -0
- htmlgraph/orchestration/headless_spawner.py +281 -0
- htmlgraph/orchestration/live_events.py +377 -0
- htmlgraph/orchestration/model_selection.py +327 -0
- htmlgraph/orchestration/plugin_manager.py +140 -0
- htmlgraph/orchestration/prompts.py +137 -0
- htmlgraph/orchestration/spawner_event_tracker.py +383 -0
- htmlgraph/orchestration/spawners/__init__.py +16 -0
- htmlgraph/orchestration/spawners/base.py +194 -0
- htmlgraph/orchestration/spawners/claude.py +173 -0
- htmlgraph/orchestration/spawners/codex.py +435 -0
- htmlgraph/orchestration/spawners/copilot.py +294 -0
- htmlgraph/orchestration/spawners/gemini.py +471 -0
- htmlgraph/orchestration/subprocess_runner.py +36 -0
- htmlgraph/orchestration/task_coordination.py +343 -0
- htmlgraph/orchestration.md +563 -0
- htmlgraph/orchestrator-system-prompt-optimized.txt +863 -0
- htmlgraph/orchestrator.py +669 -0
- htmlgraph/orchestrator_config.py +357 -0
- htmlgraph/orchestrator_mode.py +328 -0
- htmlgraph/orchestrator_validator.py +133 -0
- htmlgraph/parallel.py +646 -0
- htmlgraph/parser.py +160 -35
- htmlgraph/path_query.py +608 -0
- htmlgraph/pattern_matcher.py +636 -0
- htmlgraph/planning.py +147 -52
- htmlgraph/pydantic_models.py +476 -0
- htmlgraph/quality_gates.py +350 -0
- htmlgraph/query_builder.py +109 -72
- htmlgraph/query_composer.py +509 -0
- htmlgraph/reflection.py +443 -0
- htmlgraph/refs.py +344 -0
- htmlgraph/repo_hash.py +512 -0
- htmlgraph/repositories/__init__.py +292 -0
- htmlgraph/repositories/analytics_repository.py +455 -0
- htmlgraph/repositories/analytics_repository_standard.py +628 -0
- htmlgraph/repositories/feature_repository.py +581 -0
- htmlgraph/repositories/feature_repository_htmlfile.py +668 -0
- htmlgraph/repositories/feature_repository_memory.py +607 -0
- htmlgraph/repositories/feature_repository_sqlite.py +858 -0
- htmlgraph/repositories/filter_service.py +620 -0
- htmlgraph/repositories/filter_service_standard.py +445 -0
- htmlgraph/repositories/shared_cache.py +621 -0
- htmlgraph/repositories/shared_cache_memory.py +395 -0
- htmlgraph/repositories/track_repository.py +552 -0
- htmlgraph/repositories/track_repository_htmlfile.py +619 -0
- htmlgraph/repositories/track_repository_memory.py +508 -0
- htmlgraph/repositories/track_repository_sqlite.py +711 -0
- htmlgraph/routing.py +8 -19
- htmlgraph/scripts/deploy.py +1 -2
- 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/sdk/strategic/__init__.py +26 -0
- htmlgraph/sdk/strategic/mixin.py +563 -0
- htmlgraph/server.py +685 -180
- htmlgraph/services/__init__.py +10 -0
- htmlgraph/services/claiming.py +199 -0
- htmlgraph/session_hooks.py +300 -0
- htmlgraph/session_manager.py +1392 -175
- htmlgraph/session_registry.py +587 -0
- htmlgraph/session_state.py +436 -0
- htmlgraph/session_warning.py +201 -0
- htmlgraph/sessions/__init__.py +23 -0
- htmlgraph/sessions/handoff.py +756 -0
- htmlgraph/setup.py +34 -17
- htmlgraph/spike_index.py +143 -0
- htmlgraph/sync_docs.py +12 -15
- htmlgraph/system_prompts.py +450 -0
- htmlgraph/templates/AGENTS.md.template +366 -0
- htmlgraph/templates/CLAUDE.md.template +97 -0
- htmlgraph/templates/GEMINI.md.template +87 -0
- htmlgraph/templates/orchestration-view.html +350 -0
- htmlgraph/track_builder.py +146 -15
- htmlgraph/track_manager.py +69 -21
- htmlgraph/transcript.py +890 -0
- htmlgraph/transcript_analytics.py +699 -0
- htmlgraph/types.py +323 -0
- htmlgraph/validation.py +115 -0
- htmlgraph/watch.py +8 -5
- htmlgraph/work_type_utils.py +3 -2
- {htmlgraph-0.9.3.data → htmlgraph-0.27.5.data}/data/htmlgraph/dashboard.html +2406 -307
- htmlgraph-0.27.5.data/data/htmlgraph/templates/AGENTS.md.template +366 -0
- htmlgraph-0.27.5.data/data/htmlgraph/templates/CLAUDE.md.template +97 -0
- htmlgraph-0.27.5.data/data/htmlgraph/templates/GEMINI.md.template +87 -0
- {htmlgraph-0.9.3.dist-info → htmlgraph-0.27.5.dist-info}/METADATA +97 -64
- htmlgraph-0.27.5.dist-info/RECORD +337 -0
- {htmlgraph-0.9.3.dist-info → htmlgraph-0.27.5.dist-info}/entry_points.txt +1 -1
- htmlgraph/cli.py +0 -2688
- htmlgraph/sdk.py +0 -709
- htmlgraph-0.9.3.dist-info/RECORD +0 -61
- {htmlgraph-0.9.3.data → htmlgraph-0.27.5.data}/data/htmlgraph/styles.css +0 -0
- {htmlgraph-0.9.3.dist-info → htmlgraph-0.27.5.dist-info}/WHEEL +0 -0
htmlgraph/types.py
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Type definitions for HtmlGraph SDK return types.
|
|
3
|
+
|
|
4
|
+
Provides TypedDict definitions for SDK methods that return dictionaries,
|
|
5
|
+
improving developer experience with better type hints and IDE autocomplete.
|
|
6
|
+
|
|
7
|
+
These complement the Pydantic models in dependency_models.py by providing
|
|
8
|
+
type hints for dict-based return values used in the SDK for backward compatibility.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import sys
|
|
12
|
+
from typing import Literal, TypedDict
|
|
13
|
+
|
|
14
|
+
# NotRequired was added in Python 3.11
|
|
15
|
+
if sys.version_info >= (3, 11):
|
|
16
|
+
from typing import NotRequired
|
|
17
|
+
else:
|
|
18
|
+
from typing_extensions import NotRequired
|
|
19
|
+
|
|
20
|
+
# ============================================================================
|
|
21
|
+
# Analytics Return Types
|
|
22
|
+
# ============================================================================
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class BottleneckDict(TypedDict):
|
|
26
|
+
"""Bottleneck task information from find_bottlenecks()."""
|
|
27
|
+
|
|
28
|
+
id: str
|
|
29
|
+
title: str
|
|
30
|
+
status: str
|
|
31
|
+
priority: str
|
|
32
|
+
blocks_count: int # Number of tasks this blocks (transitive)
|
|
33
|
+
impact_score: float # Weighted impact score
|
|
34
|
+
blocked_tasks: list[str] # List of blocked task IDs
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class WorkRecommendation(TypedDict):
|
|
38
|
+
"""Work recommendation from recommend_next_work()."""
|
|
39
|
+
|
|
40
|
+
id: str
|
|
41
|
+
title: str
|
|
42
|
+
priority: str
|
|
43
|
+
score: float # Priority score
|
|
44
|
+
reasons: list[str] # Human-readable reasons for recommendation
|
|
45
|
+
estimated_hours: NotRequired[float] # Effort estimate
|
|
46
|
+
unlocks_count: int # Number of tasks this unlocks
|
|
47
|
+
unlocks: list[str] # Task IDs that become available
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ParallelWorkInfo(TypedDict):
|
|
51
|
+
"""Parallel work opportunities from get_parallel_work()."""
|
|
52
|
+
|
|
53
|
+
max_parallelism: int # Maximum number of parallel tasks
|
|
54
|
+
ready_now: list[str] # Tasks ready to start immediately
|
|
55
|
+
total_ready: int # Total count of ready tasks
|
|
56
|
+
level_count: int # Number of dependency levels
|
|
57
|
+
next_level: list[str] # Tasks in next dependency level
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class RiskAssessmentDict(TypedDict):
|
|
61
|
+
"""Risk assessment from assess_risks()."""
|
|
62
|
+
|
|
63
|
+
high_risk_count: int
|
|
64
|
+
high_risk_tasks: list["HighRiskTask"]
|
|
65
|
+
circular_dependencies: list[list[str]]
|
|
66
|
+
orphaned_count: int
|
|
67
|
+
orphaned_tasks: list[str]
|
|
68
|
+
recommendations: list[str]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class HighRiskTask(TypedDict):
|
|
72
|
+
"""Individual high-risk task information."""
|
|
73
|
+
|
|
74
|
+
id: str
|
|
75
|
+
title: str
|
|
76
|
+
risk_score: float
|
|
77
|
+
risk_factors: list[str]
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class ImpactAnalysisDict(TypedDict):
|
|
81
|
+
"""Impact analysis from analyze_impact()."""
|
|
82
|
+
|
|
83
|
+
node_id: str
|
|
84
|
+
direct_dependents: int
|
|
85
|
+
total_impact: int # Transitive dependents
|
|
86
|
+
completion_impact: float # Percentage of work this unlocks
|
|
87
|
+
unlocks_count: int
|
|
88
|
+
affected_tasks: list[str]
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# ============================================================================
|
|
92
|
+
# Session Management Return Types
|
|
93
|
+
# ============================================================================
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class SessionStartInfo(TypedDict):
|
|
97
|
+
"""Comprehensive session start information from get_session_start_info()."""
|
|
98
|
+
|
|
99
|
+
status: "ProjectStatus"
|
|
100
|
+
active_work: NotRequired["ActiveWorkItem"] # None if no active work
|
|
101
|
+
features: list["FeatureSummary"]
|
|
102
|
+
sessions: list["SessionSummary"]
|
|
103
|
+
git_log: NotRequired[list[str]] # Recent commit messages
|
|
104
|
+
analytics: "SessionAnalytics"
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class ProjectStatus(TypedDict):
|
|
108
|
+
"""Project status metrics."""
|
|
109
|
+
|
|
110
|
+
total_nodes: int
|
|
111
|
+
in_progress_count: int
|
|
112
|
+
todo_count: int
|
|
113
|
+
done_count: int
|
|
114
|
+
blocked_count: int
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class ActiveWorkItem(TypedDict):
|
|
118
|
+
"""Currently active work item details."""
|
|
119
|
+
|
|
120
|
+
id: str
|
|
121
|
+
title: str
|
|
122
|
+
type: Literal["feature", "bug", "spike", "chore", "epic"]
|
|
123
|
+
status: str
|
|
124
|
+
agent: NotRequired[str] # Assigned agent
|
|
125
|
+
steps_total: int
|
|
126
|
+
steps_completed: int
|
|
127
|
+
auto_generated: NotRequired[bool] # For spikes
|
|
128
|
+
spike_subtype: NotRequired[str] # For spikes
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class FeatureSummary(TypedDict):
|
|
132
|
+
"""Feature summary for session start."""
|
|
133
|
+
|
|
134
|
+
id: str
|
|
135
|
+
title: str
|
|
136
|
+
status: str
|
|
137
|
+
priority: str
|
|
138
|
+
steps_total: int
|
|
139
|
+
steps_completed: int
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class SessionSummary(TypedDict):
|
|
143
|
+
"""Session summary information."""
|
|
144
|
+
|
|
145
|
+
id: str
|
|
146
|
+
status: str
|
|
147
|
+
agent: str
|
|
148
|
+
event_count: int
|
|
149
|
+
started: NotRequired[str] # ISO timestamp
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class SessionAnalytics(TypedDict):
|
|
153
|
+
"""Strategic analytics for session start."""
|
|
154
|
+
|
|
155
|
+
bottlenecks: list[BottleneckDict]
|
|
156
|
+
recommendations: list[WorkRecommendation]
|
|
157
|
+
parallel: ParallelWorkInfo
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# ============================================================================
|
|
161
|
+
# Work Queue Return Types
|
|
162
|
+
# ============================================================================
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class WorkQueueItem(TypedDict):
|
|
166
|
+
"""Work queue item from get_work_queue()."""
|
|
167
|
+
|
|
168
|
+
task_id: str
|
|
169
|
+
title: str
|
|
170
|
+
status: str
|
|
171
|
+
priority: str
|
|
172
|
+
score: float # Routing score
|
|
173
|
+
type: str # Work item type
|
|
174
|
+
complexity: NotRequired[str]
|
|
175
|
+
effort: NotRequired[float]
|
|
176
|
+
agent_assigned: NotRequired[str]
|
|
177
|
+
blocks_count: int
|
|
178
|
+
blocked_by: list[str]
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
# ============================================================================
|
|
182
|
+
# Planning Return Types
|
|
183
|
+
# ============================================================================
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class SmartPlanResult(TypedDict):
|
|
187
|
+
"""Result from smart_plan()."""
|
|
188
|
+
|
|
189
|
+
type: Literal["spike", "track"]
|
|
190
|
+
spike_id: NotRequired[str] # Present if type="spike"
|
|
191
|
+
track_id: NotRequired[str] # Present if type="track"
|
|
192
|
+
title: str
|
|
193
|
+
status: NotRequired[str] # For spikes
|
|
194
|
+
timebox_hours: NotRequired[float] # For spikes
|
|
195
|
+
has_spec: NotRequired[bool] # For tracks
|
|
196
|
+
has_plan: NotRequired[bool] # For tracks
|
|
197
|
+
priority: NotRequired[str] # For tracks
|
|
198
|
+
project_context: "PlanningContext"
|
|
199
|
+
research_informed: bool
|
|
200
|
+
next_steps: list[str]
|
|
201
|
+
warnings: NotRequired[list[str]]
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class PlanningContext(TypedDict):
|
|
205
|
+
"""Project context for planning."""
|
|
206
|
+
|
|
207
|
+
bottlenecks_count: int
|
|
208
|
+
high_risk_count: int
|
|
209
|
+
parallel_capacity: int
|
|
210
|
+
description: str
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class TrackCreationResult(TypedDict):
|
|
214
|
+
"""Result from create_track_from_plan()."""
|
|
215
|
+
|
|
216
|
+
track_id: str
|
|
217
|
+
title: str
|
|
218
|
+
has_spec: bool
|
|
219
|
+
has_plan: bool
|
|
220
|
+
spike_id: NotRequired[str] # Original planning spike
|
|
221
|
+
priority: str
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
# ============================================================================
|
|
225
|
+
# Orchestration Return Types
|
|
226
|
+
# ============================================================================
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class SubagentPrompt(TypedDict):
|
|
230
|
+
"""Subagent prompt from spawn_explorer() or spawn_coder().
|
|
231
|
+
|
|
232
|
+
This TypedDict represents the return value from SDK methods that spawn
|
|
233
|
+
subagents for specialized tasks like code exploration or implementation.
|
|
234
|
+
|
|
235
|
+
Fields:
|
|
236
|
+
prompt: The full prompt text for the subagent
|
|
237
|
+
description: Short description of the subagent's task
|
|
238
|
+
subagent_type: Type of subagent ("Explore", "Code", etc.)
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
prompt: str
|
|
242
|
+
description: str
|
|
243
|
+
subagent_type: str
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class OrchestrationResult(TypedDict):
|
|
247
|
+
"""Result from orchestrate() method.
|
|
248
|
+
|
|
249
|
+
Contains prompts for a two-phase feature implementation workflow:
|
|
250
|
+
1. Explorer discovers relevant code and patterns
|
|
251
|
+
2. Coder implements the feature based on explorer findings
|
|
252
|
+
|
|
253
|
+
Fields:
|
|
254
|
+
explorer: Prompt for the explorer subagent
|
|
255
|
+
coder: Prompt for the coder subagent
|
|
256
|
+
workflow: Step-by-step workflow instructions
|
|
257
|
+
"""
|
|
258
|
+
|
|
259
|
+
explorer: SubagentPrompt
|
|
260
|
+
coder: SubagentPrompt
|
|
261
|
+
workflow: list[str] # Step-by-step workflow
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
# Type aliases for specific spawning methods
|
|
265
|
+
SpawnExplorerResult = SubagentPrompt
|
|
266
|
+
"""Return type for spawn_explorer() - same structure as SubagentPrompt."""
|
|
267
|
+
|
|
268
|
+
SpawnCoderResult = SubagentPrompt
|
|
269
|
+
"""Return type for spawn_coder() - same structure as SubagentPrompt."""
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
# ============================================================================
|
|
273
|
+
# Parallel Work Return Types
|
|
274
|
+
# ============================================================================
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class ParallelPlanResult(TypedDict):
|
|
278
|
+
"""Result from plan_parallel_work()."""
|
|
279
|
+
|
|
280
|
+
can_parallelize: bool
|
|
281
|
+
max_parallelism: int
|
|
282
|
+
ready_tasks: list[str]
|
|
283
|
+
blocked_tasks: list[str]
|
|
284
|
+
speedup_factor: float
|
|
285
|
+
recommendation: str
|
|
286
|
+
warnings: list[str]
|
|
287
|
+
prompts: list["TaskPrompt"]
|
|
288
|
+
task_count: NotRequired[int]
|
|
289
|
+
guidelines: NotRequired["ParallelGuidelines"]
|
|
290
|
+
reason: NotRequired[str] # If can_parallelize=False
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
class TaskPrompt(TypedDict):
|
|
294
|
+
"""Individual task prompt for parallel execution."""
|
|
295
|
+
|
|
296
|
+
prompt: str
|
|
297
|
+
description: str
|
|
298
|
+
task_id: str
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
class ParallelGuidelines(TypedDict):
|
|
302
|
+
"""Guidelines for parallel execution."""
|
|
303
|
+
|
|
304
|
+
dispatch: str
|
|
305
|
+
patterns: list[str]
|
|
306
|
+
avoid: list[str]
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
class AggregateResultsDict(TypedDict):
|
|
310
|
+
"""Result from aggregate_parallel_results()."""
|
|
311
|
+
|
|
312
|
+
total_agents: int
|
|
313
|
+
successful: int
|
|
314
|
+
failed: int
|
|
315
|
+
total_duration_seconds: float
|
|
316
|
+
parallel_speedup: float
|
|
317
|
+
avg_health_score: float
|
|
318
|
+
total_anti_patterns: int
|
|
319
|
+
files_modified: list[str]
|
|
320
|
+
conflicts: list[str]
|
|
321
|
+
recommendations: list[str]
|
|
322
|
+
validation: dict[str, bool]
|
|
323
|
+
all_passed: bool
|
htmlgraph/validation.py
ADDED
|
@@ -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
|
|
@@ -16,7 +17,6 @@ from pathlib import Path
|
|
|
16
17
|
|
|
17
18
|
from htmlgraph.session_manager import SessionManager
|
|
18
19
|
|
|
19
|
-
|
|
20
20
|
DEFAULT_IGNORE_DIRS = {
|
|
21
21
|
".git",
|
|
22
22
|
".venv",
|
|
@@ -69,7 +69,9 @@ def watch_and_track(
|
|
|
69
69
|
ignore = set(ignore_dirs or DEFAULT_IGNORE_DIRS)
|
|
70
70
|
|
|
71
71
|
manager = SessionManager(graph_dir)
|
|
72
|
-
session = manager.start_session(
|
|
72
|
+
session = manager.start_session(
|
|
73
|
+
session_id=session_id, agent=agent, title=f"Watch: {agent}"
|
|
74
|
+
)
|
|
73
75
|
|
|
74
76
|
last_snapshot = _snapshot(root, ignore)
|
|
75
77
|
pending: set[str] = set()
|
|
@@ -123,6 +125,7 @@ def watch_and_track(
|
|
|
123
125
|
last_snapshot = current
|
|
124
126
|
except KeyboardInterrupt:
|
|
125
127
|
print("\nStopping watcher…")
|
|
126
|
-
manager.track_activity(
|
|
128
|
+
manager.track_activity(
|
|
129
|
+
session_id=session.id, tool="Stop", summary="Watcher stopped"
|
|
130
|
+
)
|
|
127
131
|
manager.end_session(session.id)
|
|
128
|
-
|
htmlgraph/work_type_utils.py
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
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
|
-
|
|
9
|
+
|
|
8
10
|
from typing import TYPE_CHECKING
|
|
9
11
|
|
|
10
12
|
if TYPE_CHECKING:
|
|
11
|
-
from htmlgraph.models import WorkType
|
|
12
13
|
from htmlgraph import SDK
|
|
13
14
|
|
|
14
15
|
|