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,208 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Attribute Index for O(1) attribute-based lookups.
|
|
5
|
+
|
|
6
|
+
Provides efficient attribute-based queries by maintaining
|
|
7
|
+
indexes for common node attributes. This enables O(1) lookups for:
|
|
8
|
+
- Finding all nodes with a specific status
|
|
9
|
+
- Finding all nodes with a specific priority
|
|
10
|
+
- Finding all nodes with a specific type
|
|
11
|
+
|
|
12
|
+
Without this index, finding nodes by attribute requires scanning
|
|
13
|
+
all nodes in the graph - O(n) complexity.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
from collections import defaultdict
|
|
18
|
+
from dataclasses import dataclass, field
|
|
19
|
+
from typing import TYPE_CHECKING
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from htmlgraph.models import Node
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class AttributeIndex:
|
|
27
|
+
"""
|
|
28
|
+
Attribute-based index for efficient node lookups.
|
|
29
|
+
|
|
30
|
+
Maintains indexes for common node attributes:
|
|
31
|
+
- _by_status: Maps status value to set of node IDs
|
|
32
|
+
- _by_priority: Maps priority value to set of node IDs
|
|
33
|
+
- _by_type: Maps type value to set of node IDs
|
|
34
|
+
|
|
35
|
+
The indexes are lazy-built on first access and updated
|
|
36
|
+
incrementally as nodes are added/modified/removed.
|
|
37
|
+
|
|
38
|
+
Example:
|
|
39
|
+
index = AttributeIndex()
|
|
40
|
+
index.rebuild(graph.nodes)
|
|
41
|
+
|
|
42
|
+
# O(1) lookup of all todo nodes
|
|
43
|
+
todo_ids = index.get_by_status("todo")
|
|
44
|
+
|
|
45
|
+
# O(1) lookup of all high-priority nodes
|
|
46
|
+
high_priority_ids = index.get_by_priority("high")
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
_by_status: dict[str, set[str]] = field(default_factory=lambda: defaultdict(set))
|
|
50
|
+
_by_priority: dict[str, set[str]] = field(default_factory=lambda: defaultdict(set))
|
|
51
|
+
_by_type: dict[str, set[str]] = field(default_factory=lambda: defaultdict(set))
|
|
52
|
+
_is_built: bool = False
|
|
53
|
+
|
|
54
|
+
def add_node(self, node_id: str, node: Node) -> None:
|
|
55
|
+
"""
|
|
56
|
+
Add a node to all relevant indexes.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
node_id: Node ID
|
|
60
|
+
node: Node object with attributes to index
|
|
61
|
+
"""
|
|
62
|
+
self._by_status[node.status].add(node_id)
|
|
63
|
+
self._by_priority[node.priority].add(node_id)
|
|
64
|
+
self._by_type[node.type].add(node_id)
|
|
65
|
+
|
|
66
|
+
def remove_node(self, node_id: str, node: Node) -> None:
|
|
67
|
+
"""
|
|
68
|
+
Remove a node from all indexes.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
node_id: Node ID
|
|
72
|
+
node: Node object with attributes to remove
|
|
73
|
+
"""
|
|
74
|
+
self._by_status[node.status].discard(node_id)
|
|
75
|
+
self._by_priority[node.priority].discard(node_id)
|
|
76
|
+
self._by_type[node.type].discard(node_id)
|
|
77
|
+
|
|
78
|
+
# Clean up empty sets
|
|
79
|
+
if not self._by_status[node.status]:
|
|
80
|
+
del self._by_status[node.status]
|
|
81
|
+
if not self._by_priority[node.priority]:
|
|
82
|
+
del self._by_priority[node.priority]
|
|
83
|
+
if not self._by_type[node.type]:
|
|
84
|
+
del self._by_type[node.type]
|
|
85
|
+
|
|
86
|
+
def update_node(self, node_id: str, old_node: Node, new_node: Node) -> None:
|
|
87
|
+
"""
|
|
88
|
+
Update a node's indexed attributes.
|
|
89
|
+
|
|
90
|
+
Removes old attributes and adds new ones atomically.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
node_id: Node ID
|
|
94
|
+
old_node: Previous node object
|
|
95
|
+
new_node: Updated node object
|
|
96
|
+
"""
|
|
97
|
+
# Remove old attributes
|
|
98
|
+
self._by_status[old_node.status].discard(node_id)
|
|
99
|
+
self._by_priority[old_node.priority].discard(node_id)
|
|
100
|
+
self._by_type[old_node.type].discard(node_id)
|
|
101
|
+
|
|
102
|
+
# Add new attributes
|
|
103
|
+
self._by_status[new_node.status].add(node_id)
|
|
104
|
+
self._by_priority[new_node.priority].add(node_id)
|
|
105
|
+
self._by_type[new_node.type].add(node_id)
|
|
106
|
+
|
|
107
|
+
# Clean up empty sets from old values
|
|
108
|
+
if not self._by_status[old_node.status]:
|
|
109
|
+
del self._by_status[old_node.status]
|
|
110
|
+
if not self._by_priority[old_node.priority]:
|
|
111
|
+
del self._by_priority[old_node.priority]
|
|
112
|
+
if not self._by_type[old_node.type]:
|
|
113
|
+
del self._by_type[old_node.type]
|
|
114
|
+
|
|
115
|
+
def get_by_status(self, status: str) -> set[str]:
|
|
116
|
+
"""
|
|
117
|
+
Get all node IDs with a specific status (O(1) lookup).
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
status: Status value to search for (e.g., "todo", "in-progress", "done")
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Set of node IDs with the given status
|
|
124
|
+
"""
|
|
125
|
+
return self._by_status.get(status, set()).copy()
|
|
126
|
+
|
|
127
|
+
def get_by_priority(self, priority: str) -> set[str]:
|
|
128
|
+
"""
|
|
129
|
+
Get all node IDs with a specific priority (O(1) lookup).
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
priority: Priority value to search for (e.g., "low", "medium", "high")
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Set of node IDs with the given priority
|
|
136
|
+
"""
|
|
137
|
+
return self._by_priority.get(priority, set()).copy()
|
|
138
|
+
|
|
139
|
+
def get_by_type(self, node_type: str) -> set[str]:
|
|
140
|
+
"""
|
|
141
|
+
Get all node IDs with a specific type (O(1) lookup).
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
node_type: Type value to search for (e.g., "feature", "bug", "task")
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
Set of node IDs with the given type
|
|
148
|
+
"""
|
|
149
|
+
return self._by_type.get(node_type, set()).copy()
|
|
150
|
+
|
|
151
|
+
def rebuild(self, nodes: dict[str, Node]) -> None:
|
|
152
|
+
"""
|
|
153
|
+
Rebuild the entire index from a node dictionary.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
nodes: Dictionary mapping node_id to Node objects
|
|
157
|
+
"""
|
|
158
|
+
self.clear()
|
|
159
|
+
|
|
160
|
+
for node_id, node in nodes.items():
|
|
161
|
+
self.add_node(node_id, node)
|
|
162
|
+
|
|
163
|
+
self._is_built = True
|
|
164
|
+
|
|
165
|
+
def ensure_built(self, nodes: dict[str, Node]) -> None:
|
|
166
|
+
"""
|
|
167
|
+
Ensure index is built (lazy initialization).
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
nodes: Dictionary mapping node_id to Node objects
|
|
171
|
+
"""
|
|
172
|
+
if not self._is_built:
|
|
173
|
+
self.rebuild(nodes)
|
|
174
|
+
|
|
175
|
+
def clear(self) -> None:
|
|
176
|
+
"""Clear all indexes."""
|
|
177
|
+
self._by_status.clear()
|
|
178
|
+
self._by_priority.clear()
|
|
179
|
+
self._by_type.clear()
|
|
180
|
+
self._is_built = False
|
|
181
|
+
|
|
182
|
+
@property
|
|
183
|
+
def is_built(self) -> bool:
|
|
184
|
+
"""Check if index has been built."""
|
|
185
|
+
return self._is_built
|
|
186
|
+
|
|
187
|
+
def stats(self) -> dict:
|
|
188
|
+
"""
|
|
189
|
+
Get index statistics.
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
Dictionary with index statistics
|
|
193
|
+
"""
|
|
194
|
+
return {
|
|
195
|
+
"is_built": self._is_built,
|
|
196
|
+
"statuses": list(self._by_status.keys()),
|
|
197
|
+
"priorities": list(self._by_priority.keys()),
|
|
198
|
+
"types": list(self._by_type.keys()),
|
|
199
|
+
"total_nodes_by_status": {
|
|
200
|
+
status: len(ids) for status, ids in self._by_status.items()
|
|
201
|
+
},
|
|
202
|
+
"total_nodes_by_priority": {
|
|
203
|
+
priority: len(ids) for priority, ids in self._by_priority.items()
|
|
204
|
+
},
|
|
205
|
+
"total_nodes_by_type": {
|
|
206
|
+
node_type: len(ids) for node_type, ids in self._by_type.items()
|
|
207
|
+
},
|
|
208
|
+
}
|