flowproof 0.23.2__tar.gz → 0.23.4__tar.gz

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.
Files changed (164) hide show
  1. {flowproof-0.23.2 → flowproof-0.23.4}/Cargo.lock +7 -7
  2. {flowproof-0.23.2 → flowproof-0.23.4}/Cargo.toml +1 -1
  3. {flowproof-0.23.2 → flowproof-0.23.4}/PKG-INFO +1 -1
  4. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/web.rs +36 -5
  5. flowproof-0.23.4/crates/flowproof-adapters/tests/grid_scene_e2e.rs +54 -0
  6. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/tests/static_area_e2e.rs +21 -0
  7. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/author.rs +60 -8
  8. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/llm.rs +17 -13
  9. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/tests/model_client_http.rs +30 -0
  10. {flowproof-0.23.2 → flowproof-0.23.4}/flowproof/__init__.py +1 -1
  11. {flowproof-0.23.2 → flowproof-0.23.4}/pyproject.toml +1 -1
  12. {flowproof-0.23.2 → flowproof-0.23.4}/README.md +0 -0
  13. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/Cargo.toml +0 -0
  14. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/agent_proxy.rs +0 -0
  15. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/agent_runner.rs +0 -0
  16. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/egress.rs +0 -0
  17. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/egress_linux.rs +0 -0
  18. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/egress_windows/audit.rs +0 -0
  19. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/egress_windows/capture.rs +0 -0
  20. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/egress_windows/env_block.rs +0 -0
  21. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/egress_windows/filters.rs +0 -0
  22. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/egress_windows/identity.rs +0 -0
  23. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/egress_windows/logon.rs +0 -0
  24. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/egress_windows/netevents.rs +0 -0
  25. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/egress_windows/run.rs +0 -0
  26. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/egress_windows/spawn.rs +0 -0
  27. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/egress_windows/wfp.rs +0 -0
  28. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/egress_windows.rs +0 -0
  29. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/fiori.rs +0 -0
  30. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/fs_observe.rs +0 -0
  31. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/lib.rs +0 -0
  32. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/mcp_core.rs +0 -0
  33. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/mcp_http.rs +0 -0
  34. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/mcp_stdio.rs +0 -0
  35. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/sap_com.rs +0 -0
  36. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/src/vision.rs +0 -0
  37. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/tests/a11y_capture.rs +0 -0
  38. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/tests/drag_spike.rs +0 -0
  39. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/tests/fs_observation_e2e.rs +0 -0
  40. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/tests/network_idle_e2e.rs +0 -0
  41. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/tests/shared_browser_shutdown_e2e.rs +0 -0
  42. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/tests/side_effect_http_e2e.rs +0 -0
  43. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-adapters/tests/windows_containment_e2e.rs +0 -0
  44. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/Cargo.toml +0 -0
  45. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/agent_steps.rs +0 -0
  46. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/clarify.rs +0 -0
  47. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/doc_author.rs +0 -0
  48. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/doc_formats/hp_alm.rs +0 -0
  49. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/doc_formats.rs +0 -0
  50. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/draft_assembly.rs +0 -0
  51. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/heal.rs +0 -0
  52. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/lib.rs +0 -0
  53. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/recorder.rs +0 -0
  54. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/repair.rs +0 -0
  55. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/rules.rs +0 -0
  56. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-agent/src/spec.rs +0 -0
  57. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/Cargo.toml +0 -0
  58. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/skills/flowproof-config/SKILL.md +0 -0
  59. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/src/agent_flow.rs +0 -0
  60. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/src/capture.rs +0 -0
  61. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/src/config.rs +0 -0
  62. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/src/doctor.rs +0 -0
  63. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/src/lib.rs +0 -0
  64. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/src/main.rs +0 -0
  65. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/src/suite.rs +0 -0
  66. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/src/suite_checkpoint.rs +0 -0
  67. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/src/suite_inputs.rs +0 -0
  68. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/src/suite_journal.rs +0 -0
  69. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/src/update_check.rs +0 -0
  70. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/a11y_selector_e2e.rs +0 -0
  71. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/agent_conversation_anthropic_e2e.rs +0 -0
  72. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/agent_conversation_streaming_e2e.rs +0 -0
  73. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/agent_flow_e2e.rs +0 -0
  74. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/agent_url_record_e2e.rs +0 -0
  75. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/api_pipeline.rs +0 -0
  76. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/audit_record_e2e.rs +0 -0
  77. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/calc_e2e.rs +0 -0
  78. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/clock_e2e.rs +0 -0
  79. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/config_cli_e2e.rs +0 -0
  80. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/config_seed_e2e.rs +0 -0
  81. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/config_skill_e2e.rs +0 -0
  82. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/cookie_e2e.rs +0 -0
  83. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/doctor_ai_e2e.rs +0 -0
  84. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/doctor_e2e.rs +0 -0
  85. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/documented_flags.rs +0 -0
  86. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/egress_e2e.rs +0 -0
  87. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/examples_resolve.rs +0 -0
  88. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/falsifiability_arg_matchers.rs +0 -0
  89. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/falsifiability_audit_since.rs +0 -0
  90. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/falsifiability_call_order.rs +0 -0
  91. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/falsifiability_capability_regression.rs +0 -0
  92. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/falsifiability_control_verdict.rs +0 -0
  93. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/falsifiability_mcp_kill.rs +0 -0
  94. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/falsifiability_no_tool_call.rs +0 -0
  95. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/falsifiability_reply_contains.rs +0 -0
  96. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/falsifiability_side_effect.rs +0 -0
  97. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/fiori_field_commit_e2e.rs +0 -0
  98. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/grid_cell_e2e.rs +0 -0
  99. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/iframe_e2e.rs +0 -0
  100. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/llm_author_e2e.rs +0 -0
  101. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/mcp_http_e2e.rs +0 -0
  102. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/mcp_stdio_e2e.rs +0 -0
  103. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/notepad_author_e2e.rs +0 -0
  104. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/notepad_e2e.rs +0 -0
  105. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/page_title_e2e.rs +0 -0
  106. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/pinned_random_e2e.rs +0 -0
  107. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/sap_e2e.rs +0 -0
  108. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/sap_pipeline.rs +0 -0
  109. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/sap_sim_e2e.rs +0 -0
  110. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/scoped_container_e2e.rs +0 -0
  111. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/select_missing_option_e2e.rs +0 -0
  112. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/skip_unless_env.rs +0 -0
  113. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/suite_checkpoint.rs +0 -0
  114. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/suite_env_from.rs +0 -0
  115. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/suite_flow_isolation.rs +0 -0
  116. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/suite_missing_trace.rs +0 -0
  117. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/suite_policy.rs +0 -0
  118. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/support/sap_simulator.py +0 -0
  119. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/visibility_e2e.rs +0 -0
  120. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/vision_pipeline.rs +0 -0
  121. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-cli/tests/web_e2e.rs +0 -0
  122. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-driver/Cargo.toml +0 -0
  123. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-driver/src/app.rs +0 -0
  124. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-driver/src/backend.rs +0 -0
  125. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-driver/src/gdi.rs +0 -0
  126. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-driver/src/lib.rs +0 -0
  127. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-driver/src/mock.rs +0 -0
  128. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-driver/src/oob.rs +0 -0
  129. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-driver/src/recording.rs +0 -0
  130. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-driver/src/redact.rs +0 -0
  131. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-driver/src/surface.rs +0 -0
  132. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-driver/src/visual.rs +0 -0
  133. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-driver/src/window.rs +0 -0
  134. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-python/Cargo.toml +0 -0
  135. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-python/src/lib.rs +0 -0
  136. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-replay/Cargo.toml +0 -0
  137. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-replay/src/lib.rs +0 -0
  138. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-replay/src/report.rs +0 -0
  139. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-replay/src/runrecord.rs +0 -0
  140. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-replay/tests/replay_calc.rs +0 -0
  141. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/Cargo.toml +0 -0
  142. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/schema/cassette-v1.schema.json +0 -0
  143. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/schema/side-effect-v1.schema.json +0 -0
  144. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/schema/trace-v1.schema.json +0 -0
  145. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/src/captures.rs +0 -0
  146. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/src/cassette.rs +0 -0
  147. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/src/cassette_diff.rs +0 -0
  148. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/src/egress.rs +0 -0
  149. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/src/format.rs +0 -0
  150. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/src/lib.rs +0 -0
  151. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/src/secret.rs +0 -0
  152. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/src/secret_scan.rs +0 -0
  153. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/src/side_effect.rs +0 -0
  154. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/src/substitution.rs +0 -0
  155. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/src/toolcalls.rs +0 -0
  156. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/tests/cassette_conformance.rs +0 -0
  157. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/tests/fixtures/multi.trace.jsonl +0 -0
  158. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/tests/fixtures/sample.trace.jsonl +0 -0
  159. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/tests/schema_conformance.rs +0 -0
  160. {flowproof-0.23.2 → flowproof-0.23.4}/crates/flowproof-trace/tests/side_effect_conformance.rs +0 -0
  161. {flowproof-0.23.2 → flowproof-0.23.4}/flowproof/cli.py +0 -0
  162. {flowproof-0.23.2 → flowproof-0.23.4}/flowproof/flow.py +0 -0
  163. {flowproof-0.23.2 → flowproof-0.23.4}/flowproof/mcp_server.py +0 -0
  164. {flowproof-0.23.2 → flowproof-0.23.4}/flowproof/py.typed +0 -0
@@ -930,7 +930,7 @@ dependencies = [
930
930
 
931
931
  [[package]]
932
932
  name = "flowproof-adapters"
933
- version = "0.23.2"
933
+ version = "0.23.4"
934
934
  dependencies = [
935
935
  "anyhow",
936
936
  "flowproof-driver",
@@ -949,7 +949,7 @@ dependencies = [
949
949
 
950
950
  [[package]]
951
951
  name = "flowproof-agent"
952
- version = "0.23.2"
952
+ version = "0.23.4"
953
953
  dependencies = [
954
954
  "chrono",
955
955
  "flowproof-driver",
@@ -967,7 +967,7 @@ dependencies = [
967
967
 
968
968
  [[package]]
969
969
  name = "flowproof-cli"
970
- version = "0.23.2"
970
+ version = "0.23.4"
971
971
  dependencies = [
972
972
  "ab_glyph",
973
973
  "chrono",
@@ -992,7 +992,7 @@ dependencies = [
992
992
 
993
993
  [[package]]
994
994
  name = "flowproof-driver"
995
- version = "0.23.2"
995
+ version = "0.23.4"
996
996
  dependencies = [
997
997
  "calamine",
998
998
  "flowproof-trace",
@@ -1008,7 +1008,7 @@ dependencies = [
1008
1008
 
1009
1009
  [[package]]
1010
1010
  name = "flowproof-python"
1011
- version = "0.23.2"
1011
+ version = "0.23.4"
1012
1012
  dependencies = [
1013
1013
  "flowproof-agent",
1014
1014
  "flowproof-cli",
@@ -1020,7 +1020,7 @@ dependencies = [
1020
1020
 
1021
1021
  [[package]]
1022
1022
  name = "flowproof-replay"
1023
- version = "0.23.2"
1023
+ version = "0.23.4"
1024
1024
  dependencies = [
1025
1025
  "chrono",
1026
1026
  "flowproof-agent",
@@ -1034,7 +1034,7 @@ dependencies = [
1034
1034
 
1035
1035
  [[package]]
1036
1036
  name = "flowproof-trace"
1037
- version = "0.23.2"
1037
+ version = "0.23.4"
1038
1038
  dependencies = [
1039
1039
  "jsonschema",
1040
1040
  "regex",
@@ -22,7 +22,7 @@ members = ["crates/flowproof-driver", "crates/flowproof-trace", "crates/flowproo
22
22
  exclude = ["spike/windows-containment"]
23
23
 
24
24
  [workspace.package]
25
- version = "0.23.2"
25
+ version = "0.23.4"
26
26
  edition = "2021"
27
27
  license = "Apache-2.0"
28
28
  repository = "https://github.com/automators-com/flowproof"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flowproof
3
- Version: 0.23.2
3
+ Version: 0.23.4
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: Programming Language :: Python :: 3
@@ -4691,8 +4691,14 @@ impl AppDriver for WebAppDriver {
4691
4691
  KeyMod::Meta => ModifierKey::Meta,
4692
4692
  })
4693
4693
  .collect();
4694
+ // CDP's key table uses the literal space as the key value; models
4695
+ // and human-authored specs commonly use its code/name instead.
4696
+ let browser_key = match key {
4697
+ "Space" | "Spacebar" => " ",
4698
+ _ => key,
4699
+ };
4694
4700
  self.tab()?
4695
- .press_key_with_modifiers(key, (!mods.is_empty()).then_some(mods.as_slice()))
4701
+ .press_key_with_modifiers(browser_key, (!mods.is_empty()).then_some(mods.as_slice()))
4696
4702
  .map_err(|e| web_err(&format!("pressing key '{key}'"), e))?;
4697
4703
  Ok(())
4698
4704
  }
@@ -4911,7 +4917,7 @@ impl AppDriver for WebAppDriver {
4911
4917
  standInHosts.add(host);
4912
4918
  }
4913
4919
  const interactive = el => el.matches(
4914
- 'input, button, a, select, textarea, [role=button], [role=checkbox], [role=radio], [role=menuitem], [draggable], [ondrop], .draggable-row, .droparea'
4920
+ 'input, button, a, select, textarea, [role=textbox], [role=combobox], [role=button], [role=checkbox], [role=radio], [role=menuitem], [draggable], [ondrop], .draggable-row, .droparea'
4915
4921
  ) || (!!el.id && el.children.length === 0 && ['DIV', 'SPAN'].includes(el.tagName)) ||
4916
4922
  styledLeaf(el) || standInHosts.has(el);
4917
4923
  const readableLeaf = el => {
@@ -4921,7 +4927,23 @@ impl AppDriver for WebAppDriver {
4921
4927
  (child.textContent || '').trim()
4922
4928
  ) && (semanticCss(el) || scopedReadable(el));
4923
4929
  };
4924
- const ordered = all.filter(interactive).concat(
4930
+ // Empty custom grid editors are controls too. Keep the first
4931
+ // editable row ahead of decorative toolbar leaves so the scene
4932
+ // budget cannot remove the fields needed to create an item.
4933
+ const firstGridRows = new Set();
4934
+ for (const editor of all.filter(el => el.matches('[role=textbox], [role=combobox]'))) {
4935
+ if (!isRendered(editor)) continue;
4936
+ const cell = editor.closest('[role=gridcell]');
4937
+ const row = cell && cell.closest('tr, [role=row]');
4938
+ const grid = cell && cell.closest('table, [role=grid]');
4939
+ if (row && grid && !Array.from(firstGridRows).some(r => r.closest('table, [role=grid]') === grid)) {
4940
+ firstGridRows.add(row);
4941
+ }
4942
+ }
4943
+ const priorityField = el => el.matches('input, select, textarea') ||
4944
+ (el.matches('[role=textbox], [role=combobox]') &&
4945
+ firstGridRows.has(el.closest('tr, [role=row]')));
4946
+ const ordered = all.filter(priorityField).concat(all.filter(interactive),
4925
4947
  all.filter(el => !interactive(el) && readableLeaf(el))
4926
4948
  );
4927
4949
  const seen = new Set();
@@ -4956,8 +4978,15 @@ impl AppDriver for WebAppDriver {
4956
4978
  const entries = chosen.map(el => {
4957
4979
  const css = cssPath(el);
4958
4980
  const scoped = !interactive(el) && !semanticCss(el) ? scopedReadable(el) : null;
4981
+ const labelledBy = (el.getAttribute('aria-labelledby') || '').split(/\s+/)
4982
+ .map(id => document.getElementById(id)?.textContent?.trim() || '').filter(Boolean).join(' ');
4959
4983
  const label = el.labels && el.labels[0] ? el.labels[0].textContent.trim()
4960
- : (el.getAttribute('aria-label') || el.getAttribute('placeholder') || '');
4984
+ : (el.getAttribute('aria-label') || labelledBy || el.getAttribute('placeholder') || '');
4985
+ const gridCell = el.closest('[role=gridcell]');
4986
+ const rowIndex = gridCell && (gridCell.getAttribute('aria-rowindex') ||
4987
+ gridCell.getAttribute('lsmatrixrowindex') ||
4988
+ gridCell.closest('[role=row]')?.getAttribute('aria-rowindex'));
4989
+
4961
4990
  const ticks = el.tagName === 'INPUT' && ['checkbox', 'radio'].includes(el.type);
4962
4991
  const isField = ['INPUT', 'SELECT', 'TEXTAREA'].includes(el.tagName);
4963
4992
  const entry = {
@@ -4967,7 +4996,9 @@ impl AppDriver for WebAppDriver {
4967
4996
  actionable: interactive(el),
4968
4997
  type: el.getAttribute('type') || undefined,
4969
4998
  text: (el.textContent || '').trim().slice(0, 80) || undefined,
4970
- label: label || undefined,
4999
+ label: label.trim().slice(0, 160) || undefined,
5000
+ row: rowIndex || undefined,
5001
+ role: el.getAttribute('role') || undefined,
4971
5002
  value: fieldValue(el),
4972
5003
  checked: ticks ? el.checked : undefined,
4973
5004
  required: el.required || undefined,
@@ -0,0 +1,54 @@
1
+ //! SAP-style empty custom editors must survive a crowded scene inventory.
2
+ use flowproof_driver::AppDriver;
3
+
4
+ #[test]
5
+ fn empty_grid_editors_have_column_labels_and_row_identity() {
6
+ if std::env::var("FLOWPROOF_E2E").as_deref() != Ok("1") {
7
+ return;
8
+ }
9
+ let _guard = flowproof_adapters::SharedBrowserGuard::new();
10
+ let toolbar = (0..120)
11
+ .map(|i| format!("<span id='tool{i}'>Tool {i}</span>"))
12
+ .collect::<String>();
13
+ let html = format!(
14
+ r#"<html><body>{toolbar}
15
+ <table><tr><th id="material-label">Material</th><th id="plant-label">Plant</th></tr>
16
+ <tr><td role="gridcell" lsmatrixrowindex="1"><span id="material" role="textbox" aria-labelledby="material-label" tabindex="0" style="display:block;width:100px;height:24px"></span></td>
17
+ <td role="gridcell" lsmatrixrowindex="1"><span id="plant" role="textbox" aria-labelledby="plant-label" tabindex="0" style="display:block;width:100px;height:24px"></span></td></tr></table>
18
+ <input type="password" value="never-export-this">
19
+ </body></html>"#
20
+ );
21
+ let listener = std::net::TcpListener::bind("127.0.0.1:0").expect("fixture listener");
22
+ let port = listener.local_addr().expect("listener address").port();
23
+ std::thread::spawn(move || {
24
+ use std::io::{Read, Write};
25
+ for mut stream in listener.incoming().flatten() {
26
+ let mut buf = [0; 2048];
27
+ let _ = stream.read(&mut buf);
28
+ let _ = write!(stream, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}", html.len(), html);
29
+ }
30
+ });
31
+ let mut driver = flowproof_adapters::WebAppDriver::new().expect("Chrome launches");
32
+ driver
33
+ .launch(
34
+ &format!("http://127.0.0.1:{port}"),
35
+ "",
36
+ std::time::Duration::from_secs(30),
37
+ )
38
+ .expect("fixture loads");
39
+ let scene = driver.scene().expect("scene reads").expect("scene exists");
40
+ let entries: serde_json::Value = serde_json::from_str(&scene).expect("scene JSON");
41
+ for (id, label) in [("material", "Material"), ("plant", "Plant")] {
42
+ let entry = entries
43
+ .as_array()
44
+ .expect("scene entries")
45
+ .iter()
46
+ .find(|e| e["target"] == format!("css:#{id}"))
47
+ .expect("empty editor in scene");
48
+ assert_eq!(entry["label"], label);
49
+ assert_eq!(entry["row"], "1");
50
+ assert_eq!(entry["actionable"], true);
51
+ assert_eq!(entry["role"], "textbox");
52
+ }
53
+ assert!(!scene.contains("never-export-this"));
54
+ }
@@ -32,6 +32,7 @@ fn serve(html: &'static str) -> String {
32
32
  }
33
33
 
34
34
  const FIXTURE: &str = r#"<!doctype html><html><body>
35
+ <input id="space-toggle" type="checkbox">
35
36
  <div id="app">
36
37
  <button id="open" onclick="
37
38
  var d = document.createElement('div');
@@ -69,6 +70,26 @@ fn search_reaches_content_outside_the_app_root() {
69
70
  .invoke(&UiaSelector::css("#open"))
70
71
  .expect("opening the dialog succeeds");
71
72
 
73
+ // Space aliases must produce real keyboard activation, not text insertion.
74
+ driver
75
+ .invoke(&UiaSelector::css("#space-toggle"))
76
+ .expect("focus checkbox");
77
+ assert!(driver
78
+ .element_exists(&UiaSelector::css("#space-toggle:checked"))
79
+ .expect("checked"));
80
+ for key in ["Space", "Spacebar", " "] {
81
+ driver
82
+ .press_key(key, &[])
83
+ .expect("space key activates checkbox");
84
+ assert!(driver
85
+ .element_exists(&UiaSelector::css("#space-toggle:not(:checked)"))
86
+ .expect("unchecked"));
87
+ driver.press_key(key, &[]).expect("space toggles back");
88
+ assert!(driver
89
+ .element_exists(&UiaSelector::css("#space-toggle:checked"))
90
+ .expect("checked again"));
91
+ }
92
+
72
93
  // Native-id (css) reach: the sibling div is appended to <body>, a
73
94
  // structural ancestor of neither #app nor anything inside it.
74
95
  assert!(
@@ -67,7 +67,7 @@ action that reaches the goal.
67
67
  - Respond with ONLY JSON, no prose, no code fences.
68
68
  - The JSON action is one of: \"click\", \"click_at\", \"drag\", \"type_text\", \
69
69
  \"assert_text\", \"capture_text\", \"capture_count\", \"type_captured\", \
70
- \"select_option\", \"select_options\", \"scroll\", \"press_key\", \"rule_step\", or \
70
+ \"select_option\", \"select_options\", \"scroll\", \"scroll_into_view\", \"press_key\", \"rule_step\", or \
71
71
  \"capture_ambiguity\".
72
72
  - UI actions MUST include \"target\": \"<target token of a listed element>\". \
73
73
  Clicking and typing require an entry whose \"actionable\" field is true. \
@@ -77,7 +77,11 @@ type_text also needs \"text\"; assert_text needs \"expected\" and optional \
77
77
  drag needs \"onto\" with a second listed actionable target. click_at needs \
78
78
  \"x_pct\" and \"y_pct\" from 0 through 100. capture_count needs a safe \"name\". \
79
79
  select_option needs one \"text\" value; select_options is only for a multi-select \
80
- and needs a non-empty \"values\" array. scroll needs \"to_px\". \
80
+ and needs a non-empty \"values\" array. scroll needs \"to_px\" and means an exact \
81
+ vertical offset inside a scroll container. To reveal a field or cell, use \
82
+ scroll_into_view with that individual target instead; it needs no offset. \
83
+ Never scroll a collection (tag=collection): it represents multiple rows for counting, \
84
+ not a scroll container. For horizontal grids, reveal the desired cell, not a row collection. \
81
85
  press_key needs \"key\" and has no target. \
82
86
  For another action, use rule_step with \"step\" containing exact \
83
87
  deterministic grammar and copy listed target tokens into quoted targets, for \
@@ -881,12 +885,32 @@ fn ground_one(
881
885
  .ok_or("select_option needs a non-empty 'text'")?;
882
886
  Ok(vec![ResolvedAction::TypeText { target, text }])
883
887
  }
884
- "scroll" => Ok(vec![ResolvedAction::Scroll {
885
- target: Some(target),
886
- to: crate::rules::ScrollTo::Offset(
887
- authored.to_px.ok_or("scroll needs a 'to_px' offset")?,
888
- ),
889
- }]),
888
+ "scroll" | "scroll_into_view" => {
889
+ let entries: Vec<serde_json::Value> = serde_json::from_str(scene).unwrap_or_default();
890
+ if entries.iter().any(|entry| {
891
+ (entry["target"].as_str() == Some(token)
892
+ || entry["css"]
893
+ .as_str()
894
+ .is_some_and(|css| token == css || token == format!("css:{css}")))
895
+ && entry["tag"] == "collection"
896
+ }) {
897
+ return Err("cannot scroll a collection; choose an individual cell with scroll_into_view or a scroll container with scroll".into());
898
+ }
899
+ let to = if authored.action == "scroll_into_view" {
900
+ if authored.to_px.is_some() {
901
+ return Err("scroll_into_view does not accept to_px".into());
902
+ }
903
+ crate::rules::ScrollTo::IntoView
904
+ } else {
905
+ crate::rules::ScrollTo::Offset(
906
+ authored.to_px.ok_or("scroll needs a 'to_px' offset")?,
907
+ )
908
+ };
909
+ Ok(vec![ResolvedAction::Scroll {
910
+ target: Some(target),
911
+ to,
912
+ }])
913
+ }
890
914
  "type_captured" => {
891
915
  let name = authored
892
916
  .capture
@@ -2329,6 +2353,34 @@ mod tests {
2329
2353
  }
2330
2354
  }
2331
2355
 
2356
+ #[test]
2357
+ fn collection_scroll_is_rejected_and_reauthored_as_reveal_cell() {
2358
+ let mut client = Scripted {
2359
+ replies: vec![
2360
+ r#"{"action":"scroll","target":"css:#rows tr","to_px":0}"#.into(),
2361
+ r#"{"action":"scroll_into_view","target":"css:#task-1"}"#.into(),
2362
+ ],
2363
+ calls: 0,
2364
+ };
2365
+ let result = author_step(
2366
+ &mut client,
2367
+ &AuthorContext {
2368
+ intent: "Bring the first task into view",
2369
+ scene: HUMAN_PRIMITIVE_SCENE,
2370
+ ..ctx()
2371
+ },
2372
+ )
2373
+ .expect("collection rejection should reauthor an individual target");
2374
+ assert_eq!(client.calls, 2);
2375
+ assert_eq!(
2376
+ result,
2377
+ ResolvedAction::Scroll {
2378
+ target: Some(Target::css("#task-1")),
2379
+ to: crate::rules::ScrollTo::IntoView,
2380
+ }
2381
+ );
2382
+ }
2383
+
2332
2384
  #[test]
2333
2385
  fn rule_step_covers_grounded_actions_outside_the_small_json_vocabulary() {
2334
2386
  let mut client = Scripted {
@@ -225,20 +225,24 @@ impl HttpModelClient {
225
225
  if let Some(key) = &self.config.api_key {
226
226
  request = request.header("authorization", format!("Bearer {key}"));
227
227
  }
228
- // `temperature` stays here: OpenAI's API and a local vLLM both accept
229
- // it, and determinism is worth having where it is free. The
230
- // deprecation that forced it out of the Anthropic request is specific
231
- // to that API's current models.
228
+ let mut body = json!({
229
+ "model": self.model(),
230
+ "messages": [
231
+ {"role": "system", "content": system},
232
+ {"role": "user", "content": user},
233
+ ],
234
+ });
235
+ if self.config.kind == BackendKind::OpenAi {
236
+ // Includes reasoning tokens. GPT-5 rejects legacy max_tokens and
237
+ // temperature=0; leave sampling at the model's supported default.
238
+ body["max_completion_tokens"] = json!(16_384);
239
+ } else {
240
+ // Preserve the contract of local OpenAI-compatible servers.
241
+ body["max_tokens"] = json!(OPENAI_COMPATIBLE_MAX_TOKENS);
242
+ body["temperature"] = json!(0);
243
+ }
232
244
  let mut response = request
233
- .send_json(json!({
234
- "model": self.model(),
235
- "max_tokens": OPENAI_COMPATIBLE_MAX_TOKENS,
236
- "temperature": 0,
237
- "messages": [
238
- {"role": "system", "content": system},
239
- {"role": "user", "content": user},
240
- ],
241
- }))
245
+ .send_json(body)
242
246
  .map_err(|e| Self::http_err("openai-compatible", e))?;
243
247
  let response: serde_json::Value = Self::json_or_error(
244
248
  "openai-compatible",
@@ -132,3 +132,33 @@ fn an_echoed_key_is_redacted_from_the_error() {
132
132
  "and the redaction is visible: {text}"
133
133
  );
134
134
  }
135
+
136
+ #[test]
137
+ fn openai_reasoning_request_and_compatible_server_use_their_own_parameters() {
138
+ for kind in [BackendKind::OpenAi, BackendKind::OpenAiCompatible] {
139
+ let (base, rx) = serve_once(200, r#"{"choices":[{"message":{"content":"ok"}}]}"#);
140
+ let mut client = HttpModelClient::new(BackendConfig {
141
+ kind: kind.clone(),
142
+ base_url: Some(base),
143
+ model: Some("gpt-5".into()),
144
+ api_key: Some("test-key".into()),
145
+ });
146
+ assert_eq!(
147
+ client
148
+ .complete("system", "user")
149
+ .expect("completion succeeds"),
150
+ "ok"
151
+ );
152
+ let sent: serde_json::Value = serde_json::from_str(&rx.recv().expect("request captured"))
153
+ .expect("valid request JSON");
154
+ if kind == BackendKind::OpenAi {
155
+ assert_eq!(sent["max_completion_tokens"], 16384);
156
+ assert!(sent.get("max_tokens").is_none());
157
+ assert!(sent.get("temperature").is_none());
158
+ } else {
159
+ assert_eq!(sent["max_tokens"], 1024);
160
+ assert_eq!(sent["temperature"], 0);
161
+ assert!(sent.get("max_completion_tokens").is_none());
162
+ }
163
+ }
164
+ }
@@ -24,7 +24,7 @@ from flowproof.flow import (
24
24
  run,
25
25
  )
26
26
 
27
- __version__ = "0.23.2"
27
+ __version__ = "0.23.4"
28
28
 
29
29
  __all__ = [
30
30
  "ClarificationNeeded",
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "flowproof"
7
- version = "0.23.2"
7
+ version = "0.23.4"
8
8
  description = "Test that a bot only ever does the job it was given — and never deletes, sends or approves the thing it must not. Record it doing the job once, then replay on every commit with zero LLM calls. For the agents and RPA already running real work in production: web, desktop, SAP, Citrix."
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
File without changes
File without changes
File without changes