htmlgraph 0.26.23__py3-none-any.whl → 0.26.25__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. htmlgraph/__init__.py +1 -1
  2. htmlgraph/analytics/pattern_learning.py +771 -0
  3. htmlgraph/api/main.py +56 -23
  4. htmlgraph/api/templates/dashboard-redesign.html +3 -3
  5. htmlgraph/api/templates/dashboard.html +3 -3
  6. htmlgraph/api/templates/partials/work-items.html +613 -0
  7. htmlgraph/builders/track.py +26 -0
  8. htmlgraph/cli/base.py +31 -7
  9. htmlgraph/cli/work/__init__.py +74 -0
  10. htmlgraph/cli/work/browse.py +114 -0
  11. htmlgraph/cli/work/snapshot.py +558 -0
  12. htmlgraph/collections/base.py +34 -0
  13. htmlgraph/collections/todo.py +12 -0
  14. htmlgraph/converter.py +11 -0
  15. htmlgraph/db/schema.py +34 -1
  16. htmlgraph/hooks/orchestrator.py +88 -14
  17. htmlgraph/hooks/session_handler.py +3 -1
  18. htmlgraph/models.py +22 -2
  19. htmlgraph/orchestration/__init__.py +4 -0
  20. htmlgraph/orchestration/plugin_manager.py +1 -2
  21. htmlgraph/orchestration/spawner_event_tracker.py +383 -0
  22. htmlgraph/refs.py +343 -0
  23. htmlgraph/sdk.py +162 -1
  24. htmlgraph/session_manager.py +154 -2
  25. htmlgraph/sessions/__init__.py +23 -0
  26. htmlgraph/sessions/handoff.py +755 -0
  27. htmlgraph/track_builder.py +12 -0
  28. {htmlgraph-0.26.23.dist-info → htmlgraph-0.26.25.dist-info}/METADATA +1 -1
  29. {htmlgraph-0.26.23.dist-info → htmlgraph-0.26.25.dist-info}/RECORD +36 -28
  30. {htmlgraph-0.26.23.data → htmlgraph-0.26.25.data}/data/htmlgraph/dashboard.html +0 -0
  31. {htmlgraph-0.26.23.data → htmlgraph-0.26.25.data}/data/htmlgraph/styles.css +0 -0
  32. {htmlgraph-0.26.23.data → htmlgraph-0.26.25.data}/data/htmlgraph/templates/AGENTS.md.template +0 -0
  33. {htmlgraph-0.26.23.data → htmlgraph-0.26.25.data}/data/htmlgraph/templates/CLAUDE.md.template +0 -0
  34. {htmlgraph-0.26.23.data → htmlgraph-0.26.25.data}/data/htmlgraph/templates/GEMINI.md.template +0 -0
  35. {htmlgraph-0.26.23.dist-info → htmlgraph-0.26.25.dist-info}/WHEEL +0 -0
  36. {htmlgraph-0.26.23.dist-info → htmlgraph-0.26.25.dist-info}/entry_points.txt +0 -0
@@ -186,7 +186,7 @@ class SessionManager:
186
186
  """Mark a session as stale (kept for history but not considered active)."""
187
187
  if session.status != "active":
188
188
  return
189
- now = datetime.now()
189
+ now = datetime.now(timezone.utc)
190
190
  session.status = "stale"
191
191
  session.ended_at = now
192
192
  session.last_activity = now
@@ -742,7 +742,7 @@ class SessionManager:
742
742
  ActivityEntry(
743
743
  tool="SessionEnd",
744
744
  summary="Session ended",
745
- timestamp=datetime.now(),
745
+ timestamp=datetime.now(timezone.utc),
746
746
  )
747
747
  )
748
748
 
@@ -792,6 +792,158 @@ class SessionManager:
792
792
 
793
793
  return session
794
794
 
795
+ def continue_from_last(
796
+ self,
797
+ agent: str | None = None,
798
+ auto_create_session: bool = True,
799
+ ) -> tuple[Session | None, Any]: # Returns (new_session, resume_info)
800
+ """
801
+ Continue work from the last completed session.
802
+
803
+ Loads context from the previous session including:
804
+ - Handoff notes and next focus
805
+ - Blockers
806
+ - Recommended context files
807
+ - Recent commits
808
+ - Features worked on
809
+
810
+ Args:
811
+ agent: Filter by agent (None = current agent)
812
+ auto_create_session: Create new session if True
813
+
814
+ Returns:
815
+ Tuple of (new_session, resume_info) or (None, None) if no previous session
816
+
817
+ Example:
818
+ >>> manager = SessionManager(".htmlgraph")
819
+ >>> new_session, resume = manager.continue_from_last(agent="claude")
820
+ >>> if resume:
821
+ ... print(resume.summary)
822
+ ... print(resume.recommended_files)
823
+ """
824
+ # Import handoff module
825
+ from typing import Any
826
+
827
+ from htmlgraph.sessions.handoff import SessionResume
828
+
829
+ # Create a minimal SDK-like object with just the directory
830
+ # to avoid circular dependency and database initialization issues
831
+ class MinimalSDK:
832
+ def __init__(self, directory: Path) -> None:
833
+ self._directory = directory
834
+
835
+ sdk: Any = MinimalSDK(self.graph_dir)
836
+ resume = SessionResume(sdk)
837
+
838
+ # Get last session
839
+ last_session = resume.get_last_session(agent=agent)
840
+ if not last_session:
841
+ return None, None
842
+
843
+ # Build resume info
844
+ resume_info = resume.build_resume_info(last_session)
845
+
846
+ # Create new session if requested
847
+ new_session = None
848
+ if auto_create_session:
849
+ from htmlgraph.ids import generate_id
850
+
851
+ session_id = generate_id("sess")
852
+ new_session = self.start_session(
853
+ session_id=session_id,
854
+ agent=agent or last_session.agent,
855
+ title=f"Continuing from {last_session.id}",
856
+ )
857
+
858
+ # Link to previous session
859
+ new_session.continued_from = last_session.id
860
+ self.session_converter.save(new_session)
861
+
862
+ return new_session, resume_info
863
+
864
+ def end_session_with_handoff(
865
+ self,
866
+ session_id: str,
867
+ summary: str | None = None,
868
+ next_focus: str | None = None,
869
+ blockers: list[str] | None = None,
870
+ keep_context: list[str] | None = None,
871
+ auto_recommend_context: bool = True,
872
+ ) -> Session | None:
873
+ """
874
+ End session with handoff information for next session.
875
+
876
+ Args:
877
+ session_id: Session to end
878
+ summary: What was accomplished (handoff notes)
879
+ next_focus: What should be done next
880
+ blockers: List of blockers preventing progress
881
+ keep_context: List of files to keep context for
882
+ auto_recommend_context: Auto-recommend files from git history
883
+
884
+ Returns:
885
+ Updated session or None
886
+
887
+ Example:
888
+ >>> manager.end_session_with_handoff(
889
+ ... session_id="sess-123",
890
+ ... summary="Completed OAuth integration",
891
+ ... next_focus="Implement JWT token refresh",
892
+ ... blockers=["Waiting for security review"],
893
+ ... keep_context=["src/auth/oauth.py"]
894
+ ... )
895
+ """
896
+ from htmlgraph.sessions.handoff import (
897
+ ContextRecommender,
898
+ HandoffBuilder,
899
+ )
900
+
901
+ # Get session
902
+ session = self.get_session(session_id)
903
+ if not session:
904
+ return None
905
+
906
+ # Build handoff using HandoffBuilder
907
+ builder = HandoffBuilder(session)
908
+
909
+ if summary:
910
+ builder.add_summary(summary)
911
+
912
+ if next_focus:
913
+ builder.add_next_focus(next_focus)
914
+
915
+ if blockers:
916
+ builder.add_blockers(blockers)
917
+
918
+ if keep_context:
919
+ builder.add_context_files(keep_context)
920
+
921
+ # Auto-recommend context files
922
+ if auto_recommend_context:
923
+ recommender = ContextRecommender()
924
+ builder.auto_recommend_context(recommender, max_files=10)
925
+
926
+ handoff_data = builder.build()
927
+
928
+ # Update session with handoff data
929
+ session.handoff_notes = handoff_data["handoff_notes"]
930
+ session.recommended_next = handoff_data["recommended_next"]
931
+ session.blockers = handoff_data["blockers"]
932
+ session.recommended_context = handoff_data["recommended_context"]
933
+
934
+ # Persist handoff data to database before ending session
935
+ self.session_converter.save(session)
936
+
937
+ # End the session
938
+ self.end_session(session_id)
939
+
940
+ # Track handoff effectiveness (optional - only if database available)
941
+ # Note: SessionManager doesn't have direct database access,
942
+ # handoff tracking is primarily done through SDK
943
+ # Users should use SDK.end_session_with_handoff() for full tracking
944
+
945
+ return session
946
+
795
947
  def release_session_features(self, session_id: str) -> list[str]:
796
948
  """
797
949
  Release all features claimed by a specific session.
@@ -0,0 +1,23 @@
1
+ """
2
+ Session management and continuity.
3
+
4
+ Provides session lifecycle, handoff, and resumption features.
5
+ """
6
+
7
+ from htmlgraph.sessions.handoff import (
8
+ ContextRecommender,
9
+ HandoffBuilder,
10
+ HandoffMetrics,
11
+ HandoffTracker,
12
+ SessionResume,
13
+ SessionResumeInfo,
14
+ )
15
+
16
+ __all__ = [
17
+ "HandoffBuilder",
18
+ "SessionResume",
19
+ "SessionResumeInfo",
20
+ "HandoffTracker",
21
+ "HandoffMetrics",
22
+ "ContextRecommender",
23
+ ]