htmlgraph 0.23.0__py3-none-any.whl → 0.23.2__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.23.0"
87
+ __version__ = "0.23.2"
88
88
  __all__ = [
89
89
  # Exceptions
90
90
  "HtmlGraphError",
htmlgraph/event_log.py CHANGED
@@ -38,6 +38,22 @@ class EventRecord:
38
38
  session_status: str | None = None
39
39
  file_paths: list[str] | None = None
40
40
  payload: dict[str, Any] | None = None
41
+ # Phase 1: Enhanced Event Data Schema for multi-AI delegation tracking
42
+ delegated_to_ai: str | None = (
43
+ None # "gemini", "codex", "copilot", "claude", or None
44
+ )
45
+ task_id: str | None = None # Unique task ID for parallel tracking
46
+ task_status: str | None = (
47
+ None # "pending", "running", "completed", "failed", "timeout"
48
+ )
49
+ model_selected: str | None = None # Specific model (e.g., "gemini-2.0-flash")
50
+ complexity_level: str | None = None # "low", "medium", "high", "very-high"
51
+ budget_mode: str | None = None # "free", "balanced", "performance"
52
+ execution_duration_seconds: float | None = None # How long delegation took
53
+ tokens_estimated: int | None = None # Estimated token usage
54
+ tokens_actual: int | None = None # Actual token usage
55
+ cost_usd: float | None = None # Calculated cost
56
+ task_findings: str | None = None # Results from delegated task
41
57
 
42
58
  def to_json(self) -> dict[str, Any]:
43
59
  return {
@@ -56,6 +72,18 @@ class EventRecord:
56
72
  "session_status": self.session_status,
57
73
  "file_paths": self.file_paths or [],
58
74
  "payload": self.payload,
75
+ # Delegation fields
76
+ "delegated_to_ai": self.delegated_to_ai,
77
+ "task_id": self.task_id,
78
+ "task_status": self.task_status,
79
+ "model_selected": self.model_selected,
80
+ "complexity_level": self.complexity_level,
81
+ "budget_mode": self.budget_mode,
82
+ "execution_duration_seconds": self.execution_duration_seconds,
83
+ "tokens_estimated": self.tokens_estimated,
84
+ "tokens_actual": self.tokens_actual,
85
+ "cost_usd": self.cost_usd,
86
+ "task_findings": self.task_findings,
59
87
  }
60
88
 
61
89
 
@@ -107,6 +107,23 @@ def is_allowed_orchestrator_operation(tool: str, params: dict) -> tuple[bool, st
107
107
  - reason_if_not: Explanation if blocked (empty if allowed)
108
108
  - category: Operation category for logging
109
109
  """
110
+ # Get enforcement level from manager
111
+ try:
112
+ cwd = Path.cwd()
113
+ graph_dir = cwd / ".htmlgraph"
114
+ if not graph_dir.exists():
115
+ for parent in [cwd.parent, cwd.parent.parent, cwd.parent.parent.parent]:
116
+ candidate = parent / ".htmlgraph"
117
+ if candidate.exists():
118
+ graph_dir = candidate
119
+ break
120
+ manager = OrchestratorModeManager(graph_dir)
121
+ enforcement_level = (
122
+ manager.get_enforcement_level() if manager.is_enabled() else "guidance"
123
+ )
124
+ except Exception:
125
+ enforcement_level = "guidance"
126
+
110
127
  # Use OrchestratorValidator for comprehensive validation
111
128
  validator = OrchestratorValidator()
112
129
  result, reason = validator.validate_tool_use(tool, params)
@@ -121,6 +138,10 @@ def is_allowed_orchestrator_operation(tool: str, params: dict) -> tuple[bool, st
121
138
  if tool in ["Task", "AskUserQuestion", "TodoWrite"]:
122
139
  return True, "", "orchestrator-core"
123
140
 
141
+ # FIX #2: Block Skills in strict mode (must be invoked via Task delegation)
142
+ if tool == "Skill" and enforcement_level == "strict":
143
+ return False, "Skills must be invoked via Task delegation", "skill-blocked"
144
+
124
145
  # Category 2: SDK Operations - Always allowed
125
146
  if tool == "Bash":
126
147
  command = params.get("command", "")
@@ -141,11 +162,51 @@ def is_allowed_orchestrator_operation(tool: str, params: dict) -> tuple[bool, st
141
162
  if "from htmlgraph import" in command or "import htmlgraph" in command:
142
163
  return True, "", "sdk-inline"
143
164
 
165
+ # FIX #3: Check if bash command is in allowed whitelist (strict mode only)
166
+ # If we've gotten here, it's not a whitelisted command above
167
+ # Block non-whitelisted bash commands in strict mode
168
+ if enforcement_level == "strict":
169
+ # Check if it's a blocked test/build pattern (handled below)
170
+ blocked_patterns = [
171
+ r"^npm (run|test|build)",
172
+ r"^pytest",
173
+ r"^uv run pytest",
174
+ r"^python -m pytest",
175
+ r"^cargo (build|test)",
176
+ r"^mvn (compile|test|package)",
177
+ r"^make (test|build)",
178
+ ]
179
+ is_blocked_pattern = any(
180
+ re.match(pattern, command) for pattern in blocked_patterns
181
+ )
182
+
183
+ if not is_blocked_pattern:
184
+ # Not a specifically blocked pattern, but also not whitelisted
185
+ # In strict mode, we should delegate
186
+ return (
187
+ False,
188
+ f"Bash command not in allowed list. Delegate to subagent.\n\n"
189
+ f"Command: {command[:100]}",
190
+ "bash-blocked",
191
+ )
192
+
144
193
  # Category 3: Quick Lookups - Single operations only
145
194
  if tool in ["Read", "Grep", "Glob"]:
146
195
  # Check tool history to see if this is a single lookup or part of a sequence
147
196
  history = load_tool_history()
148
197
 
198
+ # FIX #4: Check for mixed exploration pattern
199
+ exploration_count = sum(
200
+ 1 for h in history[-5:] if h["tool"] in ["Read", "Grep", "Glob"]
201
+ )
202
+ if exploration_count >= 3 and enforcement_level == "strict":
203
+ return (
204
+ False,
205
+ "Multiple exploration calls detected. Delegate to Explorer agent.\n\n"
206
+ "Use Task tool with explorer subagent.",
207
+ "exploration-blocked",
208
+ )
209
+
149
210
  # Look at last 3 tool calls
150
211
  recent_same_tool = sum(1 for h in history[-3:] if h["tool"] == tool)
151
212
 
@@ -181,7 +242,7 @@ def is_allowed_orchestrator_operation(tool: str, params: dict) -> tuple[bool, st
181
242
  command = params.get("command", "")
182
243
 
183
244
  # Block compilation, testing, building (should be in subagent)
184
- blocked_patterns = [
245
+ test_build_patterns: list[tuple[str, str]] = [
185
246
  (r"^npm (run|test|build)", "npm test/build"),
186
247
  (r"^pytest", "pytest"),
187
248
  (r"^uv run pytest", "pytest"),
@@ -191,7 +252,7 @@ def is_allowed_orchestrator_operation(tool: str, params: dict) -> tuple[bool, st
191
252
  (r"^make (test|build)", "make test/build"),
192
253
  ]
193
254
 
194
- for pattern, name in blocked_patterns:
255
+ for pattern, name in test_build_patterns:
195
256
  if re.match(pattern, command):
196
257
  return (
197
258
  False,
@@ -200,8 +261,11 @@ def is_allowed_orchestrator_operation(tool: str, params: dict) -> tuple[bool, st
200
261
  "test-build-blocked",
201
262
  )
202
263
 
203
- # Default: Allow with guidance
204
- return True, "Allowed but consider if delegation would be better", "allowed-default"
264
+ # FIX #1: Remove "allowed-default" escape hatch in strict mode
265
+ if enforcement_level == "strict":
266
+ return False, "Not in allowed whitelist", "strict-blocked"
267
+ else:
268
+ return True, "Allowed in guidance mode", "guidance-allowed"
205
269
 
206
270
 
207
271
  def create_task_suggestion(tool: str, params: dict) -> str:
@@ -1,14 +1,58 @@
1
- # ORCHESTRATOR SYSTEM PROMPT (Minimal)
1
+ # ORCHESTRATOR SYSTEM PROMPT
2
2
 
3
3
  **Core Principle:** Delegation > Direct Execution. Cascading failures consume exponentially more context than structured delegation.
4
4
 
5
- ## Execute Directly (Strategic Only)
5
+ ## What is HtmlGraph?
6
6
 
7
- Only when ALL true:
8
- - Planning/Design/Decisions - Architectural choices
9
- - Single Tool Call - No error handling needed
10
- - SDK Operations - HtmlGraph feature/spike creation
11
- - Clarifying Requirements - User questions
7
+ Lightweight graph database for AI coordination and human observability. HTML files = nodes, hyperlinks = edges, CSS selectors = queries. Zero dependencies, offline-first. Use SDK for ALL operations tracking.
8
+
9
+ ## Operation Backbone: HtmlGraph + Git
10
+
11
+ ALWAYS use both:
12
+ - **HtmlGraph SDK**: Track what you're doing (features, spikes, sessions, analytics)
13
+ - **Git**: Track code changes, commits, attribution
14
+ - Together: Complete project history + observability
15
+
16
+ ## Speed & Currency
17
+
18
+ - Use WebSearch for up-to-date information (check current date/time)
19
+ - Use scripting (Python, Bash) for automation
20
+ - Prefer web lookups over assumptions for time-sensitive tasks
21
+
22
+ ## Spec-Driven Development
23
+
24
+ Write specs before implementation:
25
+ - Use TrackBuilder for multi-feature planning
26
+ - Document requirements and acceptance criteria
27
+ - Pattern: Plan → Implement → Validate
28
+
29
+ ## Testing Philosophy
30
+
31
+ - UI testing: Use browser automation tools (Chrome MCP)
32
+ - Test incrementally, not at the end
33
+ - Automated testing is non-negotiable
34
+ - Quality gates: ruff, mypy, pytest
35
+
36
+ ## Layered Planning Model
37
+
38
+ Delegate planning based on complexity and inputs:
39
+
40
+ 1. **Exploration** → Gemini (affordable, high context)
41
+ - Broad research, codebase exploration, options analysis
42
+
43
+ 2. **Strategic Planning** → Claude Opus (concrete inputs needed)
44
+ - High-level architecture, elegant solutions, critical decisions
45
+
46
+ 3. **Coordination** → Claude Sonnet (mid-level)
47
+ - Feature orchestration, multi-component decisions
48
+
49
+ 4. **Execution** → Haiku (tactical)
50
+ - Implementation, file operations, testing
51
+
52
+ Execute directly ONLY:
53
+ - SDK operations (feature/spike creation)
54
+ - User clarification (AskUserQuestion)
55
+ - TodoWrite (task tracking)
12
56
 
13
57
  ## Delegate Everything Else
14
58
 
@@ -18,9 +62,10 @@ Git, code changes, testing, research, deployment - DELEGATE.
18
62
 
19
63
  ## Quick Decision Tree
20
64
 
21
- 1. Strategic (decisions/planning)? → Execute directly
22
- 2. Single tool, no errors? → Execute directly
23
- 3. Everything elseDELEGATE
65
+ 1. SDK/TodoWrite/User question? → Execute directly
66
+ 2. Exploration/research? → Delegate to Gemini
67
+ 3. Strategic planning (with inputs)? Delegate to Opus
68
+ 4. Everything else → DELEGATE (Sonnet/Haiku)
24
69
 
25
70
  ## Spawner Selection (Brief)
26
71
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: htmlgraph
3
- Version: 0.23.0
3
+ Version: 0.23.2
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,4 +1,4 @@
1
- htmlgraph/__init__.py,sha256=lsnihHBI-FCjus10dqcyw6LgbtkXDvg4PliTsz5qvTY,4979
1
+ htmlgraph/__init__.py,sha256=CpjmLuef0RQAd4Op9FbEPyFMeLmaavFZMejnMU9FbWM,4979
2
2
  htmlgraph/agent_detection.py,sha256=MG1kx9S-ey_Wi84hJTwwgw6VDvYEbUpygmDjGPhHcUA,3805
3
3
  htmlgraph/agent_registry.py,sha256=Usa_35by7p5gtpvHO7K3AcGimnorw-FzgPVa3cWTQ58,9448
4
4
  htmlgraph/agents.py,sha256=Yvu6x1nOfrW2WhRTAHiCuSpvqoVJXx1Mkzd59kwEczw,33466
@@ -12,7 +12,7 @@ htmlgraph/dependency_models.py,sha256=eKpBz9y_pTE5E8baESqHyGUDj5-uXokVd2Bx3ZogAy
12
12
  htmlgraph/deploy.py,sha256=kM_IMa3PmKpQf4YVH57aL9uV5IfpVJgaj-IFsgAKIbY,17771
13
13
  htmlgraph/deployment_models.py,sha256=8pjvfe0YmExuYg65D4jO4kET52HaG8WhcArWXOJpfCQ,16064
14
14
  htmlgraph/edge_index.py,sha256=epeUiTj1Hm-NQj8WCWjSUypG1e8Z2hJulNT9drHstcM,14937
15
- htmlgraph/event_log.py,sha256=BjLmN73ohqwhTUQrlTd4E53eoitbMExmFCVRGNjlNY0,7866
15
+ htmlgraph/event_log.py,sha256=zJUefAaz97LvoVA-pi8uVMcCqA_pyS_saVczbioQf-Q,9372
16
16
  htmlgraph/event_migration.py,sha256=7vocfwy-E6_D8_Aeql630FrlBXppIYp1iLmZ_cw_ras,2512
17
17
  htmlgraph/exceptions.py,sha256=o_BPNQXtv9zaejbiItDVBK7kcGvYbh4Icj5NXmDSLeU,1592
18
18
  htmlgraph/file_watcher.py,sha256=qwwmDkWnKLPp8a_48VrtJZo6HcoYPRz1KMAD39yCV7U,6296
@@ -24,7 +24,7 @@ htmlgraph/index.d.ts,sha256=7dvExfA16g1z5Kut8xyHnSUfZ6wiUUwWNy6R7WKiwas,6922
24
24
  htmlgraph/learning.py,sha256=6SsRdz-xJGFPjp7YagpUDTZqqjNKp2wWihcnhwkHys0,28566
25
25
  htmlgraph/mcp_server.py,sha256=AeJeGJEtX5Dqu5rfhKfT5kwF2Oe8V8xCaP8BgMEh86s,24033
26
26
  htmlgraph/models.py,sha256=tgFFFwOuEe7Yal5I1JTZHJnF625oaHMATEGIvJgrFnk,81818
27
- htmlgraph/orchestrator-system-prompt-optimized.txt,sha256=yCXIM-gH7nSDJfh9UFsvu_VHimKI_Rra3sWvF7fMqEw,1350
27
+ htmlgraph/orchestrator-system-prompt-optimized.txt,sha256=8UptB4-jmyz0OrjRm5VlJqBxzk3oXNJEgUQChuTWhR8,2885
28
28
  htmlgraph/orchestrator.py,sha256=6mj70vroWjmNmdvQ7jqqRSA9O1rFUNMUYDWPzqkizLk,19697
29
29
  htmlgraph/orchestrator_mode.py,sha256=F6LNZARqieQXUri3CRSq_lsqFbnVeGXJQPno1ZP47O4,9187
30
30
  htmlgraph/orchestrator_validator.py,sha256=gd_KbHsRsNEIF7EElwcxbMYqOMlyeuYIZwClASp-L-E,4699
@@ -104,7 +104,7 @@ htmlgraph/hooks/__init__.py,sha256=jL2HyCoFWQQ8l-4-EAlypDxPalNE3JBfDyELYWAg-g0,8
104
104
  htmlgraph/hooks/event_tracker.py,sha256=KQcIWbhNJser6Tip87oUAPQJgUAAKESKE5ARQasLtCM,23301
105
105
  htmlgraph/hooks/hooks-config.example.json,sha256=tXpk-U-FZzGOoNJK2uiDMbIHCYEHA794J-El0fBwkqg,197
106
106
  htmlgraph/hooks/installer.py,sha256=nOctCFDEV7BEh7ZzxNY-apu1KZG0SHPMq74UPIOChqY,11756
107
- htmlgraph/hooks/orchestrator.py,sha256=55xjmfg680e9PKcMkBmpbAmSXkZa33EQcZXlwPjDn50,17105
107
+ htmlgraph/hooks/orchestrator.py,sha256=rKRx5EYED-BFQrnAJ_roIjpP8GOs3RKDpulDouA29K0,19781
108
108
  htmlgraph/hooks/orchestrator_reflector.py,sha256=j3kZge33m42CEUVYiufiz7mf7Qm4DimnsRZKjbpZStA,5154
109
109
  htmlgraph/hooks/post-checkout.sh,sha256=Hsr5hqD54jisGbtqf7-Z-G_b6XNGcee_CZRYaKYzWzU,615
110
110
  htmlgraph/hooks/post-commit.sh,sha256=if65jNGZnEWsZPq_iYDNYunrZ1cmjPUEUbh6_4vfpOE,511
@@ -134,12 +134,12 @@ htmlgraph/services/claiming.py,sha256=HcrltEJKN72mxuD7fGuXWeh1U0vwhjMvhZcFc02Eiy
134
134
  htmlgraph/templates/AGENTS.md.template,sha256=f96h7V6ygwj-v-fanVI48eYMxR6t_se4bet1H4ZsDpI,7642
135
135
  htmlgraph/templates/CLAUDE.md.template,sha256=h1kG2hTX2XYig2KszsHBfzrwa_4Cfcq2Pj4SwqzeDlM,1984
136
136
  htmlgraph/templates/GEMINI.md.template,sha256=gAGzE53Avki87BM_otqy5HdcYCoLsHgqaKjVzNzPMX8,1622
137
- htmlgraph-0.23.0.data/data/htmlgraph/dashboard.html,sha256=rkZYjSnPbUuAm35QMpCNWemenYqQTdkkumCX2hhe8Dc,173537
138
- htmlgraph-0.23.0.data/data/htmlgraph/styles.css,sha256=oDUSC8jG-V-hKojOBO9J88hxAeY2wJrBYTq0uCwX_Y4,7135
139
- htmlgraph-0.23.0.data/data/htmlgraph/templates/AGENTS.md.template,sha256=f96h7V6ygwj-v-fanVI48eYMxR6t_se4bet1H4ZsDpI,7642
140
- htmlgraph-0.23.0.data/data/htmlgraph/templates/CLAUDE.md.template,sha256=h1kG2hTX2XYig2KszsHBfzrwa_4Cfcq2Pj4SwqzeDlM,1984
141
- htmlgraph-0.23.0.data/data/htmlgraph/templates/GEMINI.md.template,sha256=gAGzE53Avki87BM_otqy5HdcYCoLsHgqaKjVzNzPMX8,1622
142
- htmlgraph-0.23.0.dist-info/METADATA,sha256=3siZ1Sgj7MSqr_JR4DHf2j7qnrGB6QqGSYlFEu54hJM,7753
143
- htmlgraph-0.23.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
144
- htmlgraph-0.23.0.dist-info/entry_points.txt,sha256=EaUbjA_bbDwEO_XDLEGMeK8aQP-ZnHiUTkLshyKDyB8,98
145
- htmlgraph-0.23.0.dist-info/RECORD,,
137
+ htmlgraph-0.23.2.data/data/htmlgraph/dashboard.html,sha256=rkZYjSnPbUuAm35QMpCNWemenYqQTdkkumCX2hhe8Dc,173537
138
+ htmlgraph-0.23.2.data/data/htmlgraph/styles.css,sha256=oDUSC8jG-V-hKojOBO9J88hxAeY2wJrBYTq0uCwX_Y4,7135
139
+ htmlgraph-0.23.2.data/data/htmlgraph/templates/AGENTS.md.template,sha256=f96h7V6ygwj-v-fanVI48eYMxR6t_se4bet1H4ZsDpI,7642
140
+ htmlgraph-0.23.2.data/data/htmlgraph/templates/CLAUDE.md.template,sha256=h1kG2hTX2XYig2KszsHBfzrwa_4Cfcq2Pj4SwqzeDlM,1984
141
+ htmlgraph-0.23.2.data/data/htmlgraph/templates/GEMINI.md.template,sha256=gAGzE53Avki87BM_otqy5HdcYCoLsHgqaKjVzNzPMX8,1622
142
+ htmlgraph-0.23.2.dist-info/METADATA,sha256=sXhGvvPyc0ZtSB0FvkXu4A_gaKqs9x0uu0pS8Yb2kh8,7753
143
+ htmlgraph-0.23.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
144
+ htmlgraph-0.23.2.dist-info/entry_points.txt,sha256=EaUbjA_bbDwEO_XDLEGMeK8aQP-ZnHiUTkLshyKDyB8,98
145
+ htmlgraph-0.23.2.dist-info/RECORD,,