Skip to content

Conversation

@jog1t
Copy link
Contributor

@jog1t jog1t commented Feb 6, 2026

Description

Please include a summary of the changes and the related issue. Please also include relevant motivation and context.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

@jog1t jog1t mentioned this pull request Feb 6, 2026
11 tasks
@jog1t jog1t marked this pull request as ready for review February 6, 2026 23:32
Copy link
Contributor Author

jog1t commented Feb 6, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more


How to use the Graphite Merge Queue

Add the label merge-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@jog1t jog1t mentioned this pull request Feb 6, 2026
11 tasks
@claude
Copy link

claude bot commented Feb 6, 2026

PR Review: feat(workflow): connect workflow visualizer with live data

Summary

This PR connects the workflow visualizer to live data from the actor inspector, replacing mock data with real workflow history. The implementation adds new query infrastructure, data transformation logic, and UI improvements.

✅ Positives

  1. Good separation of concerns: The transformation logic is cleanly separated into transform-workflow-history.ts
  2. Comprehensive data transformation: Handles all workflow entry types (step, loop, sleep, message, checkpoint, join, race, removed)
  3. Error handling: Includes try-catch blocks for CBOR decoding with fallback to undefined
  4. Type safety: Strong TypeScript typing throughout the transformation pipeline
  5. UI improvements: The visualizer now uses ActorObjectInspector for better data display and adds copy functionality

🐛 Potential Issues

1. Missing input/output handling in transformation

Location: transform-workflow-history.ts:177-226

The transformWorkflowHistory function returns a WorkflowHistory that can include input and output fields (per workflow-types.ts:128-129), but these are never populated from the transport data. The workflow visualizer previously had mock data with these fields.

// Current code returns:
return {
    workflowId: entries[0]?.id ?? "unknown",
    state,
    nameRegistry: [...nameRegistry],
    history,
    // Missing: input and output
};

Impact: Input/output visualization features may not work correctly.

2. Unsafe array access

Location: transform-workflow-history.ts:221

workflowId: entries[0]?.id ?? "unknown",

This assumes entries[0].id exists. If the entries array is empty, this returns "unknown" which is fine, but if entries exist without IDs, this could cause issues. Consider using the transport's workflow ID if available.

3. Inconsistent state derivation logic

Location: transform-workflow-history.ts:209-218

The state derivation has a subtle issue:

let state: WorkflowHistory["state"] = "pending";
if (allCompleted) {
    state = "completed";
} else if (hasFailed) {
    state = "failed";
} else if (hasRunning) {
    state = "running";
} else if (hasPending && history.some((h) => h.entry.status === "completed")) {
    state = "running";
}

The last condition checks if there are both pending and completed entries to mark as "running", but this seems arbitrary. This doesn't handle other workflow states defined in the types: "sleeping", "cancelled", or "rolling_back".

Recommendation: Check if the transport data includes an overall workflow state field that should be used directly instead of deriving it.

4. Type casting without validation

Location: transform-workflow-history.ts:135

originalType: kind.val.originalType as EntryKindType,

This casts to EntryKindType without validation. If the backend sends an invalid type, this could cause runtime issues.

Fix: Add validation:

const validTypes: EntryKindType[] = ["step", "loop", "sleep", "message", "rollback_checkpoint", "join", "race", "removed"];
const originalType = validTypes.includes(kind.val.originalType as EntryKindType) 
    ? kind.val.originalType as EntryKindType 
    : "removed";

5. Error swallowing in transformation

Location: actor-inspector-context.tsx:937-940

} catch (error) {
    console.warn("Failed to decode workflow history", error);
    return { history: null, isEnabled: true };
}

Errors are logged but swallowed. The UI will show "No workflow history available yet" which doesn't indicate an error occurred. Consider differentiating between "no data" and "error decoding data" states.

6. Query configuration concerns

Location: actor-inspector-context.tsx:314-330

Both workflow queries use staleTime: Infinity, meaning they never refetch automatically. However:

  • actorWorkflowHistoryQueryOptions makes sense with infinite stale time since it gets real-time updates via WebSocket
  • actorIsWorkflowEnabledQueryOptions has a hardcoded queryFn: () => false which seems wrong

The isWorkflowEnabled should be derived from actual data, not hardcoded to false. Looking at line 810-812, this gets set from the Init message, so the hardcoded false is just the initial value before the WebSocket connects. This is fine but could be clearer.

7. Potential memory leak in wheel event listener

Location: workflow-visualizer.tsx:1466-1472

The wheel event listener is added with { passive: false } to allow preventDefault. The cleanup function properly removes it, but there's a dependency issue with handleWheel that gets recreated on every render since useCallback has an empty dependency array while accessing transform and setTransform from closure.

Fix: Use functional setState to make the callback stable:

const handleWheel = useCallback((e: WheelEvent) => {
    e.preventDefault();
    
    if (e.ctrlKey || e.metaKey) {
        // ... zoom logic using setTransform(prev => ...)
    } else {
        setTransform((prev) => ({
            ...prev,
            x: prev.x - e.deltaX,
            y: prev.y - e.deltaY,
        }));
    }
}, []); // Now stable

8. Long import line

Location: transform-workflow-history.ts:6

import type { WorkflowHistory, EntryKind, EntryStatus, Location, SleepState, BranchStatus, BranchStatusType, EntryKindType } from "./workflow-types";

This 183-character import line is hard to read. Should be split across multiple lines per the project's style guidelines.

🔒 Security Considerations

  1. CBOR deserialization: The code uses cbor.decode() on data from the backend. Ensure the cbor-x library is up to date and validates input properly to prevent deserialization attacks.

  2. No input sanitization: Workflow data is displayed directly in the UI through ActorObjectInspector. Ensure this component properly sanitizes any HTML/script content.

⚡ Performance Considerations

  1. Transformation on every update: transformWorkflowHistory is called on every WebSocket message for workflow updates. For large workflows, this could be expensive. Consider:

    • Memoization if the same data is transformed multiple times
    • Incremental updates instead of full re-transformation
  2. Map lookups in transform: entryMetadata.get(entry.id) is called for every entry. This is O(n) operations with O(1) lookups, which is fine, but ensure the Map is properly indexed.

📝 Code Quality

Formatting

Most formatting changes appear to be from Prettier/auto-formatting. The code is generally well-formatted after the changes.

Missing Tests

This is a significant feature addition but no test files are included. Consider adding:

  • Unit tests for transformWorkflowHistory with various input scenarios
  • Tests for error handling (malformed CBOR, missing fields, etc.)
  • Integration tests for the WebSocket message handling

Documentation

The transformation function has a good JSDoc comment, but consider adding:

  • Comments explaining the state derivation logic
  • Documentation of the expected transport format
  • Examples of the data flow from WebSocket → Transform → UI

🎯 Recommendations

  1. High Priority:

    • Fix the workflow state derivation to handle all possible states
    • Validate the originalType cast
    • Fix the handleWheel callback dependencies
    • Investigate if input/output should be populated
  2. Medium Priority:

    • Add error differentiation (no data vs. decode error)
    • Add unit tests for the transformation logic
    • Split the long import line
  3. Low Priority:

    • Consider performance optimizations for large workflows
    • Add more inline documentation

✨ Overall Assessment

This is a solid implementation that successfully connects the workflow visualizer to live data. The code is well-structured with good separation of concerns. The main concerns are around edge cases, state handling completeness, and testing coverage. The issues identified are mostly minor and can be addressed in follow-up PRs if needed.

Recommendation: Approve with suggestions for follow-up improvements, especially around testing and the state derivation logic.

@graphite-app
Copy link
Contributor

graphite-app bot commented Feb 6, 2026

Graphite Automations

"Test" took an action on this PR • (02/06/26)

1 assignee was added to this PR based on Kacper Wojciechowski's automation.

@graphite-app
Copy link
Contributor

graphite-app bot commented Feb 10, 2026

Merge activity

  • Feb 10, 8:45 AM UTC: NathanFlurry added this pull request to the Graphite merge queue.
  • Feb 10, 8:46 AM UTC: CI is running for this pull request on a draft pull request (#4166) due to your merge queue CI optimization settings.
  • Feb 10, 8:48 AM UTC: The Graphite merge queue removed this pull request due to downstack failures on PR #4081.
  • Feb 10, 8:48 AM UTC: The Graphite merge queue removed this pull request due to downstack failures on PR #4081.
  • Feb 10, 7:35 PM UTC: NathanFlurry added this pull request to the Graphite merge queue.
  • Feb 10, 7:36 PM UTC: CI is running for this pull request on a draft pull request (#4167) due to your merge queue CI optimization settings.
  • Feb 10, 7:36 PM UTC: Merged by the Graphite merge queue via draft PR: #4167.

graphite-app bot pushed a commit that referenced this pull request Feb 10, 2026
# Description

Please include a summary of the changes and the related issue. Please also include relevant motivation and context.

## Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes.

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
@NathanFlurry NathanFlurry changed the base branch from 02-06-feat_sentry_use_correct_env to graphite-base/4153 February 10, 2026 19:20
@NathanFlurry NathanFlurry force-pushed the 02-07-feat_workflow_connect_workflow_visualizer_with_live_data branch from c8b012a to cef229d Compare February 10, 2026 19:25
@NathanFlurry NathanFlurry changed the base branch from graphite-base/4153 to 02-06-feat_sentry_use_correct_env February 10, 2026 19:25
graphite-app bot pushed a commit that referenced this pull request Feb 10, 2026
# Description

Please include a summary of the changes and the related issue. Please also include relevant motivation and context.

## Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes.

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
@graphite-app graphite-app bot closed this Feb 10, 2026
@graphite-app graphite-app bot deleted the 02-07-feat_workflow_connect_workflow_visualizer_with_live_data branch February 10, 2026 19:36
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.

1 participant