Skip to content

Remove drift detection system and port dashboard to Phoenix LiveView#24

Merged
shakestzd merged 16 commits intomainfrom
claude/explore-livebook-htmlgraph-SKUV1
Mar 15, 2026
Merged

Remove drift detection system and port dashboard to Phoenix LiveView#24
shakestzd merged 16 commits intomainfrom
claude/explore-livebook-htmlgraph-SKUV1

Conversation

@shakestzd
Copy link
Owner

Summary

This PR removes the deprecated drift detection and auto-classification system from HtmlGraph hooks, and introduces an exploratory Phoenix LiveView dashboard to replace the static HTML activity feed with real-time WebSocket-driven updates.

Key Changes

Drift System Removal

  • Removed modules: src/python/htmlgraph/hooks/drift_handler.py and src/python/htmlgraph/hooks/drift.py — centralized drift detection logic no longer needed
  • Removed state manager: DriftQueueManager class from state_manager.py — drift queue persistence eliminated
  • Removed tracking: Deleted drift_score field from activity tracking across:
    • session_manager.py — no longer calculates per-activity drift scores
    • sessions/activity.py — removed drift calculation from activity tracking
    • sessions/features.py — removed drift_score from attribution results
    • models.py and models/context.py — removed drift_score from ActivityEntry schema
  • Removed tests: Deleted test_drift_queue_cleanup.py and drift-related test cases from test_state_manager.py and test_event_tracker.py
  • Updated documentation: Removed drift references from code hygiene rules and agent instructions

Phoenix LiveView Dashboard (Exploratory)

  • New package: packages/phoenix-dashboard/ — complete Phoenix/Elixir application
  • Core modules:
    • activity.ex — queries HtmlGraph SQLite database and builds multi-level nested activity tree (Session → UserQuery → Tool Events → Subagent Events)
    • event_poller.ex — GenServer that polls SQLite every 1 second and broadcasts new events via Phoenix PubSub
    • repo.ex — read-only SQLite3 adapter using exqlite
    • activity_feed_live.ex — LiveView component with expand/collapse state, real-time updates, and agent filtering
  • Styling: styles.ex — inline CSS module with GitHub-inspired dark theme (no build tools required)
  • Configuration: Full Phoenix setup with dev/prod configs, router, endpoint, and error handling
  • Assets: Minimal JavaScript for LiveSocket WebSocket connection

Code Standards Enforcement

  • New tooling: scripts/check-module-size.py — enforces module size limits (warn >300 lines, fail >500 for new modules, critical >1000)
  • New test suite: tests/test_subnode.py — tests for sub-node HTML element querying and mutation layer
  • New module: src/python/htmlgraph/subnode.py — CSS selector-based querying and updating of HTML elements within track/feature files
  • Documentation: docs/tracks/MODULE_REFACTORING_TRACK.md — comprehensive refactoring plan addressing 15 oversized modules and code duplication
  • Pre-commit hook: Added module-size check to .pre-commit-config.yaml
  • Agent instructions: Updated all agent profiles (Sonnet, Haiku, Opus, Debugger, Researcher) with module size standards

Supporting Changes

  • Session model: Added focus_ratio field to Session class to measure activity attribution coverage (replaces per-event drift_score)
  • Test updates: Modified test_drift_parent_activity.py to test session-level focus_ratio instead of per-event drift scores
  • Database: Updated .htmlgraph/htmlgraph.db schema (binary change)
  • Track/Feature files: Added new track and feature HTML files documenting refactoring initiatives and dashboard exploration

Implementation Notes

  • Drift removal is non-breaking: The drift_score field is simply not populated; existing code that checks for None continues to work
  • Dashboard is exploratory: The Phoenix LiveView implementation is a proof-of-concept; the static HTML dashboard remains the primary interface
  • No build tools: Dashboard CSS is inlined; JavaScript is minimal and served as static assets
  • Database-driven: Dashboard reads directly from existing .htmlgraph/htmlgraph.db SQLite file with no schema changes required
  • Module size enforcement: Grandfathered

https://claude.ai/code/session_01R5FpDt5NCEkgVdXJSfddQ4

claude and others added 12 commits March 14, 2026 08:11
Scaffolds a Phoenix LiveView app under packages/phoenix-dashboard/ that
reads the existing .htmlgraph/htmlgraph.db SQLite database and renders
a real-time activity feed with:

- Multi-level nesting: Session > UserQuery > Tool Events > Subagent Events (4 levels)
- Color-coded badges for tool types, models, subagents, errors, features
- Descending chronological order at every level
- Live updates via GenServer polling (1s) + PubSub broadcast to LiveView
- Expand/collapse per conversation turn and per nested event
- Tree connectors for visual hierarchy
- New event flash animation

Key modules:
- Activity: Hierarchical query builder against agent_events table
- EventPoller: GenServer that polls SQLite and broadcasts via PubSub
- Repo: Lightweight read-only SQLite access via exqlite
- ActivityFeedLive: LiveView with recursive event_row component

https://claude.ai/code/session_01R5FpDt5NCEkgVdXJSfddQ4
Force-add Elixir source files that were excluded by root .gitignore lib/ rule.

Includes all application modules:
- Activity: hierarchical event query builder
- Repo: read-only SQLite access via exqlite
- EventPoller: GenServer polling + PubSub broadcast
- ActivityFeedLive: LiveView with recursive nested events
- Styles: inline CSS (dark theme, badges, tree connectors)
- Layouts, Router, Endpoint, CoreComponents

https://claude.ai/code/session_01R5FpDt5NCEkgVdXJSfddQ4
- Update Phoenix 1.8 + LiveView 1.1 + exqlite API compatibility
- Fix CSS loading (HEEx doesn't interpolate inside <style> tags)
- Move inline CSS to static asset pipeline (Tailwind + esbuild)
- Add multi-level event hierarchy (Session → UserQuery → Tools → Task)
- Remove UserQuery badge (implicit in hierarchy structure)
- Sanitize summaries: strip XML tags, raw JSON metadata dumps
- Filter empty PreToolUse events (dedup with PostToolUse)
- Add color-coded tool chips (Bash=green, Read=blue, Edit=yellow, etc.)
- Add subagent re-parenting and orphan event adoption
- Configure esbuild/tailwind asset watchers for dev mode

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add phx-key attributes on session groups, turns, and events
  for stable DOM identity (eliminates flicker)
- Debounce event reload to 500ms (prevents rapid re-renders)
- Remove new_event_ids highlight mechanism (caused double re-render)
- Session cards now show last prompt text instead of raw UUIDs
- Derive session status from data: active/idle/completed
  (idle = no events in 30 min)
- Remove NULL AS model — use real model column from sessions table
- Suppress "system" agent label when not meaningful
- Add badge-status-idle CSS (amber) and session-subtitle styling

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Filter noise events (Stop, SessionResume, InstructionsLoaded) in
  has_meaningful_content instead of letting them leak through
- Move compute_stats to run on displayed_children (after filter)
  so tool count badge matches what's actually shown
- Orchestrator Bash/MCP/Playwright calls now visible alongside
  Task delegation events in expanded turns

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All child queries and merge function now use DESC ordering,
consistent with the UserQuery turn ordering. Interleaved Task
delegations and orchestrator tool calls are now chronologically
clear with most recent events at the top.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Only filter known noise events (Stop, SessionResume, InstructionsLoaded,
SessionStart, SessionEnd). Orchestrator tool calls with JSON metadata
summaries that sanitize to empty are now kept — they display as tool
chip + timestamp, which correctly represents the work performed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove (htmlgraph:haiku-coder): prefix from Task event summaries
since the agent type is already displayed as a badge.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add step_id field to Step model (format: step-{feature_id}-{index})
- Emit data-step-id in HTML, parse it back in parser.py
- Auto-generate step_ids on feature creation and builder save
- Add step_id column to agent_events table with migration + index
- Add resolve_active_step() to event_tracker — finds first incomplete step
- Pass step_id through record_event_to_sqlite() for every event
- 34 new tests covering model, parser, DB, resolution, backward compat
- All 2213 existing tests pass (0 failures)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add RelationshipType enum (blocks, relates_to, spawned_from, etc.)
- Add Node convenience methods: relates_to(), spawned_from(), caused_by(), implements()
- Add Builder methods: .relates_to(), .spawned_from(), .caused_by(), .implements()
- Add Collection edge methods: add_edge() with dual-write (HTML + SQLite),
  related_to(), blocked_by(), blocks(), edges_of() queries
- Add DB methods: insert_graph_edge(), get_graph_edges(), delete_graph_edge()
- Add edge_sync module: sync_html_edges_to_sqlite(), sync_sqlite_edge_to_html()
- 42 new tests, all 2255 tests pass (0 failures)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 3a — Critical path analysis:
- New analytics/critical_path.py with find_critical_path(),
  find_bottlenecks(), get_dependency_graph()
- Topological sort on graph_edges, cycle detection, DAG visualization

Phase 3b — Step dependencies:
- Step.depends_on field for intra-feature step ordering
- Node.get_ready_steps() returns steps with met dependencies
- next_step property respects dependency ordering
- Parser extracts data-depends-on from HTML

Phase 3c — Auto-divergence detection:
- FeatureWorkflow.auto_create_divergent_feature() with spawned_from edge
- CIGS guidance now shows active step context
- Divergence scoring on Task events (keyword overlap heuristic)

34 new tests (17 auto-divergence + 17 critical path), all passing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aadf939b3e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +15 to +17
if Path.type(path) == :relative do
Path.join(Application.app_dir(:htmlgraph_dashboard, ""), path)
|> Path.expand()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Resolve DB path relative to project, not app build directory

When HTMLGRAPH_DB_PATH is unset, db_path/0 joins "../../.htmlgraph/htmlgraph.db" against Application.app_dir/2, which points to _build/.../lib/htmlgraph_dashboard in Mix projects. That resolves to _build/dev/.htmlgraph/htmlgraph.db instead of the repository’s .htmlgraph/htmlgraph.db, so all queries fail to open the DB and the live feed appears empty by default.

Useful? React with 👍 / 👎.

Comment on lines +211 to +214
flat
|> Enum.map(fn c -> (c["execution_duration_seconds"] || 0) end)
|> Enum.sum()
|> Float.round(2),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Guard duration rounding when a turn has no child events

compute_stats/1 pipes Enum.sum() into Float.round/2; for a UserQuery with no child events, flat is empty and Enum.sum([]) returns integer 0, which raises FunctionClauseError in Float.round/2. This crashes feed construction for sessions that include turns without tool activity.

Useful? React with 👍 / 👎.

…ok-htmlgraph-SKUV1

# Conflicts:
#	.claude-plugin/marketplace.json
#	packages/claude-plugin/.claude-plugin/marketplace.json
#	packages/claude-plugin/.claude-plugin/plugin.json
#	packages/gemini-extension/gemini-extension.json
#	pyproject.toml
#	src/python/htmlgraph/__init__.py
#	src/python/htmlgraph/builders/base.py
#	src/python/htmlgraph/hooks/prompt_analyzer.py
@shakestzd shakestzd force-pushed the claude/explore-livebook-htmlgraph-SKUV1 branch from aadf939 to 3715aa5 Compare March 15, 2026 11:36
shakestzd and others added 3 commits March 15, 2026 07:46
…gent updates

Recover files from the 11 commits (2e7cca1..aadf939) that were
overwritten during force-push:
- subnode.py: CSS selector query/update layer for HTML elements
- test_subnode.py: test suite for sub-node operations
- check-module-size.py: module size enforcement script
- MODULE_REFACTORING_TRACK.md: refactoring plan for 15 oversized modules
- Agent definitions: updated with module size standards
- code-hygiene.md: module size & complexity standards
- user-prompt-submit.py: updated hook script
- system-prompt-default.md: updated system prompt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Deploy v0.33.79 (Phase 3: auto-divergence, step deps, critical path)
- Create track trk-92f36021: Phoenix Dashboard SDK Integration
- Plan: replace raw SQLite with Python SDK via Elixir Port bridge

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@shakestzd shakestzd merged commit 5ae86f7 into main Mar 15, 2026
3 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants