cursorflow 2.2.8__py3-none-any.whl → 2.3.0__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.
cursorflow/cli.py CHANGED
@@ -191,12 +191,22 @@ def test(base_url, path, actions, output, logs, config, verbose, headless, timeo
191
191
  console.print(f"[red]❌ Failed to load actions: {e}[/red]")
192
192
  return
193
193
  elif path:
194
- # Simple path navigation
195
- test_actions = [
196
- {"navigate": path},
197
- {"wait_for_selector": "body"},
198
- {"screenshot": "page_loaded"}
199
- ]
194
+ # Simple path navigation with optional wait conditions
195
+ test_actions = [{"navigate": path}]
196
+
197
+ # Add wait conditions if specified
198
+ if wait:
199
+ test_actions.append({"wait_for_timeout": int(wait * 1000)})
200
+ if wait_for:
201
+ test_actions.append({"wait_for_selector": wait_for})
202
+ if wait_for_network_idle:
203
+ test_actions.append({"wait_for_load_state": "networkidle"})
204
+
205
+ # Default wait if none specified
206
+ if not any([wait, wait_for, wait_for_network_idle]):
207
+ test_actions.append({"wait_for_selector": "body"})
208
+
209
+ test_actions.append({"screenshot": "page_loaded"})
200
210
  console.print(f"📋 Using simple path navigation to [cyan]{path}[/cyan]")
201
211
  else:
202
212
  # Default actions - just navigate to root and screenshot
@@ -766,14 +776,21 @@ def sessions(subcommand, name):
766
776
 
767
777
  @main.command()
768
778
  @click.option('--base-url', '-u', required=True)
779
+ @click.option('--path', '-p', default='/', help='Path to navigate to')
769
780
  @click.option('--selector', '-s', required=True)
770
- def inspect(base_url, selector):
781
+ @click.option('--verbose', '-v', is_flag=True, help='Show all computed styles')
782
+ def inspect(base_url, path, selector, verbose):
771
783
  """
772
- Quick element inspection without full test
784
+ Comprehensive element inspection with full data capture
785
+
786
+ Shows computed CSS, dimensions, selectors, and visual context for matching elements.
787
+ Perfect for CSS debugging and element analysis.
773
788
 
774
- Phase 3.5: Inspect selector and show matching elements
789
+ Examples:
790
+ cursorflow inspect --base-url http://localhost:3000 --selector "#messages-panel"
791
+ cursorflow inspect -u http://localhost:3000 -p /dashboard -s ".card"
775
792
  """
776
- console.print(f"🔍 Inspecting selector: [cyan]{selector}[/cyan]")
793
+ console.print(f"🔍 Inspecting selector: [cyan]{selector}[/cyan] at [blue]{path}[/blue]")
777
794
 
778
795
  try:
779
796
  from .core.cursorflow import CursorFlow
@@ -783,18 +800,255 @@ def inspect(base_url, selector):
783
800
  browser_config={'headless': True}
784
801
  )
785
802
 
786
- # Quick inspection
803
+ # Comprehensive inspection with full data capture
804
+ console.print("📸 Capturing comprehensive page data...")
787
805
  results = asyncio.run(flow.execute_and_collect([
788
- {"navigate": "/"},
789
- {"evaluate": f"""
790
- document.querySelectorAll('{selector}').length
791
- """}
806
+ {"navigate": path},
807
+ {"wait_for_selector": "body"},
808
+ {"screenshot": "inspection"}
792
809
  ]))
793
810
 
794
- console.print(f"✅ Found matches for: {selector}")
811
+ # Extract element data from comprehensive analysis
812
+ comprehensive_data = results.get('comprehensive_data', {})
813
+ dom_analysis = comprehensive_data.get('dom_analysis', {})
814
+ elements = dom_analysis.get('elements', [])
815
+
816
+ # Find matching elements
817
+ matching_elements = []
818
+ for element in elements:
819
+ # Check multiple selector strategies
820
+ if _element_matches_selector(element, selector):
821
+ matching_elements.append(element)
822
+
823
+ if not matching_elements:
824
+ console.print(f"[yellow]⚠️ No elements found matching: {selector}[/yellow]")
825
+ console.print(f"💡 Total elements captured: {len(elements)}")
826
+ return
827
+
828
+ console.print(f"\n✅ Found [bold]{len(matching_elements)}[/bold] matching element(s)\n")
829
+
830
+ # Display detailed information for each match
831
+ for idx, element in enumerate(matching_elements[:5], 1): # Show first 5
832
+ console.print(f"[bold cyan]═══ Element {idx}/{len(matching_elements)} ═══[/bold cyan]")
833
+
834
+ # Basic info
835
+ tag = element.get('tagName', 'unknown')
836
+ elem_id = element.get('id', '')
837
+ classes = element.get('className', '')
838
+
839
+ console.print(f"Tag: [yellow]{tag}[/yellow]")
840
+ if elem_id:
841
+ console.print(f"ID: [green]#{elem_id}[/green]")
842
+ if classes:
843
+ console.print(f"Classes: [blue].{classes}[/blue]")
844
+
845
+ # Selectors
846
+ unique_selector = element.get('uniqueSelector', 'N/A')
847
+ console.print(f"Unique: [cyan]{unique_selector}[/cyan]")
848
+
849
+ # Dimensions
850
+ bbox = element.get('boundingBox', {})
851
+ if bbox:
852
+ console.print(f"\n📐 Dimensions:")
853
+ console.print(f" Position: x={bbox.get('x', 0):.0f}, y={bbox.get('y', 0):.0f}")
854
+ console.print(f" Size: {bbox.get('width', 0):.0f}w × {bbox.get('height', 0):.0f}h")
855
+
856
+ # Computed styles (key CSS properties)
857
+ computed = element.get('computedStyles', {})
858
+ if computed:
859
+ console.print(f"\n🎨 Key CSS Properties:")
860
+
861
+ # Layout
862
+ display = computed.get('display', 'N/A')
863
+ position = computed.get('position', 'N/A')
864
+ console.print(f" display: {display}")
865
+ console.print(f" position: {position}")
866
+
867
+ # Flexbox
868
+ if 'flex' in computed:
869
+ console.print(f" flex: {computed.get('flex', 'N/A')}")
870
+ if 'flexBasis' in computed:
871
+ console.print(f" flex-basis: {computed.get('flexBasis', 'N/A')}")
872
+
873
+ # Dimensions
874
+ width = computed.get('width', 'N/A')
875
+ height = computed.get('height', 'N/A')
876
+ console.print(f" width: {width}")
877
+ console.print(f" height: {height}")
878
+
879
+ # Spacing
880
+ margin = computed.get('margin', 'N/A')
881
+ padding = computed.get('padding', 'N/A')
882
+ if margin != 'N/A':
883
+ console.print(f" margin: {margin}")
884
+ if padding != 'N/A':
885
+ console.print(f" padding: {padding}")
886
+
887
+ # Show all styles in verbose mode
888
+ if verbose:
889
+ console.print(f"\n📋 All Computed Styles:")
890
+ for prop, value in sorted(computed.items())[:30]: # Limit to 30
891
+ console.print(f" {prop}: {value}")
892
+
893
+ # Accessibility info
894
+ accessibility = element.get('accessibility', {})
895
+ if accessibility:
896
+ role = accessibility.get('role', 'N/A')
897
+ is_interactive = accessibility.get('isInteractive', False)
898
+ console.print(f"\n♿ Accessibility:")
899
+ console.print(f" Role: {role}")
900
+ console.print(f" Interactive: {'✅' if is_interactive else '❌'}")
901
+
902
+ # Visual context
903
+ visual = element.get('visual_context', {})
904
+ if visual:
905
+ console.print(f"\n👁️ Visual Context:")
906
+ if visual.get('is_visible'):
907
+ console.print(f" Visibility: ✅ Visible")
908
+ else:
909
+ console.print(f" Visibility: ❌ Hidden")
910
+ if visual.get('z_index'):
911
+ console.print(f" Z-index: {visual.get('z_index')}")
912
+
913
+ console.print("") # Spacing between elements
914
+
915
+ if len(matching_elements) > 5:
916
+ console.print(f"[dim]... and {len(matching_elements) - 5} more elements[/dim]")
917
+
918
+ # Show screenshot location
919
+ screenshots = results.get('artifacts', {}).get('screenshots', [])
920
+ if screenshots:
921
+ screenshot_path = screenshots[0]
922
+ console.print(f"\n📸 Screenshot saved: [cyan]{screenshot_path}[/cyan]")
795
923
 
796
924
  except Exception as e:
797
925
  console.print(f"[red]❌ Inspection failed: {e}[/red]")
926
+ import traceback
927
+ console.print(traceback.format_exc())
928
+
929
+ def _element_matches_selector(element: Dict, selector: str) -> bool:
930
+ """Check if element matches the given selector"""
931
+
932
+ # ID selector
933
+ if selector.startswith('#'):
934
+ target_id = selector[1:]
935
+ return element.get('id') == target_id
936
+
937
+ # Class selector
938
+ if selector.startswith('.'):
939
+ target_class = selector[1:]
940
+ classes = element.get('className', '')
941
+ return target_class in classes.split()
942
+
943
+ # Tag selector
944
+ tag = element.get('tagName', '').lower()
945
+ selector_lower = selector.lower()
946
+ if tag == selector_lower:
947
+ return True
948
+
949
+ # Check unique selector contains the target
950
+ unique_selector = element.get('uniqueSelector', '').lower()
951
+ if selector_lower in unique_selector:
952
+ return True
953
+
954
+ return False
955
+
956
+ @main.command()
957
+ @click.option('--base-url', '-u', required=True)
958
+ @click.option('--path', '-p', default='/', help='Path to navigate to')
959
+ @click.option('--selector', '-s', required=True, multiple=True, help='Selector(s) to measure (can specify multiple)')
960
+ @click.option('--verbose', '-v', is_flag=True, help='Show all computed CSS properties')
961
+ def measure(base_url, path, selector, verbose):
962
+ """
963
+ Surgical element dimension measurement
964
+
965
+ Quickly measure width, height, and position of elements.
966
+ Use --verbose to see all computed CSS properties.
967
+
968
+ Examples:
969
+ cursorflow measure --base-url http://localhost:3000 --selector "#messages-panel"
970
+ cursorflow measure -u http://localhost:3000 -s "#panel1" -s "#panel2" --verbose
971
+ """
972
+ console.print(f"📏 Measuring element dimensions at [blue]{path}[/blue]\n")
973
+
974
+ try:
975
+ from .core.cursorflow import CursorFlow
976
+ flow = CursorFlow(
977
+ base_url=base_url,
978
+ log_config={'source': 'local', 'paths': []},
979
+ browser_config={'headless': True}
980
+ )
981
+
982
+ # Use comprehensive data capture but display only dimensions
983
+ selectors_list = list(selector)
984
+
985
+ # Execute with screenshot to get comprehensive data
986
+ results = asyncio.run(flow.execute_and_collect([
987
+ {"navigate": path},
988
+ {"wait_for_selector": "body"},
989
+ {"screenshot": "measurement"}
990
+ ]))
991
+
992
+ # Extract element data from comprehensive analysis
993
+ comprehensive_data = results.get('comprehensive_data', {})
994
+ dom_analysis = comprehensive_data.get('dom_analysis', {})
995
+ elements = dom_analysis.get('elements', [])
996
+
997
+ # For each selector, find matching elements and display dimensions
998
+ for sel in selectors_list:
999
+ matching_elements = []
1000
+ for element in elements:
1001
+ if _element_matches_selector(element, sel):
1002
+ matching_elements.append(element)
1003
+
1004
+ if not matching_elements:
1005
+ console.print(f"[yellow]⚠️ {sel}: No elements found[/yellow]\n")
1006
+ continue
1007
+
1008
+ for idx, element in enumerate(matching_elements):
1009
+ if len(matching_elements) > 1:
1010
+ console.print(f"[bold cyan]{sel}[/bold cyan] [dim](element {idx + 1}/{len(matching_elements)})[/dim]")
1011
+ else:
1012
+ console.print(f"[bold cyan]{sel}[/bold cyan]")
1013
+
1014
+ # Dimensions - check both camelCase and snake_case
1015
+ bbox = element.get('boundingBox') or element.get('visual_context', {}).get('bounding_box')
1016
+ if bbox:
1017
+ width = bbox.get('width', 0)
1018
+ height = bbox.get('height', 0)
1019
+ x = bbox.get('x', 0)
1020
+ y = bbox.get('y', 0)
1021
+ console.print(f" 📐 Rendered: {width:.0f}w × {height:.0f}h")
1022
+ console.print(f" 📍 Position: x={x:.0f}, y={y:.0f}")
1023
+
1024
+ # Computed styles
1025
+ computed = element.get('computedStyles', {})
1026
+ if computed:
1027
+ if verbose:
1028
+ # Show ALL computed CSS properties
1029
+ console.print(f" 🎨 Computed CSS (all properties):")
1030
+ for prop, value in sorted(computed.items()):
1031
+ console.print(f" {prop}: {value}")
1032
+ else:
1033
+ # Show key CSS properties only
1034
+ console.print(f" 🎨 Display: {computed.get('display', 'N/A')}")
1035
+ console.print(f" 📦 CSS Width: {computed.get('width', 'N/A')}")
1036
+
1037
+ if computed.get('flex'):
1038
+ console.print(f" 🔧 Flex: {computed.get('flex')}")
1039
+ if computed.get('flexBasis') and computed.get('flexBasis') != 'auto':
1040
+ console.print(f" 📏 Flex Base: {computed.get('flexBasis')}")
1041
+
1042
+ console.print(f" 💡 Use --verbose to see all {len(computed)} CSS properties")
1043
+
1044
+ console.print("")
1045
+
1046
+ console.print("✅ Measurement complete")
1047
+
1048
+ except Exception as e:
1049
+ console.print(f"[red]❌ Measurement failed: {e}[/red]")
1050
+ import traceback
1051
+ console.print(traceback.format_exc())
798
1052
 
799
1053
  @main.command()
800
1054
  @click.option('--base-url', '-u', required=True)
@@ -1380,7 +1380,7 @@ class BrowserController:
1380
1380
  animationData.transition_details.push({
1381
1381
  element_selector: element.tagName.toLowerCase() +
1382
1382
  (element.id ? '#' + element.id : '') +
1383
- (element.className ? '.' + element.className.split(' ').join('.') : ''),
1383
+ (element.className && typeof element.className === 'string' ? '.' + element.className.split(' ').join('.') : ''),
1384
1384
  transition_property: transitionProperty,
1385
1385
  duration: computedStyle.transitionDuration,
1386
1386
  delay: computedStyle.transitionDelay,
@@ -255,8 +255,9 @@ cursorflow test --base-url http://localhost:3000 --actions '[
255
255
  ### **All CLI Commands:**
256
256
  ```bash
257
257
  cursorflow test # Test UI with comprehensive data capture
258
+ cursorflow inspect # Comprehensive element analysis (CSS, dimensions, accessibility)
259
+ cursorflow measure # Surgical dimension checking (quick CSS verification)
258
260
  cursorflow rerun # Re-run last test
259
- cursorflow inspect # Quick element inspection
260
261
  cursorflow count # Count matching elements
261
262
  cursorflow timeline # View event timeline
262
263
  cursorflow sessions # Manage saved sessions
@@ -376,6 +377,54 @@ cursorflow test \
376
377
  ]'
377
378
  ```
378
379
 
380
+ ### CSS Debugging & Element Analysis
381
+ ```bash
382
+ # Comprehensive element inspection (full CSS analysis)
383
+ cursorflow inspect --base-url http://localhost:3000 --selector "#messages-panel"
384
+
385
+ # Output includes:
386
+ # - Computed CSS (all properties: display, flex, width, etc.)
387
+ # - Rendered dimensions (actual width × height on screen)
388
+ # - Position (x, y coordinates)
389
+ # - Unique selector for targeting
390
+ # - Accessibility info (role, interactive state)
391
+ # - Visual context (visibility, z-index)
392
+ # - Screenshot saved to artifacts
393
+
394
+ # Show ALL computed CSS properties (verbose mode)
395
+ cursorflow inspect -u http://localhost:3000 -p /dashboard -s ".card" --verbose
396
+
397
+ # Quick dimension check (surgical precision)
398
+ cursorflow measure --base-url http://localhost:3000 --selector "#panel"
399
+
400
+ # Measure multiple elements at once
401
+ cursorflow measure -u http://localhost:3000 -s "#panel1" -s "#panel2"
402
+
403
+ # Verify CSS changes with all properties
404
+ cursorflow measure -u http://localhost:3000 -s ".button" --verbose
405
+ ```
406
+
407
+ **When to use inspect vs measure:**
408
+ - **`inspect`**: Deep CSS debugging, complex layout issues, need accessibility info
409
+ - **`measure`**: Quick dimension verification, CSS change validation, multiple elements
410
+
411
+ **Workflow example:**
412
+ ```bash
413
+ # 1. Quick check dimensions
414
+ cursorflow measure -u http://localhost:3000 -s "#panel"
415
+ # Output: 260w × 900h
416
+
417
+ # 2. Dimensions seem wrong, get full analysis
418
+ cursorflow inspect -u http://localhost:3000 -s "#panel" --verbose
419
+ # Output: Full CSS, flex: 1 1 0%, flex-basis: 260px, etc.
420
+
421
+ # 3. Make CSS changes based on insights
422
+
423
+ # 4. Verify fix
424
+ cursorflow measure -u http://localhost:3000 -s "#panel"
425
+ # Output: 532w × 900h ✅
426
+ ```
427
+
379
428
  ## Analyzing Results
380
429
 
381
430
  ### **Hot Reload CSS Iteration Results**
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cursorflow
3
- Version: 2.2.8
3
+ Version: 2.3.0
4
4
  Summary: 🔥 Complete page intelligence for AI-driven development with Hot Reload Intelligence - captures DOM, network, console, performance, HMR events, and comprehensive page analysis
5
5
  Author-email: GeekWarrior Development <rbush@cooltheory.com>
6
6
  License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/haley-marketing-group/cursorflow
8
- Project-URL: Documentation, https://cursorflow.readthedocs.io
8
+ Project-URL: Documentation, https://cursorflow.dev
9
9
  Project-URL: Repository, https://github.com/haley-marketing-group/cursorflow
10
10
  Keywords: ui-testing,automation,cursor,ai,web-testing,css-iteration,hot-reload,hmr,element-intelligence,page-analysis,error-context
11
11
  Classifier: Development Status :: 5 - Production/Stable
@@ -386,6 +386,24 @@ cursorflow iterate-mockup https://mockup.com/design \
386
386
  ]'
387
387
  ```
388
388
 
389
+ ### **Element Analysis & CSS Debugging**
390
+ ```bash
391
+ # Comprehensive element inspection with full CSS analysis
392
+ cursorflow inspect --base-url http://localhost:3000 --selector "#messages-panel"
393
+
394
+ # Show all computed CSS properties
395
+ cursorflow inspect -u http://localhost:3000 -s ".card" --verbose
396
+
397
+ # Quick dimension check (surgical precision)
398
+ cursorflow measure --base-url http://localhost:3000 --selector "#panel"
399
+
400
+ # Measure multiple elements at once
401
+ cursorflow measure -u http://localhost:3000 -s "#panel1" -s "#panel2"
402
+
403
+ # Verify CSS changes with all properties
404
+ cursorflow measure -u http://localhost:3000 -s ".button" --verbose
405
+ ```
406
+
389
407
  ### **AI Integration**
390
408
  ```bash
391
409
  # Install Cursor AI rules
@@ -397,14 +415,6 @@ cursorflow update
397
415
 
398
416
  ## 🧠 Why This Matters
399
417
 
400
- ### **For Job Board v4 Testing:**
401
- ✅ **Real API response times** from `/ajax_rq.smpl?fn=gjapi_typeahead`
402
- ✅ **Actual network failures** when they occur
403
- ✅ **Real browser console errors** from production code
404
- ✅ **Genuine performance metrics** under real load
405
-
406
- ❌ **With mocking:** You'd never know the typeahead is slow in production!
407
-
408
418
  ### **For Any Web Application:**
409
419
  - **Trust your test results** - they reflect actual behavior
410
420
  - **Find real performance bottlenecks** - no artificial speed boosts
@@ -427,9 +437,8 @@ cursorflow update
427
437
 
428
438
  ## 📖 Documentation
429
439
 
430
- - **[Complete User Manual](docs/USER_MANUAL.md)** - Full feature guide
431
- - **[Examples](examples/)** - Practical usage examples
432
- - **[API Reference](docs/api/)** - Complete Python API documentation
440
+ - **[Usage Guide](docs/user/USAGE_GUIDE.md)** - Complete usage documentation (included in pip install)
441
+ - **[Examples](examples/)** - Practical usage examples (included in pip install)
433
442
 
434
443
  ## 🎪 The CursorFlow Advantage
435
444
 
@@ -1,14 +1,14 @@
1
1
  cursorflow/__init__.py,sha256=5G0Zm1HeS4oGx9S9E5GFRon5gduljQMlJhs1XEBUuE4,2763
2
2
  cursorflow/auto_init.py,sha256=dXQaXXiXe4wkUP-jd8fcJ5fYVt7ASdTb47b7SzXymOM,6122
3
3
  cursorflow/auto_updater.py,sha256=oQ12TIMZ6Cm3HF-x9iRWFtvOLkRh-JWPqitS69-4roE,7851
4
- cursorflow/cli.py,sha256=cRxhu48AwQfpO48qlU2B29Vi_jfUIXFe5bvi8LS8poA,50423
4
+ cursorflow/cli.py,sha256=l8TTcX6ve5Zx4sAOkdX5P1OChrZkDjvkix4Fbgdf-VE,62069
5
5
  cursorflow/install_cursorflow_rules.py,sha256=DsZ0680y9JMuTKFXjdgYtOKIEAjBMsdwL8LmA9WEb5A,11864
6
6
  cursorflow/post_install.py,sha256=WieBiKWG0qBAQpF8iMVWUyb9Fr2Xky9qECTMPrlAbpE,2678
7
7
  cursorflow/updater.py,sha256=SroSQHQi5cYyzcOK_bf-WzmQmE7yeOs8qo3r__j-Z6E,19583
8
8
  cursorflow/core/action_validator.py,sha256=SCk3w_62D1y0cCRDOajK8L44-abSj_KpnUBgR_yNVW4,6846
9
9
  cursorflow/core/agent.py,sha256=f3lecgEzDRDdGTVccAtorpLGfNJJ49bbsQAmgr0vNGg,10136
10
10
  cursorflow/core/auth_handler.py,sha256=oRafO6ZdxoHryBIvHsrNV8TECed4GXpJsdEiH0KdPPk,17149
11
- cursorflow/core/browser_controller.py,sha256=mfJ5a6-996TC6Z2CHNxxQUQPPqPjPWAvL1njTONwqsA,147423
11
+ cursorflow/core/browser_controller.py,sha256=Efx48lxIz6MYZI8bHhIDpP_hqKDxeHSLvK8vgiPaXBM,147464
12
12
  cursorflow/core/browser_engine.py,sha256=7N9hPOyDrEhLWYgZW2981N9gKlHF6Lbp7D7h0zBzuz8,14851
13
13
  cursorflow/core/config_validator.py,sha256=HRtONSOmM0Xxt3-ok3xwnBADRiNnI0nNOMaS2OqOkDk,7286
14
14
  cursorflow/core/css_iterator.py,sha256=whLCIwbHZEWaH1HCbmqhNX5zrh_fL-r3hsxKjYsukcE,16478
@@ -29,10 +29,10 @@ cursorflow/log_sources/local_file.py,sha256=GVnhsaifIdc41twXwbxRM9-fBeRDsknDpk5I
29
29
  cursorflow/log_sources/ssh_remote.py,sha256=_Kwh0bhRpKgq-0c98oaX2hN6h9cT-wCHlqY5NiWVCoY,8388
30
30
  cursorflow/rules/__init__.py,sha256=gPcA-IkhXj03sl7cvZV0wwo7CtEkcyuKs4y0F5oQbqE,458
31
31
  cursorflow/rules/cursorflow-installation.mdc,sha256=D55pzzDPAVVbE3gAtKPUGoT-2fvB-FI2l6yrTdzUIEo,10208
32
- cursorflow/rules/cursorflow-usage.mdc,sha256=JVj-Xgura1rIfHaR5W_GHy6mBVlYCgE922RtuRVEJvg,21383
33
- cursorflow-2.2.8.dist-info/licenses/LICENSE,sha256=e4QbjAsj3bW-xgQOvQelr8sGLYDoqc48k6cKgCr_pBU,1080
34
- cursorflow-2.2.8.dist-info/METADATA,sha256=Pt_t2eFlVaGhHPNP5FiBHF6PlnvqSW25ZwEX6oDd7e8,14538
35
- cursorflow-2.2.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
- cursorflow-2.2.8.dist-info/entry_points.txt,sha256=-Ed_n4Uff7wClEtWS-Py6xmQabecB9f0QAOjX0w7ljA,51
37
- cursorflow-2.2.8.dist-info/top_level.txt,sha256=t1UZwRyZP4u-ng2CEcNHmk_ZT4ibQxoihB2IjTF7ovc,11
38
- cursorflow-2.2.8.dist-info/RECORD,,
32
+ cursorflow/rules/cursorflow-usage.mdc,sha256=8TUeQ1hq2fTlgPqUBYOVBXrdEN0BR0Xp0d_1L-eUsME,23150
33
+ cursorflow-2.3.0.dist-info/licenses/LICENSE,sha256=e4QbjAsj3bW-xgQOvQelr8sGLYDoqc48k6cKgCr_pBU,1080
34
+ cursorflow-2.3.0.dist-info/METADATA,sha256=hC0JZcjfBUi9MolXNXB80aX_YU23nH0Zgnr350bYKlI,14793
35
+ cursorflow-2.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
+ cursorflow-2.3.0.dist-info/entry_points.txt,sha256=-Ed_n4Uff7wClEtWS-Py6xmQabecB9f0QAOjX0w7ljA,51
37
+ cursorflow-2.3.0.dist-info/top_level.txt,sha256=t1UZwRyZP4u-ng2CEcNHmk_ZT4ibQxoihB2IjTF7ovc,11
38
+ cursorflow-2.3.0.dist-info/RECORD,,