gflow-cli 0.23.0__tar.gz → 0.25.0__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 (503) hide show
  1. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.env.template +4 -3
  2. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/CHANGELOG.md +112 -1
  3. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/PKG-INFO +1 -1
  4. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/CONFIGURATION.md +4 -2
  5. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/INDEX.md +1 -1
  6. gflow_cli-0.25.0/docs/LIVE_VERIFICATION_v0.24.0.md +38 -0
  7. gflow_cli-0.25.0/docs/LIVE_VERIFICATION_v0.25.0.md +97 -0
  8. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/MCP.md +2 -2
  9. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/PROJECT_STATUS.md +14 -1
  10. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/SECURITY.md +1 -1
  11. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/USAGE.md +29 -6
  12. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/pyproject.toml +1 -1
  13. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/__init__.py +1 -1
  14. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/_cli_helpers.py +21 -0
  15. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/client.py +19 -1
  16. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/ui_automation_video.py +262 -80
  17. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/video.py +31 -15
  18. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/cli.py +1 -1
  19. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/cli_image.py +6 -19
  20. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/cli_video.py +66 -25
  21. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/config.py +67 -7
  22. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/models.py +2 -0
  23. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/repository.py +57 -62
  24. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/mcp/tools.py +253 -99
  25. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/paths.py +19 -0
  26. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/worker/daemon.py +15 -0
  27. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_client_image.py +23 -0
  28. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_client_launch_kwargs.py +45 -0
  29. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_video.py +1 -1
  30. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_video_request.py +14 -1
  31. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/test_ui_automation_video.py +95 -0
  32. gflow_cli-0.25.0/tests/auth/test_cookies.py +107 -0
  33. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_video.py +187 -29
  34. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_helpers.py +10 -1
  35. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/data/test_repository.py +48 -0
  36. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/conftest.py +4 -2
  37. gflow_cli-0.25.0/tests/mcp/test_tools_helpers.py +282 -0
  38. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/mcp/test_tools_wired.py +135 -0
  39. gflow_cli-0.25.0/tests/test_config.py +456 -0
  40. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_paths.py +33 -0
  41. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/worker/test_daemon.py +84 -0
  42. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/uv.lock +1 -1
  43. gflow_cli-0.23.0/tests/auth/test_cookies.py +0 -51
  44. gflow_cli-0.23.0/tests/test_config.py +0 -227
  45. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/README.md +0 -0
  46. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/active.md +0 -0
  47. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/branch-review.md +0 -0
  48. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/changelog.md +0 -0
  49. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/check.md +0 -0
  50. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/doc-review.md +0 -0
  51. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/issue-assessment.md +0 -0
  52. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/issue-resolve.md +0 -0
  53. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/known-issues.md +0 -0
  54. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/next.md +0 -0
  55. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/plan.md +0 -0
  56. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/pr-council-review.md +0 -0
  57. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/predict.md +0 -0
  58. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/release.md +0 -0
  59. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/scenario.md +0 -0
  60. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/sonar.md +0 -0
  61. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.claude/commands/gflow/status.md +0 -0
  62. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.gitattributes +0 -0
  63. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.github/CODEOWNERS +0 -0
  64. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  65. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.github/copilot-instructions.md +0 -0
  66. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.github/dependabot.yml +0 -0
  67. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.github/workflows/ci.yml +0 -0
  68. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.github/workflows/external-pr-triage.yml +0 -0
  69. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.github/workflows/governance-advisory.yml +0 -0
  70. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.github/workflows/governance-benchmark.yml +0 -0
  71. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.github/workflows/main-base-guard.yml +0 -0
  72. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.github/workflows/release.yml +0 -0
  73. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.gitignore +0 -0
  74. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.gitleaks.toml +0 -0
  75. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.pre-commit-config.yaml +0 -0
  76. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/.secrets.baseline +0 -0
  77. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/AGENTS.md +0 -0
  78. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/CLAUDE.md +0 -0
  79. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/CONFIGURATION.md +0 -0
  80. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/CONTRIBUTING.md +0 -0
  81. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/DISCLAIMER.md +0 -0
  82. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/GEMINI.md +0 -0
  83. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/KNOWN_ISSUES.md +0 -0
  84. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/LICENSE +0 -0
  85. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/PLAN.md +0 -0
  86. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/README.md +0 -0
  87. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/RELEASE.md +0 -0
  88. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/ROADMAP.md +0 -0
  89. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/conftest.py +0 -0
  90. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docker-compose.yml +0 -0
  91. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/AGENT_GUIDE.md +0 -0
  92. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/AGENT_UI_E2E.md +0 -0
  93. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/AGENT_UI_RECON.md +0 -0
  94. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/ARCHITECTURE.md +0 -0
  95. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/AUTHENTICATION.md +0 -0
  96. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/CHARACTER.md +0 -0
  97. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/CHARACTER_RECON.md +0 -0
  98. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/DATA_LAYER.md +0 -0
  99. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/DEBUGGING.md +0 -0
  100. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/DEMOS.md +0 -0
  101. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/DEVELOPMENT.md +0 -0
  102. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/E2E_TESTING.md +0 -0
  103. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/EXTERNAL_STORAGE.md +0 -0
  104. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/GITHUB.md +0 -0
  105. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/GOVERNANCE_BENCHMARK.md +0 -0
  106. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/IMAGE_UPSCALE_RECON.md +0 -0
  107. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_data_layer.md +0 -0
  108. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_image_batch.md +0 -0
  109. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.10.0.md +0 -0
  110. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.11.0.md +0 -0
  111. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.12.0.md +0 -0
  112. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.13.0.md +0 -0
  113. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.16.0.md +0 -0
  114. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.17.0.md +0 -0
  115. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.18.0.md +0 -0
  116. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.19.0.md +0 -0
  117. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.20.0.md +0 -0
  118. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.20.1.md +0 -0
  119. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.21.0.md +0 -0
  120. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.22.0.md +0 -0
  121. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.23.0.md +0 -0
  122. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.7.0.md +0 -0
  123. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.8.1.md +0 -0
  124. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.9.0.md +0 -0
  125. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_v0.9.1.md +0 -0
  126. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/LIVE_VERIFICATION_video_download.md +0 -0
  127. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/MOVIE.md +0 -0
  128. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/PROMPT_EXPANSION.md +0 -0
  129. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/TOOLS.md +0 -0
  130. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/USER_GUIDE.md +0 -0
  131. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/assets/demo-split-pf.gif +0 -0
  132. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/assets/example-run.gif +0 -0
  133. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/assets/examples.webp +0 -0
  134. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/medium_tutorial.md +0 -0
  135. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/schemas/movie-handoff.schema.json +0 -0
  136. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/sonar-cleanup-tracker.md +0 -0
  137. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/superpowers/plans/2026-06-12-issue-174-library-ui-attach/PLAN.md +0 -0
  138. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/superpowers/plans/2026-06-22-mcp-server/PLAN.md +0 -0
  139. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/superpowers/plans/2026-06-22-mcp-server/PREDICT.md +0 -0
  140. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/superpowers/plans/2026-06-22-mcp-server/SCENARIO.md +0 -0
  141. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/superpowers/plans/2026-06-22-prompt-expansion/PLAN.md +0 -0
  142. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/superpowers/plans/2026-06-22-prompt-expansion/PREDICT.md +0 -0
  143. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/superpowers/plans/2026-06-22-prompt-expansion/SCENARIO.md +0 -0
  144. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/superpowers/plans/2026-06-24-gflow-studio-scaffold/PLAN.md +0 -0
  145. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/superpowers/plans/2026-06-24-rest-api-layer/PLAN.md +0 -0
  146. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/superpowers/plans/2026-06-26-mcp-e2e-test/PLAN.md +0 -0
  147. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/superpowers/research/2026-06-27-tool-abstraction-evaluation.md +0 -0
  148. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/docs/superpowers/specs/2026-06-29-issue-assessment-workflow-design.md +0 -0
  149. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/examples/README.md +0 -0
  150. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/examples/batch_from_config.py +0 -0
  151. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/examples/multi_prompt_t2i.py +0 -0
  152. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/examples/sample_config.json +0 -0
  153. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/examples/sample_prompts.txt +0 -0
  154. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/examples/single_image_t2i.py +0 -0
  155. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/examples/workflow_chain.py +0 -0
  156. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/llms.txt +0 -0
  157. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/README.md +0 -0
  158. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/01_upload_image.json +0 -0
  159. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
  160. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
  161. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/04_archive_workflow.json +0 -0
  162. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/05_createProject.json +0 -0
  163. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/06_batchGenerateImages.json +0 -0
  164. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
  165. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/08_batchAsyncGenerateVideoStartAndEndImage.json +0 -0
  166. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/09_batchAsyncGenerateVideoReferenceImages.json +0 -0
  167. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/10_batchCheckAsyncVideoGenerationStatus_successful.json +0 -0
  168. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/11_batchCheckAsyncVideoGenerationStatus_failed.json +0 -0
  169. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/12_create_scene.json +0 -0
  170. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/13_sceneWorkflows_update.json +0 -0
  171. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/14_get_scene_workflows.json +0 -0
  172. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/samples/captured/15_commit_flowWorkflow.json +0 -0
  173. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/ci/check_doc_links.py +0 -0
  174. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/ci/check_materiality.py +0 -0
  175. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/ci/check_repo_hygiene.py +0 -0
  176. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/debug_editor.py +0 -0
  177. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/debug_gen_settings.py +0 -0
  178. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/debug_settings.py +0 -0
  179. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/_recording_client.py +0 -0
  180. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/_spike_common.py +0 -0
  181. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/active_plan.py +0 -0
  182. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/analyze_agent_ui_capture.py +0 -0
  183. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/capture_i2v_frame_slots_dom.py +0 -0
  184. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/capture_i2v_intercept_submit.py +0 -0
  185. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/capture_i2v_model_select_repro.py +0 -0
  186. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/capture_i2v_post_bind_state.py +0 -0
  187. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/capture_image_add_media_dom.py +0 -0
  188. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/capture_locale_invariants.py +0 -0
  189. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/cdp_drive_and_probe.py +0 -0
  190. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/character_create_spike.py +0 -0
  191. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/character_create_spike_v2.py +0 -0
  192. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/dump_character_selectors.js +0 -0
  193. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/make_project.py +0 -0
  194. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/materiality_backtest.py +0 -0
  195. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/monitor_pr_38.py +0 -0
  196. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/patch_character.py +0 -0
  197. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/skillopt/README.md +0 -0
  198. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/skillopt/harness.py +0 -0
  199. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/skillopt/tasks.json +0 -0
  200. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_char_editor_dom.py +0 -0
  201. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_char_gen_capture.py +0 -0
  202. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_image_upscale_capture.py +0 -0
  203. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_image_upscale_drive.py +0 -0
  204. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_image_upscale_recaptcha_action.py +0 -0
  205. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_image_upscale_rest_probe.py +0 -0
  206. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_issue170_picker_locale_recon.py +0 -0
  207. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_issue174_library_ui_recon.py +0 -0
  208. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_movie_attach_payload.py +0 -0
  209. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_movie_entity_recon.py +0 -0
  210. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_movie_gen_capture.py +0 -0
  211. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_movie_picker_select.py +0 -0
  212. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_movie_voice_list.py +0 -0
  213. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_patch_entity.py +0 -0
  214. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/dev/spike_patchright.py +0 -0
  215. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/diag/README.md +0 -0
  216. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/diag/capture_flow_traffic.py +0 -0
  217. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/diag/memory_profile.py +0 -0
  218. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/diag/recaptcha_mint.py +0 -0
  219. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/e2e/agentic_image_e2e.ps1 +0 -0
  220. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/e2e/capture_agent_toggle.py +0 -0
  221. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/record_demo.ps1 +0 -0
  222. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/smoke_image.py +0 -0
  223. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/smoke_real_chrome_image.py +0 -0
  224. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/smoke_video_editor.py +0 -0
  225. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/smoke_worker_style.py +0 -0
  226. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/scripts/verify_chrome_auth_viability.py +0 -0
  227. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/skills/README.md +0 -0
  228. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/skills/gflow-cli/SKILL.md +0 -0
  229. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/skills/issue-assessment/SKILL.md +0 -0
  230. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/skills/issue-resolve/SKILL.md +0 -0
  231. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/skills/plan/SKILL.md +0 -0
  232. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/skills/pr-council-review/SKILL.md +0 -0
  233. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/skills/predict/SKILL.md +0 -0
  234. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/skills/scenario/SKILL.md +0 -0
  235. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/skills/status/SKILL.md +0 -0
  236. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/sonar-project.properties +0 -0
  237. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/__main__.py +0 -0
  238. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/__init__.py +0 -0
  239. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/_engine.py +0 -0
  240. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/_retry.py +0 -0
  241. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/_sapisidhash.py +0 -0
  242. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/character.py +0 -0
  243. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/dto.py +0 -0
  244. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/image.py +0 -0
  245. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/image_upscale.py +0 -0
  246. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/recaptcha.py +0 -0
  247. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/routes.py +0 -0
  248. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/scene.py +0 -0
  249. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/__init__.py +0 -0
  250. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/_common.py +0 -0
  251. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/_fingerprint.py +0 -0
  252. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/base.py +0 -0
  253. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/drivers/__init__.py +0 -0
  254. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/drivers/agentic.py +0 -0
  255. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/drivers/base.py +0 -0
  256. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/drivers/classic.py +0 -0
  257. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/drivers/factory.py +0 -0
  258. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/experimental/__init__.py +0 -0
  259. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/experimental/bearer.py +0 -0
  260. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +0 -0
  261. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/experimental/sapisidhash.py +0 -0
  262. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/api/transports/ui_automation.py +0 -0
  263. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/auth/__init__.py +0 -0
  264. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/auth/base.py +0 -0
  265. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/auth/cookies.py +0 -0
  266. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/auth/factory.py +0 -0
  267. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/auth/internal_chromium.py +0 -0
  268. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/auth/real_chrome.py +0 -0
  269. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/auth/strategies.py +0 -0
  270. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/auth/verification.py +0 -0
  271. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/browser_manager.py +0 -0
  272. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/chain.py +0 -0
  273. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/chain_manifest.py +0 -0
  274. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/cli_character.py +0 -0
  275. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/cli_data.py +0 -0
  276. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/cli_models.py +0 -0
  277. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/cli_movie.py +0 -0
  278. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/cli_run.py +0 -0
  279. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/cli_scene.py +0 -0
  280. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/cli_tools.py +0 -0
  281. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/composition.py +0 -0
  282. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/__init__.py +0 -0
  283. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/chain_repo.py +0 -0
  284. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/migrations/0001_initial.sql +0 -0
  285. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/migrations/0002_add_cloud_storage.sql +0 -0
  286. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/migrations/0003_add_scene_tables.sql +0 -0
  287. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/migrations/0004_add_scene_output_path.sql +0 -0
  288. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/migrations/0005_add_chain_links.sql +0 -0
  289. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/migrations/0006_add_operations_metadata.sql +0 -0
  290. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/migrations/0007_queue.sql +0 -0
  291. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/migrations/0008_add_operation_expanded_prompt.sql +0 -0
  292. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/migrations/__init__.py +0 -0
  293. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/queries.py +0 -0
  294. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/recorder.py +0 -0
  295. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/redaction.py +0 -0
  296. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/data/store.py +0 -0
  297. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/errors.py +0 -0
  298. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/exceptions.py +0 -0
  299. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/image_batch.py +0 -0
  300. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/json_output.py +0 -0
  301. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/manifest.py +0 -0
  302. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/mcp/__init__.py +0 -0
  303. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/mcp/prompts.py +0 -0
  304. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/mcp/resources.py +0 -0
  305. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/mcp/server.py +0 -0
  306. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/media.py +0 -0
  307. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/movie_manifest.py +0 -0
  308. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/observability.py +0 -0
  309. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/profile_store.py +0 -0
  310. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/services/__init__.py +0 -0
  311. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/services/character_create.py +0 -0
  312. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/storage.py +0 -0
  313. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/tools/__init__.py +0 -0
  314. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/tools/banned.py +0 -0
  315. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/tools/builtin/__init__.py +0 -0
  316. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/tools/builtin/creative-director.toml +0 -0
  317. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/tools/expander.py +0 -0
  318. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/tools/invocation.py +0 -0
  319. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/tools/loader.py +0 -0
  320. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/tools/registry.py +0 -0
  321. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/tools/runtime.py +0 -0
  322. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/tools/spec.py +0 -0
  323. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/ui/app.py +0 -0
  324. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/ui/server.py +0 -0
  325. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/src/gflow_cli/worker/queue.py +0 -0
  326. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tasks/lessons.md +0 -0
  327. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/test_assets/sample_batch.json +0 -0
  328. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/test_assets/sample_batch.tsv +0 -0
  329. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/test_assets/sample_batch_invalid.tsv +0 -0
  330. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/__init__.py +0 -0
  331. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/__init__.py +0 -0
  332. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/fixtures/character_gen_response.json +0 -0
  333. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/fixtures/patch_entity_response.json +0 -0
  334. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_aisandbox_auth_error.py +0 -0
  335. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_aisandbox_auth_headers.py +0 -0
  336. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_bearer_redaction.py +0 -0
  337. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_character.py +0 -0
  338. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_client.py +0 -0
  339. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_client_character.py +0 -0
  340. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_client_delete_characters.py +0 -0
  341. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_client_generate_character.py +0 -0
  342. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_client_patch_entity.py +0 -0
  343. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_client_scene.py +0 -0
  344. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_client_upscale.py +0 -0
  345. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_concurrency.py +0 -0
  346. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_dto.py +0 -0
  347. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_engine.py +0 -0
  348. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_image.py +0 -0
  349. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_image_dto.py +0 -0
  350. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_image_upscale.py +0 -0
  351. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_post_json_aisandbox_auth.py +0 -0
  352. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_recaptcha.py +0 -0
  353. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_retry.py +0 -0
  354. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_routes.py +0 -0
  355. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_routes_character.py +0 -0
  356. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_routes_scene.py +0 -0
  357. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_sapisidhash_helper.py +0 -0
  358. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/test_scene_models.py +0 -0
  359. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/__init__.py +0 -0
  360. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/conftest.py +0 -0
  361. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/drivers/__init__.py +0 -0
  362. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/drivers/test_agentic.py +0 -0
  363. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/drivers/test_factory.py +0 -0
  364. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/test_base.py +0 -0
  365. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/test_bearer.py +0 -0
  366. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/test_common.py +0 -0
  367. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/test_evaluate_fetch.py +0 -0
  368. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/test_factory.py +0 -0
  369. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/test_fingerprint.py +0 -0
  370. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/test_sapisidhash.py +0 -0
  371. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/test_transport_timeout.py +0 -0
  372. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/test_ui_automation.py +0 -0
  373. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/test_ui_automation_batch.py +0 -0
  374. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/test_ui_automation_image_mode.py +0 -0
  375. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/api/transports/test_ui_character_editor.py +0 -0
  376. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/auth/strategies/test_factory.py +0 -0
  377. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/auth/strategies/test_strategies.py +0 -0
  378. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/auth/test_verification.py +0 -0
  379. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/__init__.py +0 -0
  380. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_auth_list.py +0 -0
  381. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_character.py +0 -0
  382. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_character_create.py +0 -0
  383. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_data.py +0 -0
  384. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_image.py +0 -0
  385. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_image_seed_removed.py +0 -0
  386. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_image_selector_drift.py +0 -0
  387. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_image_upscale.py +0 -0
  388. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_models.py +0 -0
  389. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_movie.py +0 -0
  390. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_run.py +0 -0
  391. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_scene.py +0 -0
  392. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_tools.py +0 -0
  393. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_cli_video_chain.py +0 -0
  394. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_error_handling.py +0 -0
  395. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_movie_manifest.py +0 -0
  396. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_settings_validation.py +0 -0
  397. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/cli/test_t2i_multi_prompt.py +0 -0
  398. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/composition/test_character.py +0 -0
  399. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/composition/test_compose_prompt.py +0 -0
  400. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/composition/test_handoff.py +0 -0
  401. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/conftest.py +0 -0
  402. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/data/__init__.py +0 -0
  403. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/data/test_chain_repo.py +0 -0
  404. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/data/test_find_incomplete_character.py +0 -0
  405. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/data/test_models.py +0 -0
  406. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/data/test_packaging.py +0 -0
  407. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/data/test_recorder.py +0 -0
  408. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/data/test_recorder_character.py +0 -0
  409. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/data/test_redaction.py +0 -0
  410. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/data/test_scene_persistence.py +0 -0
  411. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/data/test_settings_and_errors.py +0 -0
  412. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/data/test_store_migrations.py +0 -0
  413. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/dev/test_recording_client.py +0 -0
  414. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/__init__.py +0 -0
  415. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_aisandbox_auth_live.py +0 -0
  416. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_auth_verification_e2e.py +0 -0
  417. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_chain_e2e.py +0 -0
  418. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_character_create_e2e.py +0 -0
  419. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_daemon_e2e.py +0 -0
  420. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_data_layer_e2e.py +0 -0
  421. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_i2v_flags_e2e.py +0 -0
  422. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_image_batch_e2e.py +0 -0
  423. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_image_i2i_ref_cap_e2e.py +0 -0
  424. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_json_output_e2e.py +0 -0
  425. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_locale_selectors_e2e.py +0 -0
  426. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_scene_compose_live.py +0 -0
  427. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_tools_e2e.py +0 -0
  428. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_transports_e2e.py +0 -0
  429. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_video_r2v_ref_cap_e2e.py +0 -0
  430. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/e2e/test_video_t2v_e2e.py +0 -0
  431. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/__init__.py +0 -0
  432. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/auth.feature +0 -0
  433. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/auth_login.feature +0 -0
  434. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/character_create.feature +0 -0
  435. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/character_read.feature +0 -0
  436. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/conftest.py +0 -0
  437. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/image.feature +0 -0
  438. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/image_upscale.feature +0 -0
  439. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/locale_picker_include.feature +0 -0
  440. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/test_auth_login_steps.py +0 -0
  441. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/test_auth_steps.py +0 -0
  442. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/test_character_create_steps.py +0 -0
  443. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/test_character_read_steps.py +0 -0
  444. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/test_image_steps.py +0 -0
  445. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/test_image_upscale_steps.py +0 -0
  446. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/test_locale_picker_include_steps.py +0 -0
  447. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/test_step_collision_guard.py +0 -0
  448. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/test_video_agent_ui_steps.py +0 -0
  449. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/test_video_chain_steps.py +0 -0
  450. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/video_agent_ui.feature +0 -0
  451. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/features/video_chain.feature +0 -0
  452. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/fixtures/__init__.py +0 -0
  453. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/fixtures/seeded_catalog.py +0 -0
  454. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/image_batch/__init__.py +0 -0
  455. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/image_batch/test_image_manifest.py +0 -0
  456. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/image_batch/test_observability_events.py +0 -0
  457. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/integration/__init__.py +0 -0
  458. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/integration/conftest.py +0 -0
  459. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/integration/constants.py +0 -0
  460. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/integration/test_storage_gcs.py +0 -0
  461. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/integration/test_storage_s3.py +0 -0
  462. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/mcp/__init__.py +0 -0
  463. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/mcp/conftest.py +0 -0
  464. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/mcp/test_server.py +0 -0
  465. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/mcp/test_stdio_transport.py +0 -0
  466. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/scripts/test_analyze_agent_ui_capture.py +0 -0
  467. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/scripts/test_capture_locale_invariants.py +0 -0
  468. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/scripts/test_check_materiality.py +0 -0
  469. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/scripts/test_check_repo_hygiene.py +0 -0
  470. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/scripts/test_materiality_backtest.py +0 -0
  471. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/services/__init__.py +0 -0
  472. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/services/test_character_create_redaction.py +0 -0
  473. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/services/test_character_create_saga.py +0 -0
  474. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/services/test_character_gen_no_direct_post.py +0 -0
  475. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/smoke/__init__.py +0 -0
  476. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/smoke/test_profile_account_smoke.py +0 -0
  477. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/smoke/test_real_flow.py +0 -0
  478. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_auth.py +0 -0
  479. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_browser_manager.py +0 -0
  480. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_chain.py +0 -0
  481. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_chain_manifest.py +0 -0
  482. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_cli_data.py +0 -0
  483. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_conftest_isolation.py +0 -0
  484. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_data_queries.py +0 -0
  485. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_documentation_gate.py +0 -0
  486. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_errors.py +0 -0
  487. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_errors_403.py +0 -0
  488. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_json_output.py +0 -0
  489. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_manifest.py +0 -0
  490. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_marker_registry.py +0 -0
  491. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_media.py +0 -0
  492. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_observability.py +0 -0
  493. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_profile_store.py +0 -0
  494. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/test_smoke.py +0 -0
  495. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/tools/__init__.py +0 -0
  496. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/tools/test_banned.py +0 -0
  497. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/tools/test_expander.py +0 -0
  498. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/tools/test_invocation.py +0 -0
  499. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/tools/test_loader.py +0 -0
  500. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/tools/test_registry.py +0 -0
  501. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/tools/test_runtime.py +0 -0
  502. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/tools/test_spec.py +0 -0
  503. {gflow_cli-0.23.0 → gflow_cli-0.25.0}/tests/ui/test_app.py +0 -0
@@ -1,7 +1,8 @@
1
1
  # gflow-cli — example environment variables.
2
- # Copy to `.env` in the directory where you invoke `gflow` and uncomment what
3
- # you want to override. ($GFLOW_CLI_HOME is NOT a .env search path only the
4
- # current working directory is loaded.)
2
+ # Copy to `.env` in the directory where you invoke `gflow` (project-local
3
+ # overrides) or to `$GFLOW_CLI_HOME/.env` (machine-wide defaults; used by
4
+ # processes with arbitrary working directories, e.g. the MCP server) and
5
+ # uncomment what you want to override. On conflicts the CWD `.env` wins.
5
6
  # All variables are OPTIONAL — defaults work out of the box for most users.
6
7
  # Lines below are commented to show the SHIPPED DEFAULT — uncomment to override.
7
8
 
@@ -7,6 +7,116 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.25.0] — 2026-07-06
11
+
12
+ ### Fixed
13
+
14
+ - **Follow-up review fixes for remote image UUIDs (#237/#245)**: a post-merge
15
+ multi-angle review surfaced regressions and defects now corrected:
16
+ - Image `i2i` with a Flow media-id ref that isn't in the local catalog is no
17
+ longer rejected — UUID→display-name resolution is applied only to the video
18
+ paths (image refs attach by media id). Restores the `i2i` pass-through.
19
+ - The generation result envelope's `flow_media_id` again carries the real
20
+ media id (it was returning the asset's `flow_workflow_id`); the workflow id
21
+ is exposed under its own `flow_workflow_id` key.
22
+ - An in-catalog asset with no display name no longer returns its raw UUID as
23
+ the picker search term (which timed out); it fails fast with a clear error.
24
+ - Remote picker tiles match the display name exactly (`get_by_role(exact=True)`),
25
+ so a name that is a substring of another can't silently attach the wrong image.
26
+ - The R2V picker-close timeout matches the I2V budget (was a too-tight 8s that
27
+ aborted slow-but-successful attaches).
28
+ - `_attach_reference_audio` selects its tile by ARIA role+name instead of an
29
+ apostrophe-unsafe `:has-text()` selector.
30
+
31
+ - **Remote-UUID video attach reworked to use local upload (#237)**: live
32
+ verification found the original mechanism — resolve the UUID to a display name
33
+ and select its tile in Flow's resource picker — could never work for generated
34
+ media: Flow's asset search does not index generation prompts, and generated
35
+ assets carry no display name, so the picker returned "No results found" and the
36
+ attach timed out. The UUID is now resolved to the image's on-disk local file and
37
+ attached through the existing, already-verified file-upload path. The failing
38
+ picker path is no longer used for video UUID refs. (Automatic download-by-media-id
39
+ for the rare case where the local file was pruned is a planned follow-up; for now
40
+ that case fails fast with a clear "Reference Not On Disk" error.)
41
+
42
+ - **`gflow_generate_image` no longer silently saves a video as an image**: the
43
+ agentic image path has no explicit image-mode toggle — Flow's conversational
44
+ agent infers image-vs-video from the prompt and can produce a *video*, whose
45
+ tile is then scraped as if it were an image. The MP4 bytes were saved with a
46
+ `.png` suffix and catalogued as an image, a silent corruption that only
47
+ surfaced far downstream (Flow 400-rejects the file as an i2v frame → text-only
48
+ #125 fallback). `download_image` now detects video magic bytes (ISO-BMFF / WebM)
49
+ and fails loud with a `WireFormatError` naming the cause, instead of writing the
50
+ corrupt file. (Root cause — the agentic agent producing a video for an image
51
+ request — is tracked separately; this stops the silent corruption.)
52
+
53
+ - **Rejected i2v/r2v frame uploads now fail loud instead of falling back to T2V**:
54
+ `_upload_via_open_dialog` matched the `uploadImage` response by URL only and
55
+ ignored its status, so a Flow 4xx rejection (e.g. an invalid image file) was
56
+ treated as success — the code committed an empty slot and the generation
57
+ silently produced a text-only video (#125). The upload status is now checked and
58
+ a rejection aborts with a clear error.
59
+
60
+ ### Added
61
+
62
+ - **Remote image UUIDs in `gflow_generate_video` (#237)**: I2V (`initial_frame` /
63
+ `end_frame`) and R2V (`reference_images`) now accept a generated image's Flow UUID,
64
+ not just a local file path — pipe the output of an image generation straight into a
65
+ video generation. At enqueue time the UUID is resolved to the image's local file
66
+ (already on disk from the image generation) and attached through the same proven
67
+ file-upload path used for a local `--initial-frame`, so no picker name-search is
68
+ involved. A UUID that isn't in your asset catalog fails fast with a clear "Reference
69
+ Not Found" error, and a catalogued asset whose local file is missing fails fast with
70
+ "Reference Not On Disk" (re-generate it or pass a local path) — both instead of a
71
+ long browser timeout. (Contributed by @C1ph3r404; the attach mechanism was
72
+ reworked during maintainer live-verification — see Fixed below.)
73
+
74
+ ### Fixed
75
+
76
+ - **Removed a shadowed duplicate `Settings.daemon_token` field definition (#243)**: the
77
+ class body defined `daemon_token` twice; Python silently kept only the second
78
+ (aliased) one, leaving the first as dead code that a future edit could touch without
79
+ effect. The surviving definition's contract (both `GFLOW_CLI_DAEMON_TOKEN` and
80
+ `GFLOW_DAEMON_TOKEN` accepted) is now pinned by tests, along with a guard that the
81
+ field is defined exactly once.
82
+
83
+ - **`$GFLOW_CLI_HOME/.env` now loads as a dotenv fallback (#240)**: `config.py`'s own
84
+ module docstring promised a `.env` fallback "from CWD or `$GFLOW_CLI_HOME/.env`", but
85
+ the implementation only ever read the CWD file — a key placed in the home `.env` was
86
+ silently ignored (easy to miss under the prompt tools' never-fatal contract, and it
87
+ bites any process whose CWD is not a project root: the MCP server launched by a
88
+ desktop client, a worker service, a scheduled task). `Settings` now defaults the
89
+ standard pydantic-settings `_env_file` init kwarg to `($GFLOW_CLI_HOME/.env, ./.env)`
90
+ per construction, so explicit `Settings(_env_file=...)` — including the disable idiom
91
+ `_env_file=None` — keeps working. Precedence: process env vars beat both files, and a
92
+ CWD `.env` beats `$GFLOW_CLI_HOME/.env`.
93
+ - **Home resolution is coherent across every channel**: the home used to locate the
94
+ home `.env` now matches what `Settings.home` reports when `GFLOW_CLI_HOME` comes
95
+ from the process env (case-insensitively, as the env source matches it), from a
96
+ `GFLOW_CLI_HOME` entry in the CWD `.env`, or is set-but-empty (treated as unset
97
+ rather than `Path('.')`). The home `.env` itself cannot relocate home (circular).
98
+ - **Docs reconciled**: `docs/CONFIGURATION.md` § ".env loading", `docs/SECURITY.md`
99
+ (Gemini-key locations) and `.env.template` previously documented CWD-only loading
100
+ and now describe the two-file behavior; the `gflow serve` token hint no longer
101
+ points at `.env.local`, which was never a loaded file.
102
+ - **Worker daemon**: `FlowApiClient` constructions in `process_task` now receive the
103
+ daemon's cached settings instead of re-reading `.env` files live per task, so a
104
+ mid-run edit to the home `.env` can no longer produce a task whose client config
105
+ disagrees with the parameters the task derived from `get_settings()`.
106
+
107
+ ## [0.24.0] — 2026-07-01
108
+
109
+ ### Added
110
+
111
+ - **`--project` on `video t2v`/`i2v`/`r2v` (#233)**: generate into an existing Flow
112
+ project instead of always creating a scratch project, matching `image t2i`/`i2i`.
113
+ Lets programmatic callers (e.g. a multi-clip storyboard worker) share one project
114
+ across several video generations instead of leaving one throwaway project per clip.
115
+ - **`project` parameter on the MCP `gflow_generate_image` / `gflow_generate_video`
116
+ tools**: mirrors the CLI `--project` flag so MCP callers can also target an existing
117
+ Flow project (validated against the same id format). Completes `--project` parity
118
+ across the CLI and MCP surfaces.
119
+
10
120
  ## [0.23.0] — 2026-07-01
11
121
 
12
122
  ### Added
@@ -1682,7 +1792,8 @@ shell-script template that branches on these codes.
1682
1792
 
1683
1793
  First skeleton. Not functional end-to-end yet.
1684
1794
 
1685
- [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.23.0...HEAD
1795
+ [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.24.0...HEAD
1796
+ [0.24.0]: https://github.com/ffroliva/gflow-cli/compare/v0.23.0...v0.24.0
1686
1797
  [0.23.0]: https://github.com/ffroliva/gflow-cli/compare/v0.22.0...v0.23.0
1687
1798
  [0.22.0]: https://github.com/ffroliva/gflow-cli/compare/v0.21.0...v0.22.0
1688
1799
  [0.21.0]: https://github.com/ffroliva/gflow-cli/compare/v0.20.1...v0.21.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gflow-cli
3
- Version: 0.23.0
3
+ Version: 0.25.0
4
4
  Summary: Unofficial CLI for Google Flow — drive Veo image-to-video generations from the terminal.
5
5
  Project-URL: Homepage, https://github.com/ffroliva/gflow-cli
6
6
  Project-URL: Issues, https://github.com/ffroliva/gflow-cli/issues
@@ -312,9 +312,11 @@ predictable external storage keys, set the bucket prefix in
312
312
 
313
313
  ## .env loading
314
314
 
315
- `gflow-cli` (via [`pydantic-settings`](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)) loads a single `.env` from the **current working directory** at startup. There is no second load from `$GFLOW_CLI_HOME` keep your `.env` next to where you invoke `gflow`.
315
+ `gflow-cli` (via [`pydantic-settings`](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)) loads **two** `.env` files at startup: `$GFLOW_CLI_HOME/.env` (machine-wide defaults — useful for processes whose working directory is arbitrary, like the MCP server or a worker service) and a `.env` in the **current working directory** (project-local overrides). On conflicting keys the CWD file wins.
316
316
 
317
- Variables already set in the actual environment always beat any `.env` file. Anything explicitly passed on the CLI beats everything else.
317
+ The home used for the first file is resolved from the `GFLOW_CLI_HOME` env var, else a `GFLOW_CLI_HOME` entry in the CWD `.env`, else the platform default — the same home `Settings.home` reports. (By construction the home `.env` cannot relocate home itself; set the env var or the CWD `.env` instead.)
318
+
319
+ Variables already set in the actual environment always beat both `.env` files. Anything explicitly passed on the CLI beats everything else.
318
320
 
319
321
  Use [`.env.template`](../.env.template) as your starting point:
320
322
 
@@ -117,7 +117,7 @@ Slash commands for Claude Code, stored in `.claude/commands/gflow/`. All prefixe
117
117
  **"A gflow command hangs / fails — where do I start?"** → [DEBUGGING § Quick reference](DEBUGGING.md#quick-reference)
118
118
  **"Flow's UI broke a selector — how do I diagnose it?"** → [DEBUGGING § Inspecting Flow's live UI](DEBUGGING.md#inspecting-flows-live-ui)
119
119
  **"What does each `ui_automation.*` log event mean?"** → [DEBUGGING § Listener & HTTP-layer debugging](DEBUGGING.md#listener--http-layer-debugging)
120
- **"What was actually live-verified for the latest release?"** → latest: [LIVE_VERIFICATION_v0.23.0](LIVE_VERIFICATION_v0.23.0.md) (MCP generation wiring proven live end-to-end — tool→worker→real Flow REST→structured-error translation; final image-write blocked by an expired session, environmental. #222 macOS fix reporter-verified e2e on Apple Silicon). Prior: [v0.22.0](LIVE_VERIFICATION_v0.22.0.md) (Tools framework — automated/CI coverage complete; credit/key-gated live feature run is a pending owner gate, see the doc) · [v0.21.0](LIVE_VERIFICATION_v0.21.0.md) (MCP server over stdio + HTTP/SSE — credit-free protocol handshake; 4 tools / 2 prompts / 3 resources confirmed on stdout) · [v0.20.1](LIVE_VERIFICATION_v0.20.1.md) · [v0.20.0](LIVE_VERIFICATION_v0.20.0.md) · [v0.19.0](LIVE_VERIFICATION_v0.19.0.md) · [v0.18.0](LIVE_VERIFICATION_v0.18.0.md) · [v0.17.0](LIVE_VERIFICATION_v0.17.0.md) · [v0.16.0](LIVE_VERIFICATION_v0.16.0.md) · [v0.13.0](LIVE_VERIFICATION_v0.13.0.md) · [v0.12.0](LIVE_VERIFICATION_v0.12.0.md) · [v0.11.0](LIVE_VERIFICATION_v0.11.0.md) · [v0.10.0](LIVE_VERIFICATION_v0.10.0.md) · [v0.9.1](LIVE_VERIFICATION_v0.9.1.md) · [v0.9.0](LIVE_VERIFICATION_v0.9.0.md) · [v0.8.1](LIVE_VERIFICATION_v0.8.1.md) · [v0.7.0](LIVE_VERIFICATION_v0.7.0.md)
120
+ **"What was actually live-verified for the latest release?"** → latest: [LIVE_VERIFICATION_v0.25.0](LIVE_VERIFICATION_v0.25.0.md) (**#237 remote-UUID i2v proven live e2e GREEN** — a real 8s 720×1280 interpolation from a generated image's UUID, after the picker-search attach was reworked to local upload; #240 home-`.env` matrix live; plus two silent-failure guards root-caused live: video-as-image download rejection and rejected-upload fail-loud). Prior: [v0.24.0](LIVE_VERIFICATION_v0.24.0.md) (--project parity across CLI + MCP — automated coverage; live gen auth-gated). Prior: [v0.23.0](LIVE_VERIFICATION_v0.23.0.md) (MCP generation wiring proven live end-to-end — tool→worker→real Flow REST→structured-error translation; final image-write blocked by an expired session, environmental. #222 macOS fix reporter-verified e2e on Apple Silicon). Prior: [v0.22.0](LIVE_VERIFICATION_v0.22.0.md) (Tools framework — automated/CI coverage complete; credit/key-gated live feature run is a pending owner gate, see the doc) · [v0.21.0](LIVE_VERIFICATION_v0.21.0.md) (MCP server over stdio + HTTP/SSE — credit-free protocol handshake; 4 tools / 2 prompts / 3 resources confirmed on stdout) · [v0.20.1](LIVE_VERIFICATION_v0.20.1.md) · [v0.20.0](LIVE_VERIFICATION_v0.20.0.md) · [v0.19.0](LIVE_VERIFICATION_v0.19.0.md) · [v0.18.0](LIVE_VERIFICATION_v0.18.0.md) · [v0.17.0](LIVE_VERIFICATION_v0.17.0.md) · [v0.16.0](LIVE_VERIFICATION_v0.16.0.md) · [v0.13.0](LIVE_VERIFICATION_v0.13.0.md) · [v0.12.0](LIVE_VERIFICATION_v0.12.0.md) · [v0.11.0](LIVE_VERIFICATION_v0.11.0.md) · [v0.10.0](LIVE_VERIFICATION_v0.10.0.md) · [v0.9.1](LIVE_VERIFICATION_v0.9.1.md) · [v0.9.0](LIVE_VERIFICATION_v0.9.0.md) · [v0.8.1](LIVE_VERIFICATION_v0.8.1.md) · [v0.7.0](LIVE_VERIFICATION_v0.7.0.md)
121
121
  **"Where is the reverse-engineered wire protocol for a feature?"** → the `*_RECON.md` design docs: [CHARACTER_RECON](CHARACTER_RECON.md) (Flow character entity protocol), [IMAGE_UPSCALE_RECON](IMAGE_UPSCALE_RECON.md) (`/v1/flow/upsampleImage` wire). Naming convention: one `<FEATURE>_RECON.md` per reverse-engineered surface, kept as the durable spec after the feature ships.
122
122
  **"What was live-verified for the data layer (PR #58)?"** → [LIVE_VERIFICATION_data_layer](LIVE_VERIFICATION_data_layer.md) — 1 Imagen + 1 Veo credit on denon82, 6-layer ledger (file + magic + Pillow + DB rows + CLI round-trip + structlog)
123
123
  **"What was live-verified for the video-download feature (#29)?"** → [LIVE_VERIFICATION_video_download](LIVE_VERIFICATION_video_download.md)
@@ -0,0 +1,38 @@
1
+ # Live Verification — v0.24.0
2
+
3
+ Release date: 2026-07-01. This release completes `--project` parity: `video
4
+ t2v/i2v/r2v` gain `--project` (#233/#234) and the MCP `gflow_generate_image` /
5
+ `gflow_generate_video` tools gain a `project` parameter (#235) — both let a caller
6
+ target an existing Flow project instead of a scratch one.
7
+
8
+ ## Scope
9
+
10
+ | Change | Surface | Verification |
11
+ |---|---|---|
12
+ | **#234** — `--project` on `video t2v/i2v/r2v` (CLI) | `cli_video.py`, `_cli_helpers.py` | ✅ Automated — behavior tests assert the id threads to `generate_video(project_id=...)` for all three modes; default (no flag) → scratch project; bad id rejected at the CLI boundary. Full council review GREEN + Sonar 100% new-coverage. |
13
+ | **#235** — `project` param on MCP generate tools | `mcp/tools.py` | ✅ Automated — payload-threading tests assert `project` reaches `payload["project_id"]` (image + video), omitted → no `project_id`, bad id rejected before the worker. Reuses the CLI `_FLOW_ID_RE` validator. Council GREEN + Sonar pass. |
14
+
15
+ ## Nature of the change (why automated coverage is sufficient here)
16
+
17
+ Neither change adds new generation plumbing: the worker/daemon already consumed
18
+ `payload["project_id"]` (daemon.py:97 image, :168 video) and `FlowApiClient.generate_video`
19
+ already accepted `project_id`. Both PRs only **surface + validate** the existing
20
+ capability at the CLI and MCP boundaries, and thread it into the already-wired payload.
21
+ The end-to-end "generate into an existing project" path (browser navigation to
22
+ `project_editor_url(locale, project_id)` → `entering_existing_project`) is the same code
23
+ prior releases exercised live for `image t2i --project`.
24
+
25
+ ## Live generation status
26
+
27
+ A live credit-free run of `--project` against real Flow was **not** performed this cycle
28
+ because the available `denon82` profile's Flow session is server-side expired (HTTP 401 —
29
+ see [LIVE_VERIFICATION_v0.23.0](LIVE_VERIFICATION_v0.23.0.md)); exercising it requires an
30
+ interactive `gflow auth login`. The project-targeting code path is shared with the
31
+ already-live-verified `image t2i --project` path, and is fully covered by the automated
32
+ behavior tests above.
33
+
34
+ ## Automated coverage
35
+
36
+ - Full suite green on both PRs' CI (test matrix 3.11/3.12/3.13) at the merged tree.
37
+ - `pyright src`: 0 errors. `ruff check` / `ruff format --check`: clean.
38
+ - SonarCloud gate green on both PRs (#234 new-coverage 100%; #235 pass).
@@ -0,0 +1,97 @@
1
+ # Live Verification — v0.25.0
2
+
3
+ Release date: 2026-07-06. Headline change: **remote image UUIDs in
4
+ `gflow_generate_video`** (#237), plus the `$GFLOW_CLI_HOME/.env` dotenv fallback
5
+ (#240 — the minor-bump reason) and the shadowed-duplicate `Settings.daemon_token`
6
+ removal (#243). Live verification of the #237 attach found — and this cycle fixed —
7
+ that the originally-merged mechanism could not work, and surfaced two pre-existing
8
+ silent-failure guards that are now fixed too.
9
+
10
+ All live runs: 2026-07-06, headed Playwright, profile `ffroliva`, against real Flow.
11
+
12
+ ## Scope
13
+
14
+ | Change | Surface | Verdict |
15
+ |---|---|---|
16
+ | **#237** — UUID image refs in `gflow_generate_video` | `mcp/tools.py`, `paths.py` | ✅ **Live e2e GREEN** after the attach was reworked (below) |
17
+ | **#240** — `$GFLOW_CLI_HOME/.env` fallback | `config.py` | ✅ Live CLI precedence matrix + pinning tests |
18
+ | **#243** — duplicate `daemon_token` removed | `config.py` | ✅ Automated (`tests/test_config.py`) — internal fix, no live surface |
19
+ | Hardening — video-as-image download guard | `api/client.py`, `paths.py` | ✅ Unit-verified; root-caused live |
20
+ | Hardening — rejected-upload fail-loud | `ui_automation_video.py` | ✅ Unit-verified; root-caused live |
21
+
22
+ ## #237 — remote image UUIDs → video (the rework)
23
+
24
+ **The originally-merged mechanism was broken.** It resolved the UUID to a *display
25
+ name* and searched Flow's resource picker for the tile. Instrumented live
26
+ diagnostics (picker aria-tree + screenshots) proved generated media never appear
27
+ in that picker: Flow's asset search does not index generation prompts, and
28
+ generated assets carry no display name (0 of 190 catalogued assets had one), so
29
+ the picker returned **"No results found"** and every attach timed out — in scratch
30
+ projects and in the asset's own project alike.
31
+
32
+ **Fix (this cycle):** the UUID is resolved to the image's on-disk local file
33
+ (already saved by the image generation) and attached through the same proven
34
+ file-upload path used for a local `--initial-frame`. No picker name-search.
35
+
36
+ ### Live end-to-end result — GREEN
37
+
38
+ `gflow_generate_video(mode="i2v", initial_frame="<generated-image-UUID>", …)`
39
+ driven through the **real stdio MCP server** (`gflow mcp run`), start frame a
40
+ generated image (valid JPEG, `60dcb880…`). 5-layer ledger:
41
+
42
+ 1. **File count**: exactly one MP4 written (`d7749780-…-2ae354.mp4`).
43
+ 2. **Magic bytes**: `00 00 00 20 66 74 79 70 69 73 6f 6d` (`ftypisom`, valid ISO-BMFF MP4), 5.30 MB.
44
+ 3. **Shape**: `ffprobe` → h264, **720×1280** (9:16 as requested), duration **8.0 s**.
45
+ 4. **Structlog / wire invariants**: upload `status: 200`; generate route
46
+ **`batchAsyncGenerateVideoStartImage`** (the true i2v route, **not** the T2V
47
+ `batchAsyncGenerateVideoText` route); captured `startImage` bound; task
48
+ `status: completed`.
49
+ 5. **User-confirmable artifact**: a mid-clip frame shows the wooden **"v0.25.0"**
50
+ sign *animating* (drifting dust, camera push-in, "Veo" watermark) — a genuine
51
+ interpolation of the still start frame.
52
+
53
+ ### Fail-fast paths (also live-verified, credit-free)
54
+
55
+ - Unknown UUID → RFC 9457 **`Reference Not Found`** in ~1.5 s via the real MCP
56
+ server (no browser, no timeout).
57
+ - Catalogued asset with no on-disk file → **`Reference Not On Disk`** (re-generate
58
+ or pass a local path; auto download-by-media-id is a planned follow-up).
59
+
60
+ ## #240 — `$GFLOW_CLI_HOME/.env` fallback (live CLI matrix)
61
+
62
+ Marker `GFLOW_CLI_DB_PATH` observed via `gflow data list images` from a foreign
63
+ CWD: home-`.env` only loads ✅; CWD `.env` beats home ✅; process env beats both ✅;
64
+ set-but-empty `GFLOW_CLI_HOME` treated as unset (default-home `.env` still loads)
65
+ ✅. Pinned by `tests/test_config.py`.
66
+
67
+ ## Hardening — two silent-failure guards (root-caused during this verification)
68
+
69
+ The first e2e attempts failed at the frame upload with a confusing i2v→T2V (#125)
70
+ fallback. Root cause was **not** the pipeline: the "image" fed as the start frame
71
+ (`f94bdd3f…_1.png`) was actually an **MP4 video** — its magic bytes are `ftypisom`.
72
+
73
+ 1. **`gflow_generate_image` produced a video-as-`.png`.** The agentic image path
74
+ has no explicit image-mode toggle (`switch_to_image_mode` is a no-op) — Flow's
75
+ conversational agent infers image-vs-video from the prompt and produced a video,
76
+ whose tile `await_images` scraped as an image. The MP4 bytes were saved `.png`
77
+ (`extension_from_magic` only knows image formats) and catalogued as an image.
78
+ **Fix:** `download_image` now rejects video magic bytes (`looks_like_video`:
79
+ ISO-BMFF / WebM) with a `WireFormatError` instead of writing the corrupt file.
80
+ 2. **Rejected uploads were treated as success.** `_upload_via_open_dialog` matched
81
+ the `uploadImage` response by URL only and ignored its status, so a Flow **400**
82
+ (Flow correctly rejecting the non-image bytes) committed an empty slot → T2V
83
+ fallback. **Fix:** the upload status is checked (`_upload_rejection_message`) and
84
+ a 4xx aborts loudly.
85
+
86
+ Both are pre-existing (present in 0.24.0) and unit-tested. The underlying "agentic
87
+ agent produces a video for an image request" is tracked as a separate follow-up;
88
+ these guards convert the resulting silent corruption into a clear, actionable error.
89
+
90
+ ## Automated coverage
91
+
92
+ - `pyright src`: 0 errors. `ruff check` / `ruff format --check`: clean.
93
+ `check_doc_links.py`, `check_repo_hygiene.py`: clean.
94
+ - New unit tests: UUID→local-path resolution + fail-fast cases (`tests/mcp`),
95
+ `looks_like_video` + `download_image` video rejection (`tests/test_paths.py`,
96
+ `tests/api/test_client_image.py`), `_upload_rejection_message`
97
+ (`tests/api/transports/test_ui_automation_video.py`).
@@ -45,8 +45,8 @@ Both Click CLI (`src/gflow_cli/cli.py`) and MCP Server (`src/gflow_cli/mcp/`) ar
45
45
  The server registers three protocol surfaces:
46
46
 
47
47
  ### Tools (Executable actions)
48
- * `gflow_generate_image(prompt, model, aspect, count, seed, reference_images, tools, profile)`: Triggers text-to-image / image-to-image (Imagen / Nano Banana). `reference_images` switches to i2i.
49
- * `gflow_generate_video(prompt, mode, aspect, initial_frame, end_frame, reference_images, tools, profile)`: Triggers vertical or landscape video generation (Veo). `mode` is `t2v`/`i2v`/`r2v`; `i2v` requires `initial_frame`, `r2v` requires `reference_images`.
48
+ * `gflow_generate_image(prompt, model, aspect, count, seed, reference_images, tools, profile, project)`: Triggers text-to-image / image-to-image (Imagen / Nano Banana). `reference_images` switches to i2i; `project` generates into an existing Flow project id (mirrors CLI `--project`).
49
+ * `gflow_generate_video(prompt, mode, aspect, initial_frame, end_frame, reference_images, tools, profile, project)`: Triggers vertical or landscape video generation (Veo). `mode` is `t2v`/`i2v`/`r2v`; `i2v` requires `initial_frame`, `r2v` requires `reference_images`; `project` generates into an existing Flow project id (mirrors CLI `--project`). `initial_frame`, `end_frame`, and `reference_images` each accept **either a local file path or the Flow image UUID of a generated asset** — pass a generated image's id straight in to chain image→video, and gflow attaches it for you (the UUID is resolved to the asset's already-on-disk local file and uploaded as the frame; no manual download/re-upload step). A UUID that isn't in your local asset catalog is rejected up front with a clear "Reference Not Found" error; a catalogued asset whose local file is no longer on disk gives a "Reference Not On Disk" error (re-generate it or pass a local path).
50
50
  * `gflow_list_projects(profile, limit)`: Queries SQLite catalog for recent generation folders.
51
51
  * `gflow_list_characters(profile)`: Lists Flow Character entities (requires an active browser session).
52
52
 
@@ -4,6 +4,19 @@
4
4
 
5
5
  ## Current release
6
6
 
7
+ **v0.24.0 — alpha.** **`--project` parity across CLI + MCP.** The video commands
8
+ (`video t2v`/`i2v`/`r2v`) gain `--project <id>` to generate into an existing Flow project
9
+ instead of a scratch one (#233/#234), matching `image t2i`/`i2i`; and the MCP
10
+ `gflow_generate_image` / `gflow_generate_video` tools gain a matching `project` parameter
11
+ (#235), so agent callers get the same capability. Both surface an already-wired worker
12
+ capability (`payload["project_id"]`) and validate the id identically. Carries forward
13
+ v0.23.0 (MCP generation live + macOS 401 fix). Verification:
14
+ [LIVE_VERIFICATION_v0.24.0](LIVE_VERIFICATION_v0.24.0.md).
15
+
16
+ **Develop (unreleased, post-v0.24.0):** *(empty — develop is the staging branch for the next release).*
17
+
18
+ <details><summary>v0.23.0 — MCP generation live + macOS 401 fixed</summary>
19
+
7
20
  **v0.23.0 — alpha.** **MCP generation goes live + macOS 401 fixed.** The MCP server's
8
21
  `gflow_generate_image` / `gflow_generate_video` tools — previously non-functional stubs —
9
22
  are now wired end-to-end to the FlowWorker queue (background worker owns download +
@@ -16,7 +29,7 @@ Carries forward v0.22.0 (Tools framework) + v0.21.0 (MCP server). Verification:
16
29
  [LIVE_VERIFICATION_v0.23.0](LIVE_VERIFICATION_v0.23.0.md) (MCP wiring proven live; #222
17
30
  reporter-verified e2e on macOS).
18
31
 
19
- **Develop (unreleased, post-v0.23.0):** *(empty — develop is the staging branch for the next release).*
32
+ </details>
20
33
 
21
34
  <details><summary>v0.22.0 — Tools framework ("Creative Director")</summary>
22
35
 
@@ -39,7 +39,7 @@
39
39
 
40
40
  Not used by v0.4.0a2's reverse-engineered Flow provider. Documented here in advance of `GFLOW_CLI_PROVIDER=official`.
41
41
 
42
- - **Location:** `$GFLOW_CLI_GEMINI_API_KEY` env var, optionally loaded from a `.env` file in the directory where you invoke `gflow` (CWD only `$GFLOW_CLI_HOME` is not a `.env` search path; see [CONFIGURATION.md](CONFIGURATION.md)).
42
+ - **Location:** `$GFLOW_CLI_GEMINI_API_KEY` env var, optionally loaded from a `.env` file in the directory where you invoke `gflow` or from `$GFLOW_CLI_HOME/.env` (CWD wins on conflicts; see [CONFIGURATION.md](CONFIGURATION.md#env-loading)). Treat BOTH locations as secret-bearing files: keep `$GFLOW_CLI_HOME/.env` user-readable only and out of shared images/backups.
43
43
  - **In memory:** Held only in the `Settings` dataclass, never logged.
44
44
  - **In transit:** Sent only to `generativelanguage.googleapis.com` over HTTPS.
45
45
  - **Rotate:** Set a new value in `.env`, restart the CLI. No persistence beyond the env var.
@@ -438,7 +438,11 @@ All prompts in a batch share one Flow project. The editor is opened once; each p
438
438
  Generate a video from a text prompt only.
439
439
 
440
440
  ```text
441
- gflow video t2v PROMPT [--model] [--duration] [--count] [--aspect] [--profile] [-t/--tool] [--out-dir]
441
+ gflow video t2v PROMPT [--model] [--duration] [--count] [--aspect] [--profile] [-t/--tool] [--project] [--out-dir]
442
+
443
+ Options:
444
+ --project ID Generate in this EXISTING Flow project instead of a
445
+ scratch project (see "Sharing one project across calls").
442
446
  ```
443
447
 
444
448
  ```bash
@@ -472,6 +476,8 @@ Arguments:
472
476
  Options:
473
477
  --initial-frame PATH Initial frame to animate. Canonical form; replaces the positional IMAGE.
474
478
  --end-frame PATH Optional end frame — Flow interpolates initial frame -> end frame.
479
+ --project ID Generate in this EXISTING Flow project instead of a
480
+ scratch project (see "Sharing one project across calls").
475
481
  ```
476
482
 
477
483
  ```bash
@@ -491,7 +497,9 @@ images. Per-model cap: `omni-flash` ≤7, the `veo-*` models ≤3. Fires
491
497
  gflow video r2v PROMPT --ref IMG [--ref IMG ...] [--model] [--duration] [--count] [--aspect] [...]
492
498
 
493
499
  Options:
494
- --ref PATH Reference image; repeat for up to 7 (omni-flash) / 3 (veo). [required]
500
+ --ref PATH Reference image; repeat for up to 7 (omni-flash) / 3 (veo). [required]
501
+ --project ID Generate in this EXISTING Flow project instead of a scratch
502
+ project (see "Sharing one project across calls").
495
503
  ```
496
504
 
497
505
  ```bash
@@ -499,6 +507,19 @@ gflow video r2v "a knight in this armor walks forward" --ref armor.png
499
507
  gflow video r2v "blend these worlds" --ref a.png --ref b.png --ref c.png --model omni-flash
500
508
  ```
501
509
 
510
+ ### Sharing one project across calls
511
+
512
+ By default each `video t2v` / `i2v` / `r2v` call creates its own scratch Flow
513
+ project. Pass `--project <id>` (same contract as `image t2i`/`i2i` — see
514
+ [`gflow image t2i`](#gflow-image-t2i)) to generate into an existing project
515
+ instead, e.g. to avoid one-throwaway-project-per-clip when scripting a
516
+ multi-clip storyboard:
517
+
518
+ ```bash
519
+ gflow video t2v "establishing shot" --project PROJ123
520
+ gflow video t2v "close-up reaction" --project PROJ123
521
+ ```
522
+
502
523
  ## `gflow video batch`
503
524
 
504
525
  > ⚠️ **Not yet implemented.** The `batch` subcommand currently exits with
@@ -509,10 +530,12 @@ gflow video r2v "blend these worlds" --ref a.png --ref b.png --ref c.png --model
509
530
  ### Workaround — shell for-loop
510
531
 
511
532
  Until the manifest runner lands, you can drive sequential video generations
512
- through a plain shell loop. Each `gflow video t2v` / `i2v` / `r2v` call opens
513
- its **own Flow project**, so the resulting videos will NOT share a
514
- `project_id` (unlike `gflow image batch`, which mounts one project across
515
- all prompts) — but they DO get generated and downloaded:
533
+ through a plain shell loop. Without `--project`, each `gflow video t2v` /
534
+ `i2v` / `r2v` call opens its **own Flow project**, so the resulting videos
535
+ will NOT share a `project_id` (unlike `gflow image batch`, which mounts one
536
+ project across all prompts) — but they DO get generated and downloaded. Pass
537
+ the same `--project <id>` to every call in the loop (see "Sharing one project
538
+ across calls" above) if you want them to land in one project instead:
516
539
 
517
540
  ```bash
518
541
  # bash / WSL / macOS — one prompt per line
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "gflow-cli"
3
- version = "0.23.0"
3
+ version = "0.25.0"
4
4
  description = "Unofficial CLI for Google Flow — drive Veo image-to-video generations from the terminal."
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -1,3 +1,3 @@
1
1
  """gflow-cli — unofficial CLI for Google Flow."""
2
2
 
3
- __version__ = "0.23.0"
3
+ __version__ = "0.25.0"
@@ -35,6 +35,7 @@ been removed. Both error handlers now import
35
35
 
36
36
  from __future__ import annotations
37
37
 
38
+ import re
38
39
  import sys
39
40
  from pathlib import Path
40
41
  from typing import TYPE_CHECKING, Any, Literal
@@ -70,16 +71,36 @@ _console = Console()
70
71
  # `reportPrivateUsage` rule does NOT honor the PEP 484 `from X import Y as Y`
71
72
  # re-export idiom for underscore names, so __all__ is the practical fix.
72
73
  __all__ = [
74
+ "_FLOW_ID_RE",
73
75
  "_handle_gflow_error",
74
76
  "_handle_unhandled_error",
75
77
  "_make_provider_dir",
76
78
  "_resolve_profile",
79
+ "_validate_project_id",
77
80
  "apply_tool_option",
78
81
  "run_with_handlers",
79
82
  "safe_path_text",
80
83
  "tool_option",
81
84
  ]
82
85
 
86
+ # Flow project ids are interpolated into navigation URLs and CSS selectors
87
+ # (page.goto, `data-tile-id='fe_id_<id>'`) before any other guard runs, so the
88
+ # `--project` option on both `image t2i`/`i2i` and `video t2v`/`i2v`/`r2v`
89
+ # validates against this allowlist at the CLI boundary. Mirrors
90
+ # `routes._PROJECT_ID_RE`. Relocated here (T4b follow-up) so the two call-site
91
+ # modules can't drift out of sync.
92
+ _FLOW_ID_RE = re.compile(r"^[A-Za-z0-9\-]{1,128}$")
93
+
94
+
95
+ def _validate_project_id(
96
+ _ctx: click.Context, param: click.Parameter, value: str | None
97
+ ) -> str | None:
98
+ """Reject a --project id that isn't alphanumeric/hyphen (1-128 chars)."""
99
+ if value is not None and not _FLOW_ID_RE.fullmatch(value):
100
+ msg = "project id must be 1-128 chars of letters, digits, or hyphens."
101
+ raise click.BadParameter(msg, param=param)
102
+ return value
103
+
83
104
 
84
105
  _TOOL_OPTION_HELP = (
85
106
  "Apply a prompt tool before generating, e.g. --tool creative-director or "
@@ -64,7 +64,7 @@ from gflow_cli.errors import (
64
64
  WafRejectionError,
65
65
  WireFormatError,
66
66
  )
67
- from gflow_cli.paths import adjust_key_extension, character_output_path
67
+ from gflow_cli.paths import adjust_key_extension, character_output_path, looks_like_video
68
68
  from gflow_cli.storage import AnyPath, storage_path, write_asset_async
69
69
 
70
70
  if TYPE_CHECKING:
@@ -1097,6 +1097,24 @@ class FlowApiClient:
1097
1097
  _raise_for_non_retryable(resp, await resp.text(), route=route)
1098
1098
  body = await resp.body()
1099
1099
 
1100
+ # Fail loud if an image request downloaded video content. The agentic
1101
+ # gflow_generate_image path has no explicit image-mode toggle — Flow's
1102
+ # conversational agent infers image-vs-video from the prompt and can
1103
+ # produce a video, whose tile await_images then scrapes as if it were an
1104
+ # image. Saving those bytes with an image suffix is a silent corruption
1105
+ # that only surfaces far downstream (e.g. Flow 400-rejects the file as an
1106
+ # i2v frame -> #125 text-only fallback). Catch it at the download.
1107
+ if looks_like_video(body):
1108
+ raise WireFormatError(
1109
+ detail=(
1110
+ "image download returned video content (ISO-BMFF/WebM magic "
1111
+ "bytes) — the agentic conversational agent likely produced a "
1112
+ "video instead of an image. Use a Classic UI profile "
1113
+ "(GFLOW_CLI_PREFER_CLASSIC=1) or rephrase the prompt."
1114
+ ),
1115
+ route=route,
1116
+ )
1117
+
1100
1118
  # Resolve the write target: local Path or cloud UPath.
1101
1119
  # Compute a relative key from out_path so cloud keys mirror the local
1102
1120
  # directory structure (images/YYYY-MM-DD/media_id_N.ext).