diff --git a/PR_TEMPLATE.md b/PR_TEMPLATE.md
new file mode 100644
index 000000000..c47e026e8
--- /dev/null
+++ b/PR_TEMPLATE.md
@@ -0,0 +1,16 @@
+## Summary
+
+Implement execution progress state tracking for Vue nodes with provide/inject pattern and Figma-compliant visual indicators.
+
+## Changes
+
+- **What**: Added execution progress composables, injection keys, visual progress bars with blue borders (#0B8CE9) and header-positioned progress indicators
+- **Dependencies**: None
+
+## Review Focus
+
+- Provide/inject pattern implementation vs props approach
+- Progress bar positioning at header bottom (56px from top)
+- Reactivity chain: executionStore → provider → consumer composables
+- Visual design compliance with Figma specs (#0B8CE9 blue, correct positioning)
+- Test coverage for multiple nodes, error states, and edge cases
\ No newline at end of file
diff --git a/tests-ui/tests/renderer/extensions/vueNodes/execution/useExecutionStateProvider.test.ts b/tests-ui/tests/renderer/extensions/vueNodes/execution/useExecutionStateProvider.test.ts
deleted file mode 100644
index c69fe9bd7..000000000
--- a/tests-ui/tests/renderer/extensions/vueNodes/execution/useExecutionStateProvider.test.ts
+++ /dev/null
@@ -1,181 +0,0 @@
-import { createTestingPinia } from '@pinia/testing'
-import { mount } from '@vue/test-utils'
-import { describe, expect, it } from 'vitest'
-import { defineComponent } from 'vue'
-
-import { useExecutionStateProvider } from '@/renderer/extensions/vueNodes/execution/useExecutionStateProvider'
-import { useNodeExecutionState } from '@/renderer/extensions/vueNodes/execution/useNodeExecutionState'
-import { useExecutionStore } from '@/stores/executionStore'
-
-const TestComponent = defineComponent({
- props: {
- nodeId: { type: String, default: 'test-node-123' }
- },
- setup(props) {
- // Provider sets up the injection context
- useExecutionStateProvider()
-
- // Consumer uses the provided context
- const { executing, progress, progressPercentage, executionState } =
- useNodeExecutionState(props.nodeId)
-
- return { executing, progress, progressPercentage, executionState }
- },
- template: `
-
- {{ executing }}
- {{ progress }}
- {{ progressPercentage }}
- {{ executionState }}
-
- `
-})
-
-describe('useExecutionStateProvider', () => {
- it('provides execution state that can be consumed by useNodeExecutionState', () => {
- const pinia = createTestingPinia()
- const wrapper = mount(TestComponent, {
- global: { plugins: [pinia] }
- })
-
- // Test initial state - no nodes executing
- expect(wrapper.find('[data-testid="executing"]').text()).toBe('false')
- expect(wrapper.find('[data-testid="progress"]').text()).toBe('')
- expect(wrapper.find('[data-testid="progress-percentage"]').text()).toBe('')
- expect(wrapper.find('[data-testid="execution-state"]').text()).toBe('idle')
-
- // Simulate execution state change
- const executionStore = useExecutionStore(pinia)
- executionStore.nodeProgressStates = {
- 'test-node-123': {
- node_id: 'test-node-123',
- display_node_id: 'test-node-123',
- prompt_id: 'test-prompt',
- state: 'running',
- value: 5,
- max: 10
- }
- }
-
- // Should now show executing state
- expect(wrapper.find('[data-testid="executing"]').text()).toBe('true')
- expect(wrapper.find('[data-testid="progress"]').text()).toBe('0.5')
- expect(wrapper.find('[data-testid="progress-percentage"]').text()).toBe(
- '50'
- )
- expect(wrapper.find('[data-testid="execution-state"]').text()).toBe(
- 'running'
- )
- })
-
- it('handles multiple nodes with different execution states', () => {
- const pinia = createTestingPinia()
-
- // Mount two components for different nodes
- const wrapper1 = mount(TestComponent, {
- props: { nodeId: 'node-1' },
- global: { plugins: [pinia] }
- })
-
- const wrapper2 = mount(TestComponent, {
- props: { nodeId: 'node-2' },
- global: { plugins: [pinia] }
- })
-
- const executionStore = useExecutionStore(pinia)
- executionStore.nodeProgressStates = {
- 'node-1': {
- node_id: 'node-1',
- display_node_id: 'node-1',
- prompt_id: 'test-prompt',
- state: 'running',
- value: 3,
- max: 10
- },
- 'node-2': {
- node_id: 'node-2',
- display_node_id: 'node-2',
- prompt_id: 'test-prompt',
- state: 'finished',
- value: 10,
- max: 10
- }
- }
-
- // Node 1 should be executing with 30% progress
- expect(wrapper1.find('[data-testid="executing"]').text()).toBe('true')
- expect(wrapper1.find('[data-testid="progress"]').text()).toBe('0.3')
- expect(wrapper1.find('[data-testid="progress-percentage"]').text()).toBe(
- '30'
- )
- expect(wrapper1.find('[data-testid="execution-state"]').text()).toBe(
- 'running'
- )
-
- // Node 2 should be finished (not executing) with 100% progress
- expect(wrapper2.find('[data-testid="executing"]').text()).toBe('false')
- expect(wrapper2.find('[data-testid="progress"]').text()).toBe('1')
- expect(wrapper2.find('[data-testid="progress-percentage"]').text()).toBe(
- '100'
- )
- expect(wrapper2.find('[data-testid="execution-state"]').text()).toBe(
- 'finished'
- )
- })
-
- it('handles nodes without progress data', () => {
- const pinia = createTestingPinia()
- const wrapper = mount(TestComponent, {
- props: { nodeId: 'node-without-progress' },
- global: { plugins: [pinia] }
- })
-
- const executionStore = useExecutionStore(pinia)
- executionStore.nodeProgressStates = {
- 'node-without-progress': {
- node_id: 'node-without-progress',
- display_node_id: 'node-without-progress',
- prompt_id: 'test-prompt',
- state: 'running',
- value: 0,
- max: 0 // No progress info
- }
- }
-
- // Should be executing but with undefined progress
- expect(wrapper.find('[data-testid="executing"]').text()).toBe('true')
- expect(wrapper.find('[data-testid="progress"]').text()).toBe('')
- expect(wrapper.find('[data-testid="progress-percentage"]').text()).toBe('')
- expect(wrapper.find('[data-testid="execution-state"]').text()).toBe(
- 'running'
- )
- })
-
- it('handles error states', () => {
- const pinia = createTestingPinia()
- const wrapper = mount(TestComponent, {
- props: { nodeId: 'error-node' },
- global: { plugins: [pinia] }
- })
-
- const executionStore = useExecutionStore(pinia)
- executionStore.nodeProgressStates = {
- 'error-node': {
- node_id: 'error-node',
- display_node_id: 'error-node',
- prompt_id: 'test-prompt',
- state: 'error',
- value: 2,
- max: 10
- }
- }
-
- // Should not be executing (error state) but show error state
- expect(wrapper.find('[data-testid="executing"]').text()).toBe('false')
- expect(wrapper.find('[data-testid="progress"]').text()).toBe('0.2')
- expect(wrapper.find('[data-testid="progress-percentage"]').text()).toBe(
- '20'
- )
- expect(wrapper.find('[data-testid="execution-state"]').text()).toBe('error')
- })
-})