htmlgraph 0.20.2__py3-none-any.whl → 0.20.4__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 CHANGED
@@ -84,7 +84,7 @@ from htmlgraph.types import (
84
84
  )
85
85
  from htmlgraph.work_type_utils import infer_work_type, infer_work_type_from_id
86
86
 
87
- __version__ = "0.20.2"
87
+ __version__ = "0.20.4"
88
88
  __all__ = [
89
89
  # Exceptions
90
90
  "HtmlGraphError",
htmlgraph/cli.py CHANGED
@@ -2724,12 +2724,53 @@ def cmd_orchestrator_status(args: argparse.Namespace) -> None:
2724
2724
  print(f"Activated at: {status['activated_at']}")
2725
2725
  if status["auto_activated"]:
2726
2726
  print("Auto-activated: yes")
2727
+
2728
+ # Show violation tracking info
2729
+ violations = status.get("violations", 0)
2730
+ circuit_breaker = status.get("circuit_breaker_triggered", False)
2731
+ if violations > 0:
2732
+ print(f"Violations: {violations}/3")
2733
+ if circuit_breaker:
2734
+ print("⚠️ Circuit breaker: TRIGGERED")
2727
2735
  else:
2728
2736
  print("Orchestrator mode: disabled")
2729
2737
  if status["disabled_by_user"]:
2730
2738
  print("Disabled by user (auto-activation prevented)")
2731
2739
 
2732
2740
 
2741
+ def cmd_orchestrator_set_level(args: argparse.Namespace) -> None:
2742
+ """Set orchestrator mode enforcement level."""
2743
+ from typing import Literal
2744
+
2745
+ from htmlgraph.orchestrator_mode import OrchestratorModeManager
2746
+
2747
+ manager = OrchestratorModeManager(args.graph_dir)
2748
+ level: Literal["strict", "guidance"] = args.level
2749
+ manager.set_level(level)
2750
+
2751
+ level_text = "strict enforcement" if level == "strict" else "guidance mode"
2752
+ print(f"✓ Orchestrator enforcement level set to: {level_text}")
2753
+
2754
+
2755
+ def cmd_orchestrator_reset_violations(args: argparse.Namespace) -> None:
2756
+ """Reset orchestrator mode violation counter."""
2757
+ from htmlgraph.orchestrator_mode import OrchestratorModeManager
2758
+
2759
+ manager = OrchestratorModeManager(args.graph_dir)
2760
+
2761
+ # Check if mode is enabled
2762
+ if not manager.is_enabled():
2763
+ print("⚠️ Orchestrator mode is not enabled")
2764
+ return
2765
+
2766
+ # Reset violations
2767
+ manager.reset_violations()
2768
+
2769
+ print("✓ Violation counter reset")
2770
+ print("Circuit breaker: cleared")
2771
+ print("You can now continue with delegation workflow")
2772
+
2773
+
2733
2774
  def cmd_publish(args: argparse.Namespace) -> None:
2734
2775
  """Build and publish the package to PyPI (Interoperable)."""
2735
2776
  import shutil
@@ -3200,6 +3241,64 @@ def cmd_track_plan(args: argparse.Namespace) -> None:
3200
3241
  print(f"\nView plan: open {args.graph_dir}/tracks/{args.track_id}/plan.html")
3201
3242
 
3202
3243
 
3244
+ def cmd_track_show(args: argparse.Namespace) -> None:
3245
+ """Show details of a track."""
3246
+ import json
3247
+ from pathlib import Path
3248
+
3249
+ from htmlgraph.track_manager import TrackManager
3250
+
3251
+ manager = TrackManager(args.graph_dir)
3252
+
3253
+ # Load the track
3254
+ track = manager.load_track(args.track_id)
3255
+ if not track:
3256
+ print(f"Error: Track '{args.track_id}' not found", file=sys.stderr)
3257
+ sys.exit(1)
3258
+
3259
+ if args.format == "json":
3260
+ data = {
3261
+ "id": track.id,
3262
+ "title": track.title,
3263
+ "description": track.description,
3264
+ "status": track.status,
3265
+ "priority": track.priority,
3266
+ "has_spec": track.has_spec,
3267
+ "has_plan": track.has_plan,
3268
+ "created": track.created.isoformat(),
3269
+ "updated": track.updated.isoformat(),
3270
+ "features": track.features,
3271
+ "sessions": track.sessions,
3272
+ }
3273
+ print(json.dumps(data, indent=2))
3274
+ else:
3275
+ # Determine if consolidated or directory-based
3276
+ is_consolidated = manager.is_consolidated(args.track_id)
3277
+ if is_consolidated:
3278
+ track_file = Path(args.graph_dir) / "tracks" / f"{args.track_id}.html"
3279
+ file_type = "single file (consolidated)"
3280
+ else:
3281
+ track_file = Path(args.graph_dir) / "tracks" / args.track_id / "index.html"
3282
+ file_type = "directory-based"
3283
+
3284
+ print(f"Track: {track.id}")
3285
+ print(f" Title: {track.title}")
3286
+ print(f" Description: {track.description}")
3287
+ print(f" Status: {track.status}")
3288
+ print(f" Priority: {track.priority}")
3289
+ print(f" Format: {file_type}")
3290
+ print(f" Has Spec: {'Yes' if track.has_spec else 'No'}")
3291
+ print(f" Has Plan: {'Yes' if track.has_plan else 'No'}")
3292
+ print(f" Created: {track.created.strftime('%Y-%m-%d %H:%M')}")
3293
+ print(f" Updated: {track.updated.strftime('%Y-%m-%d %H:%M')}")
3294
+ if track.features:
3295
+ print(f" Features: {', '.join(track.features)}")
3296
+ if track.sessions:
3297
+ print(f" Sessions: {', '.join(track.sessions)}")
3298
+ print(f"\nPath: {track_file}")
3299
+ print(f"View: open {track_file}")
3300
+
3301
+
3203
3302
  def cmd_track_delete(args: argparse.Namespace) -> None:
3204
3303
  """Delete a track."""
3205
3304
  import json
@@ -4207,6 +4306,16 @@ For more help: https://github.com/Shakes-tzd/htmlgraph
4207
4306
  "--format", "-f", choices=["text", "json"], default="text", help="Output format"
4208
4307
  )
4209
4308
 
4309
+ # track show
4310
+ track_show = track_subparsers.add_parser("show", help="Show track details")
4311
+ track_show.add_argument("track_id", help="Track ID to display")
4312
+ track_show.add_argument(
4313
+ "--graph-dir", "-g", default=".htmlgraph", help="Graph directory"
4314
+ )
4315
+ track_show.add_argument(
4316
+ "--format", "-f", choices=["text", "json"], default="text", help="Output format"
4317
+ )
4318
+
4210
4319
  # track delete
4211
4320
  track_delete = track_subparsers.add_parser("delete", help="Delete a track")
4212
4321
  track_delete.add_argument("track_id", help="Track ID to delete")
@@ -4475,6 +4584,27 @@ For more help: https://github.com/Shakes-tzd/htmlgraph
4475
4584
  "--graph-dir", "-g", default=".htmlgraph", help="Graph directory"
4476
4585
  )
4477
4586
 
4587
+ # orchestrator set-level
4588
+ orchestrator_set_level = orchestrator_subparsers.add_parser(
4589
+ "set-level", help="Set enforcement level"
4590
+ )
4591
+ orchestrator_set_level.add_argument(
4592
+ "level",
4593
+ choices=["strict", "guidance"],
4594
+ help="Enforcement level to set",
4595
+ )
4596
+ orchestrator_set_level.add_argument(
4597
+ "--graph-dir", "-g", default=".htmlgraph", help="Graph directory"
4598
+ )
4599
+
4600
+ # orchestrator reset-violations
4601
+ orchestrator_reset_violations = orchestrator_subparsers.add_parser(
4602
+ "reset-violations", help="Reset violation counter and circuit breaker"
4603
+ )
4604
+ orchestrator_reset_violations.add_argument(
4605
+ "--graph-dir", "-g", default=".htmlgraph", help="Graph directory"
4606
+ )
4607
+
4478
4608
  # install-gemini-extension
4479
4609
  subparsers.add_parser(
4480
4610
  "install-gemini-extension",
@@ -4563,6 +4693,8 @@ For more help: https://github.com/Shakes-tzd/htmlgraph
4563
4693
  cmd_track_spec(args)
4564
4694
  elif args.track_command == "plan":
4565
4695
  cmd_track_plan(args)
4696
+ elif args.track_command == "show":
4697
+ cmd_track_show(args)
4566
4698
  elif args.track_command == "delete":
4567
4699
  cmd_track_delete(args)
4568
4700
  else:
@@ -4609,7 +4741,7 @@ For more help: https://github.com/Shakes-tzd/htmlgraph
4609
4741
  feature_parser.print_help()
4610
4742
  sys.exit(1)
4611
4743
  elif args.command == "analytics":
4612
- from htmlgraph.cli_analytics import cmd_analytics
4744
+ from htmlgraph.analytics.cli import cmd_analytics
4613
4745
 
4614
4746
  cmd_analytics(args)
4615
4747
  elif args.command == "events":
@@ -4678,6 +4810,10 @@ For more help: https://github.com/Shakes-tzd/htmlgraph
4678
4810
  cmd_orchestrator_disable(args)
4679
4811
  elif args.orchestrator_command == "status":
4680
4812
  cmd_orchestrator_status(args)
4813
+ elif args.orchestrator_command == "set-level":
4814
+ cmd_orchestrator_set_level(args)
4815
+ elif args.orchestrator_command == "reset-violations":
4816
+ cmd_orchestrator_reset_violations(args)
4681
4817
  else:
4682
4818
  orchestrator_parser.print_help()
4683
4819
  sys.exit(1)
@@ -358,6 +358,31 @@ def enforce_orchestrator_mode(tool: str, params: dict) -> dict:
358
358
  },
359
359
  }
360
360
 
361
+ # Check if circuit breaker is triggered in strict mode
362
+ if enforcement_level == "strict" and manager.is_circuit_breaker_triggered():
363
+ # Circuit breaker triggered - block all non-core operations
364
+ if tool not in ["Task", "AskUserQuestion", "TodoWrite"]:
365
+ circuit_breaker_message = (
366
+ "🚨 ORCHESTRATOR CIRCUIT BREAKER TRIGGERED\n\n"
367
+ f"You have violated delegation rules {manager.get_violation_count()} times this session.\n\n"
368
+ "Violations detected:\n"
369
+ "- Direct execution instead of delegation\n"
370
+ "- Context waste on tactical operations\n\n"
371
+ "Options:\n"
372
+ "1. Disable orchestrator mode: uv run htmlgraph orchestrator disable\n"
373
+ "2. Change to guidance mode: uv run htmlgraph orchestrator set-level guidance\n"
374
+ "3. Reset counter (acknowledge violations): uv run htmlgraph orchestrator reset-violations\n\n"
375
+ "To proceed, choose an option above."
376
+ )
377
+
378
+ return {
379
+ "hookSpecificOutput": {
380
+ "hookEventName": "PreToolUse",
381
+ "permissionDecision": "deny",
382
+ "permissionDecisionReason": circuit_breaker_message,
383
+ },
384
+ }
385
+
361
386
  # Check if operation is allowed
362
387
  is_allowed, reason, category = is_allowed_orchestrator_operation(tool, params)
363
388
 
@@ -386,19 +411,35 @@ def enforce_orchestrator_mode(tool: str, params: dict) -> dict:
386
411
  },
387
412
  }
388
413
 
389
- # Operation not allowed - provide strong warnings
390
- # NOTE: {"continue": False} doesn't work in Claude Code, so we use advisory warnings only
414
+ # Operation not allowed - track violation and provide warnings
415
+ if enforcement_level == "strict":
416
+ # Increment violation counter
417
+ mode = manager.increment_violation()
418
+ violations = mode.violations
419
+
391
420
  suggestion = create_task_suggestion(tool, params)
392
421
 
393
422
  if enforcement_level == "strict":
394
- # STRICT mode - loud warning but allow (blocking doesn't work)
423
+ # STRICT mode - loud warning with violation count
395
424
  error_message = (
396
- f"🚫 ORCHESTRATOR MODE VIOLATION: {reason}\n\n"
425
+ f"🚫 ORCHESTRATOR MODE VIOLATION ({violations}/3): {reason}\n\n"
397
426
  f"⚠️ WARNING: Direct operations waste context and break delegation pattern!\n\n"
398
427
  f"Suggested delegation:\n"
399
428
  f"{suggestion}\n\n"
400
- f"See ORCHESTRATOR_DIRECTIVES in session context for HtmlGraph delegation pattern.\n"
401
- f"To disable orchestrator mode: uv run htmlgraph orchestrator disable"
429
+ )
430
+
431
+ # Add circuit breaker warning if approaching threshold
432
+ if violations >= 3:
433
+ error_message += (
434
+ "🚨 CIRCUIT BREAKER TRIGGERED - Further violations will be blocked!\n\n"
435
+ "Reset with: uv run htmlgraph orchestrator reset-violations\n"
436
+ )
437
+ elif violations == 2:
438
+ error_message += "⚠️ Next violation will trigger circuit breaker!\n\n"
439
+
440
+ error_message += (
441
+ "See ORCHESTRATOR_DIRECTIVES in session context for HtmlGraph delegation pattern.\n"
442
+ "To disable orchestrator mode: uv run htmlgraph orchestrator disable"
402
443
  )
403
444
 
404
445
  return {
@@ -34,6 +34,15 @@ class OrchestratorMode(BaseModel):
34
34
  disabled_by_user: bool = False
35
35
  """Whether user explicitly disabled mode (prevents auto-reactivation)."""
36
36
 
37
+ violations: int = 0
38
+ """Count of delegation violations in current session."""
39
+
40
+ last_violation_at: datetime | None = None
41
+ """Timestamp of most recent violation."""
42
+
43
+ circuit_breaker_triggered: bool = False
44
+ """Whether circuit breaker has been triggered (3+ violations)."""
45
+
37
46
  def to_dict(self) -> dict:
38
47
  """Convert to dict for JSON serialization."""
39
48
  return {
@@ -45,6 +54,11 @@ class OrchestratorMode(BaseModel):
45
54
  "enforcement_level": self.enforcement_level,
46
55
  "auto_activated": self.auto_activated,
47
56
  "disabled_by_user": self.disabled_by_user,
57
+ "violations": self.violations,
58
+ "last_violation_at": (
59
+ self.last_violation_at.isoformat() if self.last_violation_at else None
60
+ ),
61
+ "circuit_breaker_triggered": self.circuit_breaker_triggered,
48
62
  }
49
63
 
50
64
  @classmethod
@@ -57,6 +71,13 @@ class OrchestratorMode(BaseModel):
57
71
  activated_at = activated_at[:-1] + "+00:00"
58
72
  activated_at = datetime.fromisoformat(activated_at)
59
73
 
74
+ last_violation_at = data.get("last_violation_at")
75
+ if last_violation_at:
76
+ # Handle both 'Z' suffix and '+00:00' timezone format
77
+ if last_violation_at.endswith("Z"):
78
+ last_violation_at = last_violation_at[:-1] + "+00:00"
79
+ last_violation_at = datetime.fromisoformat(last_violation_at)
80
+
60
81
  return cls(
61
82
  enabled=data.get("enabled", False),
62
83
  activated_at=activated_at,
@@ -64,6 +85,9 @@ class OrchestratorMode(BaseModel):
64
85
  enforcement_level=data.get("enforcement_level", "strict"),
65
86
  auto_activated=data.get("auto_activated", False),
66
87
  disabled_by_user=data.get("disabled_by_user", False),
88
+ violations=data.get("violations", 0),
89
+ last_violation_at=last_violation_at,
90
+ circuit_breaker_triggered=data.get("circuit_breaker_triggered", False),
67
91
  )
68
92
 
69
93
 
@@ -214,4 +238,58 @@ class OrchestratorModeManager:
214
238
  ),
215
239
  "auto_activated": mode.auto_activated,
216
240
  "disabled_by_user": mode.disabled_by_user,
241
+ "violations": mode.violations,
242
+ "circuit_breaker_triggered": mode.circuit_breaker_triggered,
217
243
  }
244
+
245
+ def increment_violation(self) -> OrchestratorMode:
246
+ """
247
+ Increment violation counter and update timestamp.
248
+
249
+ Returns:
250
+ Updated OrchestratorMode with incremented violations
251
+ """
252
+ mode = self.load()
253
+ mode.violations += 1
254
+ mode.last_violation_at = datetime.now(timezone.utc)
255
+
256
+ # Trigger circuit breaker if threshold reached
257
+ if mode.violations >= 3:
258
+ mode.circuit_breaker_triggered = True
259
+
260
+ self.save(mode)
261
+ return mode
262
+
263
+ def reset_violations(self) -> OrchestratorMode:
264
+ """
265
+ Reset violation counter and circuit breaker.
266
+
267
+ Returns:
268
+ Updated OrchestratorMode with reset violations
269
+ """
270
+ mode = self.load()
271
+ mode.violations = 0
272
+ mode.last_violation_at = None
273
+ mode.circuit_breaker_triggered = False
274
+ self.save(mode)
275
+ return mode
276
+
277
+ def is_circuit_breaker_triggered(self) -> bool:
278
+ """
279
+ Check if circuit breaker is currently triggered.
280
+
281
+ Returns:
282
+ True if circuit breaker is active
283
+ """
284
+ mode = self.load()
285
+ return mode.circuit_breaker_triggered
286
+
287
+ def get_violation_count(self) -> int:
288
+ """
289
+ Get current violation count.
290
+
291
+ Returns:
292
+ Number of violations in current session
293
+ """
294
+ mode = self.load()
295
+ return mode.violations
@@ -338,6 +338,44 @@ class TrackManager:
338
338
  track_id=track_id,
339
339
  )
340
340
 
341
+ def load_track(self, track_id: str) -> Track | None:
342
+ """
343
+ Load a track from disk.
344
+
345
+ Supports both consolidated (single .html file) and directory-based tracks.
346
+
347
+ Args:
348
+ track_id: Track ID
349
+
350
+ Returns:
351
+ Track instance or None if not found
352
+ """
353
+ track_path = self.get_track_path(track_id)
354
+ if track_path is None:
355
+ return None
356
+
357
+ # For now, return a basic Track instance
358
+ # TODO: Parse HTML back to Track using justhtml
359
+ if track_path.is_file():
360
+ # Consolidated format - single file
361
+ return Track(
362
+ id=track_id,
363
+ title=f"Track {track_id}",
364
+ description="Loaded from consolidated format",
365
+ )
366
+ else:
367
+ # Directory format - check for spec and plan
368
+ spec_exists = (track_path / "spec.html").exists()
369
+ plan_exists = (track_path / "plan.html").exists()
370
+
371
+ return Track(
372
+ id=track_id,
373
+ title=f"Track {track_id}",
374
+ description="Loaded from directory format",
375
+ has_spec=spec_exists,
376
+ has_plan=plan_exists,
377
+ )
378
+
341
379
  def list_tracks(self) -> list[str]:
342
380
  """
343
381
  List all track IDs.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: htmlgraph
3
- Version: 0.20.2
3
+ Version: 0.20.4
4
4
  Summary: HTML is All You Need - Graph database on web standards
5
5
  Project-URL: Homepage, https://github.com/Shakes-tzd/htmlgraph
6
6
  Project-URL: Documentation, https://github.com/Shakes-tzd/htmlgraph#readme
@@ -1,10 +1,10 @@
1
- htmlgraph/__init__.py,sha256=ir7qWjOnE7Sc50jVVHFNjiIkxAMkh77WXPpBP58aR_o,4979
1
+ htmlgraph/__init__.py,sha256=7HleUwg9jG5AvknycHtlXJl8D2JnyJGDTugHrdW95XU,4979
2
2
  htmlgraph/agent_detection.py,sha256=PAYo7rU3N_y1cGRd7Dwjh5Wgu-QZ7ENblX_yOzU-gJ0,2749
3
3
  htmlgraph/agent_registry.py,sha256=Usa_35by7p5gtpvHO7K3AcGimnorw-FzgPVa3cWTQ58,9448
4
4
  htmlgraph/agents.py,sha256=Yvu6x1nOfrW2WhRTAHiCuSpvqoVJXx1Mkzd59kwEczw,33466
5
5
  htmlgraph/analytics_index.py,sha256=ba6Y4H_NNOCxI_Z4U7wSgBFFairf4IJT74WcM1PoZuI,30594
6
6
  htmlgraph/attribute_index.py,sha256=cBZUV4YfGnhh6lF59aYPCdNrRr1hK__BzSKCueSDUhQ,6593
7
- htmlgraph/cli.py,sha256=OAEh2k2KOeMXYDK4ZeymHTP6VIkrhRAFh7Gug0tv9x4,168175
7
+ htmlgraph/cli.py,sha256=wYoCjciu1cHqwZe84u2TgO7lS_YyTs4yX5ipLLUqUfo,173218
8
8
  htmlgraph/context_analytics.py,sha256=CaLu0o2uSr6rlBM5YeaFZe7grgsy7_Hx10qdXuNcdao,11344
9
9
  htmlgraph/converter.py,sha256=SHS_7F6DHCPhmpZcLl3wN2LgGGP4XWApZ9TkW-u5m_c,20556
10
10
  htmlgraph/dashboard.html,sha256=rkZYjSnPbUuAm35QMpCNWemenYqQTdkkumCX2hhe8Dc,173537
@@ -26,7 +26,7 @@ htmlgraph/mcp_server.py,sha256=AeJeGJEtX5Dqu5rfhKfT5kwF2Oe8V8xCaP8BgMEh86s,24033
26
26
  htmlgraph/models.py,sha256=yz5GrSRvQCC2Qy2ozOOfNm5Tw6mXaXZaACkajSjJnqg,79911
27
27
  htmlgraph/orchestration.py,sha256=7_oQ4AlHOv14hs6RvLsatJzF-F5gkIbv1EOrmeGPhiw,9699
28
28
  htmlgraph/orchestrator.py,sha256=6mj70vroWjmNmdvQ7jqqRSA9O1rFUNMUYDWPzqkizLk,19697
29
- htmlgraph/orchestrator_mode.py,sha256=00-hOeqt7WJlMcWG-hGbGq0EK9qIhw_HUxx8LNWi1do,6579
29
+ htmlgraph/orchestrator_mode.py,sha256=F6LNZARqieQXUri3CRSq_lsqFbnVeGXJQPno1ZP47O4,9187
30
30
  htmlgraph/orchestrator_validator.py,sha256=gd_KbHsRsNEIF7EElwcxbMYqOMlyeuYIZwClASp-L-E,4699
31
31
  htmlgraph/parallel.py,sha256=BsyqGKWY_DkSRElBdvvAkWlL6stC9BPkyxjdPdggx_w,22418
32
32
  htmlgraph/parser.py,sha256=JM2cSxEK_2shf_cW7otLToD-83jtEakX2_B4VUfqLGU,13567
@@ -42,7 +42,7 @@ htmlgraph/spike_index.py,sha256=-qsJc92MtxJN1whHqV1SGU6HjXkKeG2Vsg7l3q2ReRg,4264
42
42
  htmlgraph/styles.css,sha256=oDUSC8jG-V-hKojOBO9J88hxAeY2wJrBYTq0uCwX_Y4,7135
43
43
  htmlgraph/sync_docs.py,sha256=CH1xB3OeOFG6Wmo_D_r1aiGWS1P1gE7hfjJySCEz7bc,9114
44
44
  htmlgraph/track_builder.py,sha256=3Ldtv6OsBfrCqpXiUB13TOjuchJdgo4IuOYnFCaxc1k,6009
45
- htmlgraph/track_manager.py,sha256=euNXQustRRmqeuwsN08jlDnQ4qbRZ02oedaFdaOGFi0,21223
45
+ htmlgraph/track_manager.py,sha256=HhCg0nFOy_dx2R0_Bb2IOx9dA2lPfg7dM-_O3vBmlRU,22445
46
46
  htmlgraph/transcript.py,sha256=uk_I9tirypUdMRfKxJmoHuaySxlu1OWt7xy774KYZNw,31808
47
47
  htmlgraph/transcript_analytics.py,sha256=O-T7SfM3gJIbGFNPlF3gmKjcy--NzPiJt03lvTC209w,24922
48
48
  htmlgraph/types.py,sha256=EBxCbke3PhORsmIhHrD-f1XG6YPRX-1D5R1OXCp6xt8,8945
@@ -87,7 +87,7 @@ htmlgraph/hooks/__init__.py,sha256=jL2HyCoFWQQ8l-4-EAlypDxPalNE3JBfDyELYWAg-g0,8
87
87
  htmlgraph/hooks/event_tracker.py,sha256=KQcIWbhNJser6Tip87oUAPQJgUAAKESKE5ARQasLtCM,23301
88
88
  htmlgraph/hooks/hooks-config.example.json,sha256=tXpk-U-FZzGOoNJK2uiDMbIHCYEHA794J-El0fBwkqg,197
89
89
  htmlgraph/hooks/installer.py,sha256=nOctCFDEV7BEh7ZzxNY-apu1KZG0SHPMq74UPIOChqY,11756
90
- htmlgraph/hooks/orchestrator.py,sha256=dZAFn7Sy6tSnIDt4HL88tRlw3_OUsHCklX5VJk7yFD0,15246
90
+ htmlgraph/hooks/orchestrator.py,sha256=55xjmfg680e9PKcMkBmpbAmSXkZa33EQcZXlwPjDn50,17105
91
91
  htmlgraph/hooks/orchestrator_reflector.py,sha256=j3kZge33m42CEUVYiufiz7mf7Qm4DimnsRZKjbpZStA,5154
92
92
  htmlgraph/hooks/post-checkout.sh,sha256=Hsr5hqD54jisGbtqf7-Z-G_b6XNGcee_CZRYaKYzWzU,615
93
93
  htmlgraph/hooks/post-commit.sh,sha256=if65jNGZnEWsZPq_iYDNYunrZ1cmjPUEUbh6_4vfpOE,511
@@ -107,12 +107,12 @@ htmlgraph/services/claiming.py,sha256=HcrltEJKN72mxuD7fGuXWeh1U0vwhjMvhZcFc02Eiy
107
107
  htmlgraph/templates/AGENTS.md.template,sha256=f96h7V6ygwj-v-fanVI48eYMxR6t_se4bet1H4ZsDpI,7642
108
108
  htmlgraph/templates/CLAUDE.md.template,sha256=h1kG2hTX2XYig2KszsHBfzrwa_4Cfcq2Pj4SwqzeDlM,1984
109
109
  htmlgraph/templates/GEMINI.md.template,sha256=gAGzE53Avki87BM_otqy5HdcYCoLsHgqaKjVzNzPMX8,1622
110
- htmlgraph-0.20.2.data/data/htmlgraph/dashboard.html,sha256=rkZYjSnPbUuAm35QMpCNWemenYqQTdkkumCX2hhe8Dc,173537
111
- htmlgraph-0.20.2.data/data/htmlgraph/styles.css,sha256=oDUSC8jG-V-hKojOBO9J88hxAeY2wJrBYTq0uCwX_Y4,7135
112
- htmlgraph-0.20.2.data/data/htmlgraph/templates/AGENTS.md.template,sha256=f96h7V6ygwj-v-fanVI48eYMxR6t_se4bet1H4ZsDpI,7642
113
- htmlgraph-0.20.2.data/data/htmlgraph/templates/CLAUDE.md.template,sha256=h1kG2hTX2XYig2KszsHBfzrwa_4Cfcq2Pj4SwqzeDlM,1984
114
- htmlgraph-0.20.2.data/data/htmlgraph/templates/GEMINI.md.template,sha256=gAGzE53Avki87BM_otqy5HdcYCoLsHgqaKjVzNzPMX8,1622
115
- htmlgraph-0.20.2.dist-info/METADATA,sha256=13RsfZ3io-sOjZUN1Z7anK1janvvOrfwWF-ETj6ouOM,7645
116
- htmlgraph-0.20.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
117
- htmlgraph-0.20.2.dist-info/entry_points.txt,sha256=EaUbjA_bbDwEO_XDLEGMeK8aQP-ZnHiUTkLshyKDyB8,98
118
- htmlgraph-0.20.2.dist-info/RECORD,,
110
+ htmlgraph-0.20.4.data/data/htmlgraph/dashboard.html,sha256=rkZYjSnPbUuAm35QMpCNWemenYqQTdkkumCX2hhe8Dc,173537
111
+ htmlgraph-0.20.4.data/data/htmlgraph/styles.css,sha256=oDUSC8jG-V-hKojOBO9J88hxAeY2wJrBYTq0uCwX_Y4,7135
112
+ htmlgraph-0.20.4.data/data/htmlgraph/templates/AGENTS.md.template,sha256=f96h7V6ygwj-v-fanVI48eYMxR6t_se4bet1H4ZsDpI,7642
113
+ htmlgraph-0.20.4.data/data/htmlgraph/templates/CLAUDE.md.template,sha256=h1kG2hTX2XYig2KszsHBfzrwa_4Cfcq2Pj4SwqzeDlM,1984
114
+ htmlgraph-0.20.4.data/data/htmlgraph/templates/GEMINI.md.template,sha256=gAGzE53Avki87BM_otqy5HdcYCoLsHgqaKjVzNzPMX8,1622
115
+ htmlgraph-0.20.4.dist-info/METADATA,sha256=b_kFOPIXxYM38kXPcp30icc3idKjo9_CcnQh2QOjnOM,7645
116
+ htmlgraph-0.20.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
117
+ htmlgraph-0.20.4.dist-info/entry_points.txt,sha256=EaUbjA_bbDwEO_XDLEGMeK8aQP-ZnHiUTkLshyKDyB8,98
118
+ htmlgraph-0.20.4.dist-info/RECORD,,