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
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Phase builder for creating project phase nodes.
|
|
5
|
+
|
|
6
|
+
Extends BaseBuilder with phase-specific methods like
|
|
7
|
+
phase ordering and dependencies.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
from datetime import date
|
|
12
|
+
from typing import TYPE_CHECKING, Any
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from htmlgraph.sdk import SDK
|
|
16
|
+
|
|
17
|
+
from htmlgraph.builders.base import BaseBuilder
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class PhaseBuilder(BaseBuilder["PhaseBuilder"]):
|
|
21
|
+
"""
|
|
22
|
+
Fluent builder for creating phases.
|
|
23
|
+
|
|
24
|
+
Inherits common builder methods from BaseBuilder and adds
|
|
25
|
+
phase-specific methods for project planning:
|
|
26
|
+
- phase_number: Ordering within project
|
|
27
|
+
- start_date/end_date: Phase timeline
|
|
28
|
+
- deliverables: What the phase produces
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
>>> sdk = SDK(agent="claude")
|
|
32
|
+
>>> phase = sdk.phases.create("Phase 1: Core Library") \\
|
|
33
|
+
... .set_priority("high") \\
|
|
34
|
+
... .set_phase_number(1) \\
|
|
35
|
+
... .set_deliverables(["Core API", "Unit tests", "Documentation"]) \\
|
|
36
|
+
... .save()
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
node_type = "phase"
|
|
40
|
+
|
|
41
|
+
def __init__(self, sdk: SDK, title: str, **kwargs: Any):
|
|
42
|
+
"""Initialize phase 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 phase '{self._data.get('title', 'Unknown')}' without agent attribution. "
|
|
53
|
+
"Pass agent='name' to SDK() initialization."
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def set_phase_number(self, number: int) -> PhaseBuilder:
|
|
57
|
+
"""
|
|
58
|
+
Set the phase number for ordering.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
number: Phase sequence number
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
Self for method chaining
|
|
65
|
+
|
|
66
|
+
Example:
|
|
67
|
+
>>> phase.set_phase_number(1)
|
|
68
|
+
"""
|
|
69
|
+
self._data["phase_number"] = number
|
|
70
|
+
return self
|
|
71
|
+
|
|
72
|
+
def set_start_date(self, start: date) -> PhaseBuilder:
|
|
73
|
+
"""
|
|
74
|
+
Set phase start date.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
start: Start date
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Self for method chaining
|
|
81
|
+
|
|
82
|
+
Example:
|
|
83
|
+
>>> phase.set_start_date(date(2025, 1, 1))
|
|
84
|
+
"""
|
|
85
|
+
return self._set_date("start_date", start)
|
|
86
|
+
|
|
87
|
+
def set_end_date(self, end: date) -> PhaseBuilder:
|
|
88
|
+
"""
|
|
89
|
+
Set phase end date.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
end: End date
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
Self for method chaining
|
|
96
|
+
|
|
97
|
+
Example:
|
|
98
|
+
>>> phase.set_end_date(date(2025, 3, 31))
|
|
99
|
+
"""
|
|
100
|
+
return self._set_date("end_date", end)
|
|
101
|
+
|
|
102
|
+
def set_deliverables(self, deliverables: list[str]) -> PhaseBuilder:
|
|
103
|
+
"""
|
|
104
|
+
Set phase deliverables.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
deliverables: List of deliverable items
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
Self for method chaining
|
|
111
|
+
|
|
112
|
+
Example:
|
|
113
|
+
>>> phase.set_deliverables(["API docs", "SDK release", "Examples"])
|
|
114
|
+
"""
|
|
115
|
+
self._data["deliverables"] = deliverables
|
|
116
|
+
return self
|
|
117
|
+
|
|
118
|
+
def add_milestone(self, milestone: str) -> PhaseBuilder:
|
|
119
|
+
"""
|
|
120
|
+
Add a milestone to the phase.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
milestone: Milestone description
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
Self for method chaining
|
|
127
|
+
|
|
128
|
+
Example:
|
|
129
|
+
>>> phase.add_milestone("Alpha release")
|
|
130
|
+
"""
|
|
131
|
+
return self._append_to_list("milestones", milestone)
|
|
132
|
+
|
|
133
|
+
def follows(self, phase_id: str) -> PhaseBuilder:
|
|
134
|
+
"""
|
|
135
|
+
Set this phase to follow another phase.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
phase_id: ID of the preceding phase
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
Self for method chaining
|
|
142
|
+
|
|
143
|
+
Example:
|
|
144
|
+
>>> phase.follows("phase-core-library")
|
|
145
|
+
"""
|
|
146
|
+
return self._add_edge("follows", phase_id)
|
|
147
|
+
|
|
148
|
+
def set_exit_criteria(self, criteria: list[str]) -> PhaseBuilder:
|
|
149
|
+
"""
|
|
150
|
+
Set exit criteria for completing the phase.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
criteria: List of exit criteria
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
Self for method chaining
|
|
157
|
+
|
|
158
|
+
Example:
|
|
159
|
+
>>> phase.set_exit_criteria(["All tests passing", "Code review complete"])
|
|
160
|
+
"""
|
|
161
|
+
self._data["exit_criteria"] = criteria
|
|
162
|
+
return self
|
htmlgraph/builders/spike.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
"""
|
|
2
4
|
Spike builder for creating spike investigation nodes.
|
|
3
5
|
|
|
@@ -5,19 +7,19 @@ Extends BaseBuilder with spike-specific methods like
|
|
|
5
7
|
spike_type and timebox_hours.
|
|
6
8
|
"""
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
from typing import TYPE_CHECKING, Any
|
|
10
12
|
|
|
11
13
|
if TYPE_CHECKING:
|
|
12
|
-
from htmlgraph.sdk import SDK
|
|
13
14
|
from htmlgraph.models import Node
|
|
15
|
+
from htmlgraph.sdk import SDK
|
|
14
16
|
|
|
15
17
|
from htmlgraph.builders.base import BaseBuilder
|
|
16
|
-
from htmlgraph.models import SpikeType, Spike
|
|
17
18
|
from htmlgraph.ids import generate_id
|
|
19
|
+
from htmlgraph.models import Spike, SpikeType
|
|
18
20
|
|
|
19
21
|
|
|
20
|
-
class SpikeBuilder(BaseBuilder[
|
|
22
|
+
class SpikeBuilder(BaseBuilder["SpikeBuilder"]):
|
|
21
23
|
"""
|
|
22
24
|
Fluent builder for creating spikes.
|
|
23
25
|
|
|
@@ -39,7 +41,7 @@ class SpikeBuilder(BaseBuilder['SpikeBuilder']):
|
|
|
39
41
|
|
|
40
42
|
node_type = "spike"
|
|
41
43
|
|
|
42
|
-
def __init__(self, sdk:
|
|
44
|
+
def __init__(self, sdk: SDK, title: str, **kwargs: Any):
|
|
43
45
|
"""Initialize spike builder with spike-specific defaults."""
|
|
44
46
|
super().__init__(sdk, title, **kwargs)
|
|
45
47
|
# Set spike-specific defaults
|
|
@@ -47,8 +49,20 @@ class SpikeBuilder(BaseBuilder['SpikeBuilder']):
|
|
|
47
49
|
self._data["spike_type"] = SpikeType.GENERAL
|
|
48
50
|
if "timebox_hours" not in self._data:
|
|
49
51
|
self._data["timebox_hours"] = 4
|
|
52
|
+
# Auto-assign agent from SDK (critical for work tracking)
|
|
53
|
+
if sdk._agent_id:
|
|
54
|
+
self._data["agent_assigned"] = sdk._agent_id
|
|
55
|
+
elif "agent_assigned" not in self._data:
|
|
56
|
+
# This should never happen now because SDK enforces agent parameter,
|
|
57
|
+
# but log warning if it does occur (for debugging)
|
|
58
|
+
import logging
|
|
59
|
+
|
|
60
|
+
logging.warning(
|
|
61
|
+
f"Creating spike '{self._data.get('title', 'Unknown')}' without agent attribution. "
|
|
62
|
+
"This will make work tracking impossible. Pass agent='name' to SDK() initialization."
|
|
63
|
+
)
|
|
50
64
|
|
|
51
|
-
def set_spike_type(self, spike_type: SpikeType) ->
|
|
65
|
+
def set_spike_type(self, spike_type: SpikeType) -> SpikeBuilder:
|
|
52
66
|
"""
|
|
53
67
|
Set the spike investigation type.
|
|
54
68
|
|
|
@@ -64,7 +78,7 @@ class SpikeBuilder(BaseBuilder['SpikeBuilder']):
|
|
|
64
78
|
self._data["spike_type"] = spike_type
|
|
65
79
|
return self
|
|
66
80
|
|
|
67
|
-
def set_timebox_hours(self, hours: float) ->
|
|
81
|
+
def set_timebox_hours(self, hours: float) -> SpikeBuilder:
|
|
68
82
|
"""
|
|
69
83
|
Set the time budget for this spike.
|
|
70
84
|
|
|
@@ -80,23 +94,36 @@ class SpikeBuilder(BaseBuilder['SpikeBuilder']):
|
|
|
80
94
|
self._data["timebox_hours"] = int(hours)
|
|
81
95
|
return self
|
|
82
96
|
|
|
83
|
-
def set_findings(self, findings: str) ->
|
|
97
|
+
def set_findings(self, findings: str) -> SpikeBuilder:
|
|
84
98
|
"""
|
|
85
99
|
Set the findings/learnings from spike investigation.
|
|
86
100
|
|
|
87
101
|
Args:
|
|
88
|
-
findings: Summary of what was learned
|
|
102
|
+
findings: Summary of what was learned (must be non-empty, min 10 chars)
|
|
89
103
|
|
|
90
104
|
Returns:
|
|
91
105
|
Self for method chaining
|
|
92
106
|
|
|
107
|
+
Raises:
|
|
108
|
+
ValueError: If findings are empty or too short
|
|
109
|
+
|
|
93
110
|
Example:
|
|
94
111
|
>>> spike.set_findings("OAuth2 is best fit. Recommend Auth0.")
|
|
95
112
|
"""
|
|
96
|
-
|
|
113
|
+
# Validate findings quality
|
|
114
|
+
stripped = findings.strip() if findings else ""
|
|
115
|
+
if not stripped:
|
|
116
|
+
raise ValueError(
|
|
117
|
+
"Findings cannot be empty. Provide meaningful investigation results."
|
|
118
|
+
)
|
|
119
|
+
if len(stripped) < 10:
|
|
120
|
+
raise ValueError(
|
|
121
|
+
"Findings must be at least 10 characters. Provide detailed results."
|
|
122
|
+
)
|
|
123
|
+
self._data["findings"] = stripped
|
|
97
124
|
return self
|
|
98
125
|
|
|
99
|
-
def set_decision(self, decision: str) ->
|
|
126
|
+
def set_decision(self, decision: str) -> SpikeBuilder:
|
|
100
127
|
"""
|
|
101
128
|
Set the final decision made based on spike results.
|
|
102
129
|
|
|
@@ -112,7 +139,7 @@ class SpikeBuilder(BaseBuilder['SpikeBuilder']):
|
|
|
112
139
|
self._data["decision"] = decision
|
|
113
140
|
return self
|
|
114
141
|
|
|
115
|
-
def save(self) ->
|
|
142
|
+
def save(self) -> Node:
|
|
116
143
|
"""
|
|
117
144
|
Save the spike and return the Spike instance.
|
|
118
145
|
|
|
@@ -129,13 +156,19 @@ class SpikeBuilder(BaseBuilder['SpikeBuilder']):
|
|
|
129
156
|
title=self._data.get("title", ""),
|
|
130
157
|
)
|
|
131
158
|
|
|
132
|
-
from htmlgraph.graph import HtmlGraph
|
|
133
|
-
|
|
134
159
|
spike = Spike(**self._data)
|
|
135
160
|
|
|
136
|
-
# Save to
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
161
|
+
# Save to the collection's shared graph
|
|
162
|
+
# This ensures the spike is visible via sdk.spikes.get() immediately
|
|
163
|
+
if hasattr(self._sdk, "spikes") and self._sdk.spikes is not None:
|
|
164
|
+
graph = self._sdk.spikes._ensure_graph()
|
|
165
|
+
graph.add(spike)
|
|
166
|
+
else:
|
|
167
|
+
# Fallback: create new graph
|
|
168
|
+
from htmlgraph.graph import HtmlGraph
|
|
169
|
+
|
|
170
|
+
graph_path = self._sdk._directory / "spikes"
|
|
171
|
+
graph = HtmlGraph(graph_path, auto_load=False)
|
|
172
|
+
graph.add(spike)
|
|
140
173
|
|
|
141
174
|
return spike
|