gflow-cli 0.14.0__tar.gz → 0.15.1__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 (400) hide show
  1. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/AGENTS.md +3 -1
  2. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/CHANGELOG.md +53 -1
  3. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/PKG-INFO +10 -10
  4. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/README.md +8 -8
  5. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/INDEX.md +6 -1
  6. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/PROJECT_STATUS.md +4 -2
  7. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/USAGE.md +45 -0
  8. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/pyproject.toml +3 -3
  9. gflow_cli-0.15.1/scripts/diag/README.md +29 -0
  10. gflow_cli-0.14.0/scripts/diag_capture_flow_traffic.py → gflow_cli-0.15.1/scripts/diag/capture_flow_traffic.py +1 -1
  11. gflow_cli-0.15.1/scripts/diag/memory_profile.py +235 -0
  12. gflow_cli-0.14.0/scripts/diag_recaptcha_mint.py → gflow_cli-0.15.1/scripts/diag/recaptcha_mint.py +1 -1
  13. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/__init__.py +1 -1
  14. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/client.py +1 -1
  15. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/image.py +18 -2
  16. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/ui_automation.py +127 -0
  17. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/ui_automation_video.py +26 -6
  18. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_image.py +155 -13
  19. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/recorder.py +6 -1
  20. gflow_cli-0.15.1/tests/api/test_client_launch_kwargs.py +77 -0
  21. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_image.py +58 -0
  22. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_ui_automation.py +166 -0
  23. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_ui_automation_video.py +26 -1
  24. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_image.py +289 -0
  25. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/dev/test_recording_client.py +4 -1
  26. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_image_steps.py +1 -0
  27. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/uv.lock +25 -25
  28. gflow_cli-0.14.0/tests/api/test_client_launch_kwargs.py +0 -35
  29. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/README.md +0 -0
  30. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/active.md +0 -0
  31. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/branch-review.md +0 -0
  32. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/changelog.md +0 -0
  33. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/check.md +0 -0
  34. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/doc-review.md +0 -0
  35. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/known-issues.md +0 -0
  36. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/next.md +0 -0
  37. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/plan.md +0 -0
  38. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/pr-council-review.md +0 -0
  39. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/predict.md +0 -0
  40. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/release.md +0 -0
  41. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/scenario.md +0 -0
  42. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/status.md +0 -0
  43. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.continue-here.md +0 -0
  44. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.env.template +0 -0
  45. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.gitattributes +0 -0
  46. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/CODEOWNERS +0 -0
  47. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  48. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/copilot-instructions.md +0 -0
  49. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/dependabot.yml +0 -0
  50. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/workflows/ci.yml +0 -0
  51. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/workflows/external-pr-triage.yml +0 -0
  52. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/workflows/governance-advisory.yml +0 -0
  53. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/workflows/governance-benchmark.yml +0 -0
  54. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/workflows/release.yml +0 -0
  55. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.gitignore +0 -0
  56. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.gitleaks.toml +0 -0
  57. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.pre-commit-config.yaml +0 -0
  58. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.secrets.baseline +0 -0
  59. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/CLAUDE.md +0 -0
  60. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/CONFIGURATION.md +0 -0
  61. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/CONTRIBUTING.md +0 -0
  62. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/DISCLAIMER.md +0 -0
  63. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/GEMINI.md +0 -0
  64. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/KNOWN_ISSUES.md +0 -0
  65. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/LICENSE +0 -0
  66. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/PLAN.md +0 -0
  67. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/PR162_MOVIE_CHARACTER_REVIEW.md +0 -0
  68. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/RELEASE.md +0 -0
  69. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/ROADMAP.md +0 -0
  70. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/conftest.py +0 -0
  71. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docker-compose.yml +0 -0
  72. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/AGENT_GUIDE.md +0 -0
  73. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/ARCHITECTURE.md +0 -0
  74. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/AUTHENTICATION.md +0 -0
  75. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/CHARACTER.md +0 -0
  76. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/CHARACTER_RECON.md +0 -0
  77. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/CONFIGURATION.md +0 -0
  78. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/DATA_LAYER.md +0 -0
  79. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/DEBUGGING.md +0 -0
  80. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/DEMOS.md +0 -0
  81. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/DEVELOPMENT.md +0 -0
  82. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/E2E_TESTING.md +0 -0
  83. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/EXTERNAL_STORAGE.md +0 -0
  84. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/GITHUB.md +0 -0
  85. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/GOVERNANCE_BENCHMARK.md +0 -0
  86. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_data_layer.md +0 -0
  87. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_image_batch.md +0 -0
  88. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.10.0.md +0 -0
  89. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.11.0.md +0 -0
  90. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.12.0.md +0 -0
  91. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.13.0.md +0 -0
  92. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.7.0.md +0 -0
  93. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.8.1.md +0 -0
  94. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.9.0.md +0 -0
  95. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.9.1.md +0 -0
  96. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_video_download.md +0 -0
  97. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/MOVIE.md +0 -0
  98. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/SECURITY.md +0 -0
  99. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/USER_GUIDE.md +0 -0
  100. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/assets/demo-split-pf.gif +0 -0
  101. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/assets/example-run.gif +0 -0
  102. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/schemas/movie-handoff.schema.json +0 -0
  103. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/2026-05-17-issue-15-handover.md +0 -0
  104. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/character-scenario.md +0 -0
  105. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/plans/2026-06-01-governance-enforcement-advisory/PLAN.md +0 -0
  106. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/plans/2026-06-04-character-create-recording.md +0 -0
  107. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/plans/2026-06-06-movie-p0-asyncio-hotfix.md +0 -0
  108. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/plans/2026-06-06-movie-p1-composition-manifest.md +0 -0
  109. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/plans/2026-06-06-movie-p2-native-identity-voice.md +0 -0
  110. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/specs/2026-06-06-movie-consistency-design.md +0 -0
  111. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +0 -0
  112. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/README.md +0 -0
  113. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/batch_from_config.py +0 -0
  114. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/multi_prompt_t2i.py +0 -0
  115. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/sample_config.json +0 -0
  116. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/sample_prompts.txt +0 -0
  117. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/single_image_t2i.py +0 -0
  118. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/workflow_chain.py +0 -0
  119. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/llms.txt +0 -0
  120. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/README.md +0 -0
  121. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/01_upload_image.json +0 -0
  122. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
  123. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
  124. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/04_archive_workflow.json +0 -0
  125. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/05_createProject.json +0 -0
  126. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/06_batchGenerateImages.json +0 -0
  127. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
  128. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/08_batchAsyncGenerateVideoStartAndEndImage.json +0 -0
  129. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/09_batchAsyncGenerateVideoReferenceImages.json +0 -0
  130. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/10_batchCheckAsyncVideoGenerationStatus_successful.json +0 -0
  131. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/11_batchCheckAsyncVideoGenerationStatus_failed.json +0 -0
  132. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/12_create_scene.json +0 -0
  133. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/13_sceneWorkflows_update.json +0 -0
  134. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/14_get_scene_workflows.json +0 -0
  135. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/15_commit_flowWorkflow.json +0 -0
  136. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/ci/check_doc_links.py +0 -0
  137. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/ci/check_materiality.py +0 -0
  138. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/ci/check_repo_hygiene.py +0 -0
  139. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/debug_editor.py +0 -0
  140. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/debug_gen_settings.py +0 -0
  141. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/debug_settings.py +0 -0
  142. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/_recording_client.py +0 -0
  143. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/_spike_common.py +0 -0
  144. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/active_plan.py +0 -0
  145. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/capture_i2v_frame_slots_dom.py +0 -0
  146. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/capture_i2v_intercept_submit.py +0 -0
  147. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/capture_i2v_model_select_repro.py +0 -0
  148. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/capture_i2v_post_bind_state.py +0 -0
  149. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/capture_image_add_media_dom.py +0 -0
  150. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/capture_locale_invariants.py +0 -0
  151. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/cdp_drive_and_probe.py +0 -0
  152. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/character_create_spike.py +0 -0
  153. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/character_create_spike_v2.py +0 -0
  154. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/dump_character_selectors.js +0 -0
  155. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/make_project.py +0 -0
  156. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/materiality_backtest.py +0 -0
  157. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/monitor_pr_38.py +0 -0
  158. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/patch_character.py +0 -0
  159. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/record_flow_capture.py +0 -0
  160. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/skillopt/README.md +0 -0
  161. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/skillopt/harness.py +0 -0
  162. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/skillopt/tasks.json +0 -0
  163. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_char_editor_dom.py +0 -0
  164. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_char_gen_capture.py +0 -0
  165. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_movie_attach_payload.py +0 -0
  166. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_movie_entity_recon.py +0 -0
  167. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_movie_gen_capture.py +0 -0
  168. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_movie_picker_select.py +0 -0
  169. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_movie_voice_list.py +0 -0
  170. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_patch_entity.py +0 -0
  171. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/record_demo.ps1 +0 -0
  172. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/smoke_image.py +0 -0
  173. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/smoke_real_chrome_image.py +0 -0
  174. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/smoke_video_editor.py +0 -0
  175. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/smoke_worker_style.py +0 -0
  176. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/verify_chrome_auth_viability.py +0 -0
  177. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/README.md +0 -0
  178. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/gflow-cli/SKILL.md +0 -0
  179. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/plan/SKILL.md +0 -0
  180. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/pr-council-review/SKILL.md +0 -0
  181. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/predict/SKILL.md +0 -0
  182. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/scenario/SKILL.md +0 -0
  183. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/status/SKILL.md +0 -0
  184. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/sonar-project.properties +0 -0
  185. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/__main__.py +0 -0
  186. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/_cli_helpers.py +0 -0
  187. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/__init__.py +0 -0
  188. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/_retry.py +0 -0
  189. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/_sapisidhash.py +0 -0
  190. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/character.py +0 -0
  191. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/dto.py +0 -0
  192. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/recaptcha.py +0 -0
  193. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/routes.py +0 -0
  194. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/scene.py +0 -0
  195. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/__init__.py +0 -0
  196. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/_common.py +0 -0
  197. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/_fingerprint.py +0 -0
  198. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/base.py +0 -0
  199. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/experimental/__init__.py +0 -0
  200. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/experimental/bearer.py +0 -0
  201. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +0 -0
  202. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/experimental/sapisidhash.py +0 -0
  203. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/video.py +0 -0
  204. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/__init__.py +0 -0
  205. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/base.py +0 -0
  206. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/factory.py +0 -0
  207. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/internal_chromium.py +0 -0
  208. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/real_chrome.py +0 -0
  209. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/strategies.py +0 -0
  210. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/verification.py +0 -0
  211. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/browser_manager.py +0 -0
  212. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/chain.py +0 -0
  213. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/chain_manifest.py +0 -0
  214. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli.py +0 -0
  215. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_character.py +0 -0
  216. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_data.py +0 -0
  217. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_models.py +0 -0
  218. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_movie.py +0 -0
  219. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_run.py +0 -0
  220. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_scene.py +0 -0
  221. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_video.py +0 -0
  222. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/composition.py +0 -0
  223. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/config.py +0 -0
  224. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/__init__.py +0 -0
  225. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/chain_repo.py +0 -0
  226. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/0001_initial.sql +0 -0
  227. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/0002_add_cloud_storage.sql +0 -0
  228. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/0003_add_scene_tables.sql +0 -0
  229. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/0004_add_scene_output_path.sql +0 -0
  230. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/0005_add_chain_links.sql +0 -0
  231. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/0006_add_operations_metadata.sql +0 -0
  232. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/__init__.py +0 -0
  233. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/models.py +0 -0
  234. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/queries.py +0 -0
  235. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/redaction.py +0 -0
  236. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/repository.py +0 -0
  237. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/store.py +0 -0
  238. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/errors.py +0 -0
  239. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/exceptions.py +0 -0
  240. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/image_batch.py +0 -0
  241. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/json_output.py +0 -0
  242. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/manifest.py +0 -0
  243. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/media.py +0 -0
  244. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/movie_manifest.py +0 -0
  245. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/observability.py +0 -0
  246. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/paths.py +0 -0
  247. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/profile_store.py +0 -0
  248. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/services/__init__.py +0 -0
  249. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/services/character_create.py +0 -0
  250. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/storage.py +0 -0
  251. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tasks/lessons.md +0 -0
  252. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/test_assets/sample_batch.json +0 -0
  253. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/test_assets/sample_batch.tsv +0 -0
  254. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/test_assets/sample_batch_invalid.tsv +0 -0
  255. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/__init__.py +0 -0
  256. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/__init__.py +0 -0
  257. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/fixtures/character_gen_response.json +0 -0
  258. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/fixtures/patch_entity_response.json +0 -0
  259. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_aisandbox_auth_error.py +0 -0
  260. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_aisandbox_auth_headers.py +0 -0
  261. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_bearer_redaction.py +0 -0
  262. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_character.py +0 -0
  263. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client.py +0 -0
  264. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client_character.py +0 -0
  265. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client_delete_characters.py +0 -0
  266. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client_generate_character.py +0 -0
  267. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client_image.py +0 -0
  268. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client_patch_entity.py +0 -0
  269. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client_scene.py +0 -0
  270. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_concurrency.py +0 -0
  271. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_dto.py +0 -0
  272. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_image_dto.py +0 -0
  273. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_post_json_aisandbox_auth.py +0 -0
  274. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_recaptcha.py +0 -0
  275. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_retry.py +0 -0
  276. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_routes.py +0 -0
  277. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_routes_character.py +0 -0
  278. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_routes_scene.py +0 -0
  279. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_sapisidhash_helper.py +0 -0
  280. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_scene_models.py +0 -0
  281. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_video.py +0 -0
  282. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_video_request.py +0 -0
  283. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/__init__.py +0 -0
  284. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_base.py +0 -0
  285. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_bearer.py +0 -0
  286. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_common.py +0 -0
  287. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_evaluate_fetch.py +0 -0
  288. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_factory.py +0 -0
  289. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_fingerprint.py +0 -0
  290. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_sapisidhash.py +0 -0
  291. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_transport_timeout.py +0 -0
  292. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_ui_automation_batch.py +0 -0
  293. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_ui_automation_image_mode.py +0 -0
  294. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_ui_character_editor.py +0 -0
  295. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/auth/strategies/test_factory.py +0 -0
  296. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/auth/strategies/test_strategies.py +0 -0
  297. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/auth/test_verification.py +0 -0
  298. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/__init__.py +0 -0
  299. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_auth_list.py +0 -0
  300. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_character.py +0 -0
  301. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_character_create.py +0 -0
  302. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_data.py +0 -0
  303. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_image_seed_removed.py +0 -0
  304. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_models.py +0 -0
  305. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_movie.py +0 -0
  306. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_run.py +0 -0
  307. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_scene.py +0 -0
  308. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_video.py +0 -0
  309. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_video_chain.py +0 -0
  310. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_error_handling.py +0 -0
  311. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_helpers.py +0 -0
  312. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_movie_manifest.py +0 -0
  313. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_t2i_multi_prompt.py +0 -0
  314. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/composition/test_character.py +0 -0
  315. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/composition/test_compose_prompt.py +0 -0
  316. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/composition/test_handoff.py +0 -0
  317. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/conftest.py +0 -0
  318. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/__init__.py +0 -0
  319. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_chain_repo.py +0 -0
  320. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_find_incomplete_character.py +0 -0
  321. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_models.py +0 -0
  322. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_packaging.py +0 -0
  323. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_recorder.py +0 -0
  324. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_recorder_character.py +0 -0
  325. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_redaction.py +0 -0
  326. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_repository.py +0 -0
  327. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_scene_persistence.py +0 -0
  328. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_settings_and_errors.py +0 -0
  329. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_store_migrations.py +0 -0
  330. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/dev/test_record_flow_capture.py +0 -0
  331. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/__init__.py +0 -0
  332. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/conftest.py +0 -0
  333. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_aisandbox_auth_live.py +0 -0
  334. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_auth_verification_e2e.py +0 -0
  335. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_chain_e2e.py +0 -0
  336. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_character_create_e2e.py +0 -0
  337. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_data_layer_e2e.py +0 -0
  338. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_i2v_flags_e2e.py +0 -0
  339. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_image_batch_e2e.py +0 -0
  340. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_image_i2i_ref_cap_e2e.py +0 -0
  341. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_json_output_e2e.py +0 -0
  342. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_locale_selectors_e2e.py +0 -0
  343. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_scene_compose_live.py +0 -0
  344. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_transports_e2e.py +0 -0
  345. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_video_r2v_ref_cap_e2e.py +0 -0
  346. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_video_t2v_e2e.py +0 -0
  347. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/__init__.py +0 -0
  348. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/auth.feature +0 -0
  349. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/auth_login.feature +0 -0
  350. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/character_create.feature +0 -0
  351. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/character_read.feature +0 -0
  352. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/conftest.py +0 -0
  353. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/image.feature +0 -0
  354. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_auth_login_steps.py +0 -0
  355. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_auth_steps.py +0 -0
  356. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_character_create_steps.py +0 -0
  357. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_character_read_steps.py +0 -0
  358. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_step_collision_guard.py +0 -0
  359. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_video_chain_steps.py +0 -0
  360. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/video_chain.feature +0 -0
  361. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/fixtures/__init__.py +0 -0
  362. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/fixtures/seeded_catalog.py +0 -0
  363. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/image_batch/__init__.py +0 -0
  364. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/image_batch/test_image_manifest.py +0 -0
  365. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/image_batch/test_observability_events.py +0 -0
  366. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/integration/__init__.py +0 -0
  367. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/integration/conftest.py +0 -0
  368. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/integration/constants.py +0 -0
  369. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/integration/test_storage_gcs.py +0 -0
  370. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/integration/test_storage_s3.py +0 -0
  371. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/scripts/test_capture_locale_invariants.py +0 -0
  372. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/scripts/test_check_materiality.py +0 -0
  373. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/scripts/test_check_repo_hygiene.py +0 -0
  374. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/scripts/test_materiality_backtest.py +0 -0
  375. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/services/__init__.py +0 -0
  376. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/services/test_character_create_redaction.py +0 -0
  377. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/services/test_character_create_saga.py +0 -0
  378. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/services/test_character_gen_no_direct_post.py +0 -0
  379. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/smoke/__init__.py +0 -0
  380. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/smoke/test_profile_account_smoke.py +0 -0
  381. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/smoke/test_real_flow.py +0 -0
  382. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_auth.py +0 -0
  383. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_browser_manager.py +0 -0
  384. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_chain.py +0 -0
  385. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_chain_manifest.py +0 -0
  386. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_cli_data.py +0 -0
  387. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_config.py +0 -0
  388. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_conftest_isolation.py +0 -0
  389. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_data_queries.py +0 -0
  390. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_documentation_gate.py +0 -0
  391. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_errors.py +0 -0
  392. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_errors_403.py +0 -0
  393. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_json_output.py +0 -0
  394. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_manifest.py +0 -0
  395. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_marker_registry.py +0 -0
  396. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_media.py +0 -0
  397. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_observability.py +0 -0
  398. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_paths.py +0 -0
  399. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_profile_store.py +0 -0
  400. {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_smoke.py +0 -0
@@ -76,10 +76,12 @@ The `skills/` directory ships installable agent skill docs in plain Markdown wit
76
76
  | `gflow-cli` | [`skills/gflow-cli/SKILL.md`](skills/gflow-cli/SKILL.md) | User wants to run any `gflow` command — auth, T2V, I2V, T2I, I2I, batch |
77
77
  | `predict` | [`skills/predict/SKILL.md`](skills/predict/SKILL.md) | Pre-implementation adversarial analysis before any high-stakes change |
78
78
  | `scenario` | [`skills/scenario/SKILL.md`](skills/scenario/SKILL.md) | Edge-case explorer after a predict GO/CAUTION |
79
+ | `plan` | [`skills/plan/SKILL.md`](skills/plan/SKILL.md) | Create a structured task-by-task implementation plan for a feature |
80
+ | `status` | [`skills/status/SKILL.md`](skills/status/SKILL.md) | Show current plan state, progress, and next unchecked task |
79
81
  | `pr-council-review` | [`skills/pr-council-review/SKILL.md`](skills/pr-council-review/SKILL.md) | Multi-dimensional PR council review |
80
82
 
81
83
  **Cursor / Aider / Codex / Gemini CLI:** paste or include the relevant `SKILL.md` in your system context.
82
- **Claude Code:** symlink `skills/gflow-cli` to `~/.claude/skills/gflow-cli` to register the skill; the `/gflow:` slash commands (in `.claude/commands/gflow/`) are auto-discovered from the project directory.
84
+ **Claude Code:** the `/gflow:` slash commands in `.claude/commands/gflow/` are auto-discovered when the project is open — no extra setup needed. To register a skill globally, copy the command file to `~/.claude/commands/`.
83
85
  **Custom agents:** fetch `skills/gflow-cli/SKILL.md` into your knowledge base before answering gflow questions.
84
86
 
85
87
  The SkillOpt harness at `scripts/dev/skillopt/` measures how accurately each skill guides an agent, and supports multiple providers (Anthropic, OpenAI-compat, Gemini, local models). See [`scripts/dev/skillopt/README.md`](scripts/dev/skillopt/README.md).
@@ -7,6 +7,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.15.1] — 2026-06-10
11
+
12
+ ### Changed
13
+
14
+ - Added `--disable-dev-shm-usage` to Chrome launch args in both `FlowApiClient._persistent_context_kwargs()` and `UiAutomationTransport.setup()` — prevents OOM in Docker containers with the default 64 MB `/dev/shm` allocation; no effect on developer machines with adequate shared memory
15
+ - README Stats badges hardened against shields.io outages — GitHub-stat badges now pass `cacheSeconds=3600` (mitigates shields.io's shared GitHub token-pool exhaustion, the "Unable to select next GitHub token from pool" error) and the PyPI downloads badge moved from `img.shields.io/pypi/dm` to pepy.tech (pypistats rate-limits shields.io upstream)
16
+
17
+ ### Added
18
+
19
+ - `scripts/diag/` directory — documented home for investigation scripts that require a live authenticated profile; includes `memory_profile.py` (Chrome process-tree RSS profiler for issue #155), `capture_flow_traffic.py`, and `recaptcha_mint.py` (both moved from `scripts/` root via git mv, history preserved)
20
+
21
+ ### Fixed
22
+
23
+ - Video status poll now raises `AuthExpiredError` (exit 3) immediately on HTTP 401 from `batchCheckAsyncVideoGenerationStatus` instead of silently timing out after 600 s with a bare `TimeoutError` (exit 1) — session expiry is now detected mid-workflow, not only at login time (issue #156)
24
+
25
+ ## [0.15.0] — 2026-06-09
26
+
27
+ ### Added
28
+
29
+ - **`gflow image` can reference locked CHARACTER entities** for character-consistent
30
+ stills. New `--reference-entity <id>` (repeatable) + `--reference-entity-name` on
31
+ `image t2i` / `i2i`, plus `--project <id>` to generate in an EXISTING project (where
32
+ the entities live) instead of a throwaway scratch project. Entities attach through
33
+ the editor's **Personagens picker** and ride the submit as `referenceEntities`
34
+ (confirmed against the live API); `_build_batch_generate_images_body` serializes them
35
+ so non-UI/headless transports get parity too. Entities count toward the per-model
36
+ reference cap. `--project` / `--reference-entity` are single-prompt only; for a pure
37
+ character reference use `t2i` (`i2i` still needs a `--ref`). See `docs/USAGE.md` →
38
+ "Character-consistent images (entity references)".
39
+
40
+ ### Fixed
41
+
42
+ - `--project` no longer overwrites an existing project's stored title/source in the
43
+ local history DB (the recorder preserves the curated title for non-created projects).
44
+
45
+ ### Security
46
+
47
+ - `--project` / `--reference-entity` ids are validated at the CLI boundary
48
+ (`[A-Za-z0-9-]{1,128}`), closing an unvalidated `page.goto` navigation path
49
+ (`project_editor_url` lacked the allowlist its sibling routes enforce) and a
50
+ CSS-selector injection vector (`data-tile-id='fe_id_<id>'`). The request-body debug
51
+ logger elides large reference-field values so Flow-built image bytes can't leak into
52
+ logs.
53
+
54
+ ### Internal
55
+
56
+ - Bump dev/CI `ruff` to `0.15.16` (both the `dev` extra and the `dependency-groups`
57
+ pin; supersedes Dependabot PR #165, which updated only the soft `>=` extra and not
58
+ the hard `==` group pin CI actually uses). `ruff check` / `format --check` clean.
59
+
10
60
  ## [0.14.0] — 2026-06-07
11
61
 
12
62
  ### Added
@@ -1434,7 +1484,9 @@ shell-script template that branches on these codes.
1434
1484
 
1435
1485
  First skeleton. Not functional end-to-end yet.
1436
1486
 
1437
- [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.14.0...HEAD
1487
+ [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.15.1...HEAD
1488
+ [0.15.1]: https://github.com/ffroliva/gflow-cli/compare/v0.15.0...v0.15.1
1489
+ [0.15.0]: https://github.com/ffroliva/gflow-cli/compare/v0.14.0...v0.15.0
1438
1490
  [0.14.0]: https://github.com/ffroliva/gflow-cli/compare/v0.13.0...v0.14.0
1439
1491
  [0.13.0]: https://github.com/ffroliva/gflow-cli/compare/v0.12.0...v0.13.0
1440
1492
  [0.12.0]: https://github.com/ffroliva/gflow-cli/compare/v0.11.0...v0.12.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gflow-cli
3
- Version: 0.14.0
3
+ Version: 0.15.1
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
@@ -53,7 +53,7 @@ Requires-Dist: numpy>=1.24; extra == 'dev'
53
53
  Requires-Dist: pyright>=1.1.0; extra == 'dev'
54
54
  Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
55
55
  Requires-Dist: pytest>=8.0.0; extra == 'dev'
56
- Requires-Dist: ruff>=0.15.15; extra == 'dev'
56
+ Requires-Dist: ruff>=0.15.16; extra == 'dev'
57
57
  Provides-Extra: gcs
58
58
  Requires-Dist: gcsfs>=2024.2.0; extra == 'gcs'
59
59
  Requires-Dist: universal-pathlib>=0.2.5; extra == 'gcs'
@@ -196,13 +196,13 @@ gflow CLI → Provider (interchangeable) → Flow (ui_automation) / Mock (te
196
196
 
197
197
  ## Stats
198
198
 
199
- [![GitHub stars](https://img.shields.io/github/stars/ffroliva/gflow-cli?style=social)](https://github.com/ffroliva/gflow-cli/stargazers)
200
- [![GitHub forks](https://img.shields.io/github/forks/ffroliva/gflow-cli?style=social)](https://github.com/ffroliva/gflow-cli/network/members)
201
- [![GitHub watchers](https://img.shields.io/github/watchers/ffroliva/gflow-cli?style=social)](https://github.com/ffroliva/gflow-cli/watchers)
202
- [![GitHub issues](https://img.shields.io/github/issues/ffroliva/gflow-cli)](https://github.com/ffroliva/gflow-cli/issues)
203
- [![GitHub pull requests](https://img.shields.io/github/issues-pr/ffroliva/gflow-cli)](https://github.com/ffroliva/gflow-cli/pulls)
204
- [![GitHub last commit](https://img.shields.io/github/last-commit/ffroliva/gflow-cli)](https://github.com/ffroliva/gflow-cli/commits/main)
205
- [![GitHub repo size](https://img.shields.io/github/repo-size/ffroliva/gflow-cli)](https://github.com/ffroliva/gflow-cli)
206
- [![PyPI downloads](https://img.shields.io/pypi/dm/gflow-cli.svg)](https://pypi.org/project/gflow-cli/)
199
+ [![GitHub stars](https://img.shields.io/github/stars/ffroliva/gflow-cli?style=social&cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli/stargazers)
200
+ [![GitHub forks](https://img.shields.io/github/forks/ffroliva/gflow-cli?style=social&cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli/network/members)
201
+ [![GitHub watchers](https://img.shields.io/github/watchers/ffroliva/gflow-cli?style=social&cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli/watchers)
202
+ [![GitHub issues](https://img.shields.io/github/issues/ffroliva/gflow-cli?cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli/issues)
203
+ [![GitHub pull requests](https://img.shields.io/github/issues-pr/ffroliva/gflow-cli?cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli/pulls)
204
+ [![GitHub last commit](https://img.shields.io/github/last-commit/ffroliva/gflow-cli?cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli/commits/main)
205
+ [![GitHub repo size](https://img.shields.io/github/repo-size/ffroliva/gflow-cli?cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli)
206
+ [![PyPI downloads](https://static.pepy.tech/badge/gflow-cli/month)](https://pepy.tech/project/gflow-cli)
207
207
 
208
208
  If `gflow-cli` saves you time, please ⭐ the repo — it is the cheapest way to support the project.
@@ -132,13 +132,13 @@ gflow CLI → Provider (interchangeable) → Flow (ui_automation) / Mock (te
132
132
 
133
133
  ## Stats
134
134
 
135
- [![GitHub stars](https://img.shields.io/github/stars/ffroliva/gflow-cli?style=social)](https://github.com/ffroliva/gflow-cli/stargazers)
136
- [![GitHub forks](https://img.shields.io/github/forks/ffroliva/gflow-cli?style=social)](https://github.com/ffroliva/gflow-cli/network/members)
137
- [![GitHub watchers](https://img.shields.io/github/watchers/ffroliva/gflow-cli?style=social)](https://github.com/ffroliva/gflow-cli/watchers)
138
- [![GitHub issues](https://img.shields.io/github/issues/ffroliva/gflow-cli)](https://github.com/ffroliva/gflow-cli/issues)
139
- [![GitHub pull requests](https://img.shields.io/github/issues-pr/ffroliva/gflow-cli)](https://github.com/ffroliva/gflow-cli/pulls)
140
- [![GitHub last commit](https://img.shields.io/github/last-commit/ffroliva/gflow-cli)](https://github.com/ffroliva/gflow-cli/commits/main)
141
- [![GitHub repo size](https://img.shields.io/github/repo-size/ffroliva/gflow-cli)](https://github.com/ffroliva/gflow-cli)
142
- [![PyPI downloads](https://img.shields.io/pypi/dm/gflow-cli.svg)](https://pypi.org/project/gflow-cli/)
135
+ [![GitHub stars](https://img.shields.io/github/stars/ffroliva/gflow-cli?style=social&cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli/stargazers)
136
+ [![GitHub forks](https://img.shields.io/github/forks/ffroliva/gflow-cli?style=social&cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli/network/members)
137
+ [![GitHub watchers](https://img.shields.io/github/watchers/ffroliva/gflow-cli?style=social&cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli/watchers)
138
+ [![GitHub issues](https://img.shields.io/github/issues/ffroliva/gflow-cli?cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli/issues)
139
+ [![GitHub pull requests](https://img.shields.io/github/issues-pr/ffroliva/gflow-cli?cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli/pulls)
140
+ [![GitHub last commit](https://img.shields.io/github/last-commit/ffroliva/gflow-cli?cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli/commits/main)
141
+ [![GitHub repo size](https://img.shields.io/github/repo-size/ffroliva/gflow-cli?cacheSeconds=3600)](https://github.com/ffroliva/gflow-cli)
142
+ [![PyPI downloads](https://static.pepy.tech/badge/gflow-cli/month)](https://pepy.tech/project/gflow-cli)
143
143
 
144
144
  If `gflow-cli` saves you time, please ⭐ the repo — it is the cheapest way to support the project.
@@ -37,6 +37,7 @@ Welcome to the `gflow-cli` documentation. This index is the routing layer: it te
37
37
  | **[tasks/lessons.md](../tasks/lessons.md)** | Running notebook of patterns + reviewer findings, dated and traced to commits | Starting a new phase; debugging "why did the council flag this?" |
38
38
  | **[skills/README.md](../skills/README.md)** | Installable agent skill docs (gflow-cli, predict, pr-council-review, scenario) — cross-tool portable Markdown consumed by Claude Code, Cursor, Codex, Gemini CLI, Aider, etc. | Any agent wanting to use gflow-cli correctly |
39
39
  | **[scripts/dev/skillopt/README.md](../scripts/dev/skillopt/README.md)** | SkillOpt mock harness — rollout→score loop for measuring and improving skill doc accuracy across multiple LLM providers | Measuring a skill edit's impact; comparing Claude vs GPT-4o vs Gemini on gflow tasks |
40
+ | **[scripts/diag/README.md](../scripts/diag/README.md)** | Diagnostic investigation scripts — run against a live authenticated profile to capture wire samples, measure Chrome memory, or mint reCAPTCHA tokens | Running a one-off investigation against a live Flow session; establishing baseline measurements for issue #155 |
40
41
 
41
42
  ## Agent commands
42
43
 
@@ -54,6 +55,9 @@ Slash commands for Claude Code, stored in `.claude/commands/gflow/`. All prefixe
54
55
  | `/gflow:release` | Full release flow (calls `/gflow:changelog` + `/gflow:check`) | Cutting a new version |
55
56
  | `/gflow:predict <proposal>` | 5-persona pre-implementation analysis → GO / CAUTION / STOP | Before any high-stakes design decision (new transport, auth change, selector redesign, schema migration) |
56
57
  | `/gflow:scenario <feature>` | 12-dimension edge-case explorer → severity-ranked scenario table + BDD skeleton | After predict GO/CAUTION; before `/gflow:plan` |
58
+ | `/gflow:pr-council-review [PR#]` | Multi-dimensional council review of an open PR (5 baseline + adaptive dimensions) | Before merging any non-trivial PR; mandatory for auth/transport/data changes |
59
+ | `/gflow:branch-review` | Same council review run against the current local feature branch (no PR needed) | Pre-PR self-audit; after predict/scenario on a high-stakes branch |
60
+ | `/gflow:doc-review` | Systematic council-driven audit of documentation completeness and drift | Before cutting a release; after major documentation changes |
57
61
 
58
62
  **Governance:** commands are executable docs — they decay like any doc. When a phase advances or a file path changes, update the relevant command in the same commit. `/gflow:release` includes a staleness review step.
59
63
 
@@ -90,6 +94,7 @@ Slash commands for Claude Code, stored in `.claude/commands/gflow/`. All prefixe
90
94
  **"How do I use this project's skills in Cursor / Codex / Gemini CLI / Aider?"** → [skills/README.md](../skills/README.md#use-with-other-agents)
91
95
  **"How do I benchmark a skill doc against real tasks?"** → [scripts/dev/skillopt/README.md](../scripts/dev/skillopt/README.md)
92
96
  **"How do I compare Claude vs GPT-4o vs Gemini on gflow tasks?"** → `python scripts/dev/skillopt/harness.py --provider openai --model gpt-4o` (see [skillopt README](../scripts/dev/skillopt/README.md))
97
+ **"What does Chrome actually use in RAM during a generation?"** → run `uv run python scripts/diag/memory_profile.py --profile NAME` (see [scripts/diag/README.md](../scripts/diag/README.md))
93
98
  **"How do I report a security issue?"** → [SECURITY § Reporting](SECURITY.md#reporting)
94
99
  **"What branch do I work on? How do I name it?"** → [DEVELOPMENT § Branching model](DEVELOPMENT.md#branching-model)
95
100
  **"How do I handle an external GitHub PR?"** → [GITHUB § Scenario Matrix](GITHUB.md#scenario-matrix)
@@ -104,7 +109,7 @@ Slash commands for Claude Code, stored in `.claude/commands/gflow/`. All prefixe
104
109
  **"A gflow command hangs / fails — where do I start?"** → [DEBUGGING § Quick reference](DEBUGGING.md#quick-reference)
105
110
  **"Flow's UI broke a selector — how do I diagnose it?"** → [DEBUGGING § Inspecting Flow's live UI](DEBUGGING.md#inspecting-flows-live-ui)
106
111
  **"What does each `ui_automation.*` log event mean?"** → [DEBUGGING § Listener & HTTP-layer debugging](DEBUGGING.md#listener--http-layer-debugging)
107
- **"What was actually live-verified for the latest release?"** → [LIVE_VERIFICATION_v0.13.0](LIVE_VERIFICATION_v0.13.0.md) · prior: [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)
112
+ **"What was actually live-verified for the latest release?"** → v0.15.0 / v0.14.x: no dedicated live-verification doc (CI + the v0.13.0 baseline). Latest doc: [LIVE_VERIFICATION_v0.13.0](LIVE_VERIFICATION_v0.13.0.md) · prior: [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)
108
113
  **"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)
109
114
  **"What was live-verified for the video-download feature (#29)?"** → [LIVE_VERIFICATION_video_download](LIVE_VERIFICATION_video_download.md)
110
115
  **"What is the jitter matrix evidence for `gflow image batch`?"** → [`LIVE_VERIFICATION_image_batch.md`](LIVE_VERIFICATION_image_batch.md) — jitter matrix evidence for `gflow image batch` (always-same-project mode)
@@ -4,9 +4,9 @@
4
4
 
5
5
  ## Current release
6
6
 
7
- **v0.13.0 — alpha.** High-fidelity CLI hardening and term alignment. **`gflow video i2v`** now uses the canonical `--initial-frame` and `--end-frame` flags (matching Flow's UI labels), with robust Click greedy-fill protection and positional backward compatibility. **In-project governance** (ruff T20, materiality classification) is now active to harden the AI-driven development flow. This release also refactors the **`character_create` saga** for improved type safety and documentation. Live-verified end-to-end on 2026-06-04 with the new flags and interpolation paths.
7
+ **v0.15.0 — alpha.** **Character-consistent images via entity references.** `gflow image t2i/i2i` can now reference locked Flow CHARACTER entities (`--reference-entity <id>`, repeatable) and generate in an existing project (`--project <id>`) where those entities live entities attach through the editor's Personagens picker and ride the submit as `referenceEntities` (confirmed against the live API; the body builder serializes them for headless transports too). Live-verified 2026-06-08: a 3-frame Dragon-Hook smoke rendered drift-free with all three characters on-model. LLM-council-reviewed (security/correctness/dedup) before merge. Carries forward the v0.14.0 `gflow movie` line (multi-scene, character-consistent video).
8
8
 
9
- **Develop (unreleased, post-v0.13.0):** *(empty — develop is the staging branch for the next release).*
9
+ **Develop (unreleased, post-v0.15.0):** *(empty — develop is the staging branch for the next release).*
10
10
 
11
11
  ## Milestone history
12
12
 
@@ -52,6 +52,8 @@
52
52
  | `gflow character rm` — free character deletion (#150) | ✅ done (v0.13.0) |
53
53
  | Align I2V CLI flags with Flow UI Labels (`--initial-frame`) (#122) | ✅ done (v0.13.0) |
54
54
  | In-project governance (ruff T20, materiality Classifier) | ✅ done (v0.13.0) |
55
+ | `gflow movie` — multi-scene, character-consistent video from a TOML manifest (entity reuse, resumable, handoff manifest) | ✅ done (v0.14.0) |
56
+ | `gflow image t2i/i2i` — reference locked CHARACTER entities (`--reference-entity`) + `--project` for character-consistent stills | ✅ done (v0.15.0) |
55
57
  | `gflow character` — reusable Flow Character entities (`create`/`list`/`show`/`voices`), persist-before-spend saga (#145) | ✅ done (v0.12.0) |
56
58
  | `gflow scene` — Add Clip / Scenes compose + credit-free server-side extended video (`runVideoFxConcatenation`) | ✅ done (v0.12.0) |
57
59
  | `gflow video chain` — last-frame I2V chaining from a JSONL manifest (`--dry-run`/`--max-links`/`--resume-from`) | ✅ done (v0.12.0) |
@@ -131,6 +131,13 @@ Options:
131
131
  Aspect ratio. [default: 9:16]
132
132
  -n, --count INTEGER How many images to generate (1-4). [default: 1]
133
133
  --out PATH Output directory (see "Output paths" below).
134
+ --project ID Generate in this EXISTING Flow project instead of a
135
+ scratch project. Required to reference locked
136
+ entities/assets in that project. Single-prompt only.
137
+ --reference-entity ID Flow CHARACTER entity id to reference for character
138
+ consistency (repeatable; must live in --project).
139
+ Single-prompt only.
140
+ --reference-entity-name N Display name paired with --reference-entity.
134
141
  --profile NAME Profile name (overrides default).
135
142
  ```
136
143
 
@@ -212,6 +219,10 @@ Options:
212
219
  Aspect ratio. [default: 9:16]
213
220
  -n, --count INTEGER How many images to generate (1-4). [default: 1]
214
221
  --out PATH Output directory (same semantics as t2i).
222
+ --project ID Generate in this EXISTING Flow project (skip scratch).
223
+ --reference-entity ID Flow CHARACTER entity id to reference (repeatable;
224
+ must live in --project). Counts toward the ref cap.
225
+ --reference-entity-name N Display name paired with --reference-entity.
215
226
  --profile NAME Profile name (overrides default).
216
227
  ```
217
228
 
@@ -248,6 +259,40 @@ A 2-image run produces files numbered `_1.png`, `_2.png`:
248
259
  ./variants/<media_name_b>_2.png
249
260
  ```
250
261
 
262
+ ## Character-consistent images (entity references)
263
+
264
+ `--reference-entity` makes `image t2i`/`i2i` reference a locked Flow **CHARACTER
265
+ entity** (minted via `gflow character create`) so the generated subject stays
266
+ on-model across shots — no per-shot prompt wrangling or fragile image refs.
267
+
268
+ How it works: entities are **project-scoped**, so you must generate **in the
269
+ project that owns them** via `--project <id>` (this also means no throwaway
270
+ scratch project is created). The CLI attaches each entity through the Flow editor's
271
+ resource picker; the submit then carries `referenceEntities`, exactly like the
272
+ video R2V path. Entities count toward the same per-model reference cap as `--ref`
273
+ images. `--reference-entity` / `--project` are **single-prompt only**.
274
+
275
+ For a *pure* character reference (no starting image) use `t2i` — `i2i` still
276
+ requires at least one `--ref`.
277
+
278
+ ```bash
279
+ # One locked character, consistent across runs (t2i = no image ref needed)
280
+ gflow image t2i "Aria explores a neon market, full body" \
281
+ --project 7fa97443-… --reference-entity 8a77f8cb-… --reference-entity-name Aria \
282
+ --model nano2 --aspect 9:16 -n 3
283
+
284
+ # Several characters in one scene (each --reference-entity repeatable)
285
+ gflow image t2i "Aria and Drako meet at the gate" --project 7fa97443-… \
286
+ --reference-entity 8a77f8cb-… --reference-entity 4ed5cb7f-…
287
+
288
+ # i2i: a starting image PLUS an entity for the character
289
+ gflow image i2i "place this hero in a snowy pass" --ref hero.png \
290
+ --project 7fa97443-… --reference-entity 8a77f8cb-…
291
+ ```
292
+
293
+ > Ids are validated at the CLI boundary (letters/digits/hyphens, ≤128 chars).
294
+ > The entity must already exist in `--project` (see `gflow character create`).
295
+
251
296
  ## `gflow image batch`
252
297
 
253
298
  Generate multiple images from a single manifest file. The format is dispatched by file extension (`.json` or `.tsv`).
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "gflow-cli"
3
- version = "0.14.0"
3
+ version = "0.15.1"
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" }
@@ -33,7 +33,7 @@ dependencies = [
33
33
  dev = [
34
34
  "pytest>=8.0.0",
35
35
  "pytest-asyncio>=0.23.0",
36
- "ruff>=0.15.15",
36
+ "ruff>=0.15.16",
37
37
  "pyright>=1.1.0",
38
38
  # video-chain: the last-frame extractor (media.py) decodes with PyAV, and its
39
39
  # tests build synthetic mp4 fixtures with numpy. Declared here so the dev/CI
@@ -134,7 +134,7 @@ dev = [
134
134
  "pytest-asyncio>=1.3.0",
135
135
  "pytest-bdd>=8.1.0",
136
136
  "pytest-cov>=7.1.0",
137
- "ruff==0.15.15",
137
+ "ruff==0.15.16",
138
138
  ]
139
139
  # Container-based integration tests — requires Docker daemon.
140
140
  # Install: uv sync --group containers
@@ -0,0 +1,29 @@
1
+ # scripts/diag/ — Diagnostic Investigation Scripts
2
+
3
+ These scripts require a live authenticated Chrome profile to run. They are investigation tools — not CI gates and not developer workflow tools — that help answer "what does this system actually do?" questions by observing a real browser session. Each script produces human-readable or structured output and does not modify production state.
4
+
5
+ ## Scripts
6
+
7
+ | Script | Purpose | Prerequisite | Run |
8
+ |---|---|---|---|
9
+ | `capture_flow_traffic.py` | Capture Flow's outgoing API requests via `page.route` | `gflow auth login` | `uv run python scripts/diag/capture_flow_traffic.py --profile NAME` |
10
+ | `recaptcha_mint.py` | What `site_key` + token does gflow-cli's `TokenMinter` produce? | `gflow auth login` (headed) | `uv run python scripts/diag/recaptcha_mint.py --profile NAME` |
11
+ | `memory_profile.py` | Chrome process-tree RSS at key milestones (issue #155) | `gflow auth login` + `pip install psutil` | `uv run python scripts/diag/memory_profile.py --profile NAME` |
12
+
13
+ ## What belongs here
14
+
15
+ 1. Requires a live authenticated session to run
16
+ 2. Produces human-readable or structured output for investigation
17
+ 3. Does not write to production data stores
18
+ 4. Answers a specific "what does this system actually do?" question
19
+
20
+ ## What does NOT belong here
21
+
22
+ - **CI gates** → `scripts/ci/` (run on every commit, no auth needed)
23
+ - **Developer workflow tools** → `scripts/dev/` (`active_plan.py`, `skillopt/`, etc.)
24
+ - **Live smoke tests** → `scripts/` root (`smoke_*.py` — full end-to-end generation runs)
25
+
26
+ ## Platform notes
27
+
28
+ - `memory_profile.py` requires `psutil`: `uv add --dev psutil` (not a hard dep — detected at runtime)
29
+ - All scripts: `uv run python scripts/diag/<name>.py` (no global Python install needed)
@@ -4,7 +4,7 @@ Spec § 11 mentioned a captured wire sample (samples/captured/06_batchGenerateIm
4
4
  but the file doesn't exist. This script produces that ground truth — what
5
5
  headers does Flow's UI actually attach when it calls aisandbox-pa?
6
6
 
7
- Run: `uv run python scripts/diag_capture_flow_traffic.py --profile <your-profile>`
7
+ Run: `uv run python scripts/diag/capture_flow_traffic.py --profile <your-profile>`
8
8
 
9
9
  Output goes to `tmp/captured/flow_outgoing_<utc>.jsonl` by default. **NEVER write
10
10
  captured traffic to `samples/captured/`** — those files contain live Bearer tokens
@@ -0,0 +1,235 @@
1
+ """Diagnostic — Chrome process-tree RSS at key milestones (issue #155).
2
+
3
+ Measures how much memory the Chrome/Chromium process tree consumes at four
4
+ points during a real browser launch against a gflow-cli profile:
5
+
6
+ baseline — before Playwright starts (current Python process only)
7
+ post_launch — immediately after launch_persistent_context returns
8
+ post_navigation — after page.goto(FLOW_URL, wait_until="networkidle")
9
+ post_close — after context.close() and Playwright stop
10
+
11
+ The output table shows Own RSS (the profiler's Python process) and Tree RSS
12
+ (profiler + all Chrome child processes) so you can see exactly how much RAM
13
+ Chrome adds at each stage.
14
+
15
+ Run: `uv run python scripts/diag/memory_profile.py --profile NAME [--output-json PATH]`
16
+
17
+ Prerequisite: gflow auth login (plus psutil — install with: uv add --dev psutil)
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import argparse
23
+ import asyncio
24
+ import json
25
+ import os
26
+ import sys
27
+ from pathlib import Path
28
+
29
+ try:
30
+ import psutil
31
+ except ImportError:
32
+ print("psutil is required: uv add --dev psutil", file=sys.stderr)
33
+ sys.exit(2)
34
+
35
+ try:
36
+ from gflow_cli.api.transports.ui_automation import FLOW_URL
37
+ except ImportError:
38
+ FLOW_URL = "https://labs.google/fx/tools/flow?hl=en"
39
+
40
+ from playwright.async_api import async_playwright
41
+
42
+ from gflow_cli.auth import profile_dir
43
+ from gflow_cli.browser_manager import channel_for_profile
44
+ from gflow_cli.config import get_settings
45
+
46
+ CHROME_ARGS = [
47
+ "--disable-blink-features=AutomationControlled",
48
+ "--disable-dev-shm-usage",
49
+ ]
50
+
51
+ _COL_MILESTONE = 16
52
+ _COL_OWN = 14
53
+ _COL_TREE = 15
54
+ _COL_DELTA = 12
55
+
56
+
57
+ def _tree_rss_mb(pid: int) -> float:
58
+ """Return total RSS (MB) of a process and all its descendants."""
59
+ try:
60
+ proc = psutil.Process(pid)
61
+ procs = [proc, *proc.children(recursive=True)]
62
+ return sum(p.memory_info().rss for p in procs if p.is_running()) / (1024 * 1024)
63
+ except (psutil.NoSuchProcess, psutil.AccessDenied):
64
+ return 0.0
65
+
66
+
67
+ def _own_rss_mb() -> float:
68
+ """Return RSS (MB) of only the current Python process."""
69
+ try:
70
+ return psutil.Process(os.getpid()).memory_info().rss / (1024 * 1024)
71
+ except (psutil.NoSuchProcess, psutil.AccessDenied):
72
+ return 0.0
73
+
74
+
75
+ def _print_table_header() -> None:
76
+ header = (
77
+ f"{'Milestone':<{_COL_MILESTONE}} | "
78
+ f"{'Own RSS (MB)':>{_COL_OWN}} | "
79
+ f"{'Tree RSS (MB)':>{_COL_TREE}} | "
80
+ f"{'Delta (MB)':>{_COL_DELTA}}"
81
+ )
82
+ sep = "-" * len(header)
83
+ print(sep)
84
+ print(header)
85
+ print(sep)
86
+
87
+
88
+ def _print_table_row(name: str, own_mb: float, tree_mb: float, delta: float | None) -> None:
89
+ delta_str = "—" if delta is None else f"{delta:+.1f}"
90
+ print(
91
+ f"{name:<{_COL_MILESTONE}} | "
92
+ f"{own_mb:>{_COL_OWN}.1f} | "
93
+ f"{tree_mb:>{_COL_TREE}.1f} | "
94
+ f"{delta_str:>{_COL_DELTA}}"
95
+ )
96
+
97
+
98
+ async def run(profile_name: str, output_json: Path | None) -> None:
99
+ """Main diagnostic loop."""
100
+ # Resolve profile directory using GFLOW_CLI_HOME
101
+ settings = get_settings()
102
+ _ = settings.home # ensure settings loaded; profile_dir() uses get_settings() internally
103
+ pdir = profile_dir(profile_name)
104
+ if not pdir.exists():
105
+ print(f"ERROR: Profile directory not found: {pdir}", file=sys.stderr)
106
+ sys.exit(1)
107
+
108
+ milestones: list[dict[str, object]] = []
109
+ pid = os.getpid()
110
+
111
+ # -------------------------------------------------------------------------
112
+ # Milestone 1: baseline (before Playwright starts)
113
+ # -------------------------------------------------------------------------
114
+ own_baseline = _own_rss_mb()
115
+ tree_baseline = _tree_rss_mb(pid)
116
+ milestones.append(
117
+ {
118
+ "name": "baseline",
119
+ "own_rss_mb": round(own_baseline, 2),
120
+ "tree_rss_mb": round(tree_baseline, 2),
121
+ "delta_mb": None,
122
+ }
123
+ )
124
+
125
+ _print_table_header()
126
+ _print_table_row("baseline", own_baseline, tree_baseline, None)
127
+
128
+ channel = channel_for_profile(pdir)
129
+
130
+ async with async_playwright() as pw:
131
+ launcher = pw.chromium
132
+
133
+ # -------------------------------------------------------------------------
134
+ # Milestone 2: post_launch
135
+ # -------------------------------------------------------------------------
136
+ ctx = await launcher.launch_persistent_context(
137
+ str(pdir),
138
+ headless=False,
139
+ args=CHROME_ARGS,
140
+ locale="en-US",
141
+ **({"channel": channel} if channel else {}),
142
+ )
143
+
144
+ own_post_launch = _own_rss_mb()
145
+ tree_post_launch = _tree_rss_mb(pid)
146
+ delta_launch = tree_post_launch - tree_baseline
147
+ milestones.append(
148
+ {
149
+ "name": "post_launch",
150
+ "own_rss_mb": round(own_post_launch, 2),
151
+ "tree_rss_mb": round(tree_post_launch, 2),
152
+ "delta_mb": round(delta_launch, 2),
153
+ }
154
+ )
155
+ _print_table_row("post_launch", own_post_launch, tree_post_launch, delta_launch)
156
+
157
+ # -------------------------------------------------------------------------
158
+ # Milestone 3: post_navigation
159
+ # -------------------------------------------------------------------------
160
+ page = ctx.pages[0] if ctx.pages else await ctx.new_page()
161
+ print(f"Navigating to {FLOW_URL} ...")
162
+ try:
163
+ await page.goto(FLOW_URL, wait_until="networkidle", timeout=45_000)
164
+ except Exception as exc: # noqa: BLE001
165
+ print(f"WARNING: navigation did not fully settle: {exc}", file=sys.stderr)
166
+
167
+ own_post_nav = _own_rss_mb()
168
+ tree_post_nav = _tree_rss_mb(pid)
169
+ delta_nav = tree_post_nav - tree_baseline
170
+ milestones.append(
171
+ {
172
+ "name": "post_navigation",
173
+ "own_rss_mb": round(own_post_nav, 2),
174
+ "tree_rss_mb": round(tree_post_nav, 2),
175
+ "delta_mb": round(delta_nav, 2),
176
+ }
177
+ )
178
+ _print_table_row("post_navigation", own_post_nav, tree_post_nav, delta_nav)
179
+
180
+ # -------------------------------------------------------------------------
181
+ # Milestone 4: post_close
182
+ # -------------------------------------------------------------------------
183
+ await ctx.close()
184
+
185
+ own_post_close = _own_rss_mb()
186
+ tree_post_close = _tree_rss_mb(pid)
187
+ delta_close = tree_post_close - tree_baseline
188
+ milestones.append(
189
+ {
190
+ "name": "post_close",
191
+ "own_rss_mb": round(own_post_close, 2),
192
+ "tree_rss_mb": round(tree_post_close, 2),
193
+ "delta_mb": round(delta_close, 2),
194
+ }
195
+ )
196
+ _print_table_row("post_close", own_post_close, tree_post_close, delta_close)
197
+ print("-" * (_COL_MILESTONE + _COL_OWN + _COL_TREE + _COL_DELTA + 9))
198
+
199
+ # -------------------------------------------------------------------------
200
+ # JSON output (optional)
201
+ # -------------------------------------------------------------------------
202
+ if output_json is not None:
203
+ result = {
204
+ "platform": sys.platform,
205
+ "chrome_args": CHROME_ARGS,
206
+ "milestones": milestones,
207
+ }
208
+ output_json.parent.mkdir(parents=True, exist_ok=True)
209
+ output_json.write_text(json.dumps(result, indent=2), encoding="utf-8")
210
+ print(f"JSON written to: {output_json}")
211
+
212
+
213
+ def main() -> None:
214
+ parser = argparse.ArgumentParser(
215
+ description=__doc__,
216
+ formatter_class=argparse.RawDescriptionHelpFormatter,
217
+ )
218
+ parser.add_argument(
219
+ "--profile",
220
+ required=True,
221
+ help="Name of the gflow-cli profile (directory under GFLOW_CLI_HOME)",
222
+ )
223
+ parser.add_argument(
224
+ "--output-json",
225
+ type=Path,
226
+ default=None,
227
+ metavar="PATH",
228
+ help="Optional path to write machine-readable results as JSON",
229
+ )
230
+ args = parser.parse_args()
231
+ asyncio.run(run(args.profile, args.output_json))
232
+
233
+
234
+ if __name__ == "__main__":
235
+ main()
@@ -1,6 +1,6 @@
1
1
  """Diagnostic — what site_key + token does gflow-cli's TokenMinter produce?
2
2
 
3
- Run: `uv run python scripts/diag_recaptcha_mint.py --profile <your-profile>`
3
+ Run: `uv run python scripts/diag/recaptcha_mint.py --profile <your-profile>`
4
4
 
5
5
  Opens HEADED Chromium, navigates to Flow, runs TokenMinter, prints the
6
6
  discovered site_key + minted token length. Compare to HAR ground truth:
@@ -1,3 +1,3 @@
1
1
  """gflow-cli — unofficial CLI for Google Flow."""
2
2
 
3
- __version__ = "0.14.0"
3
+ __version__ = "0.15.1"
@@ -293,7 +293,7 @@ class FlowApiClient:
293
293
  "--no-sandbox",
294
294
  "--password-store=basic",
295
295
  ],
296
- "args": ["--disable-blink-features=AutomationControlled"],
296
+ "args": ["--disable-blink-features=AutomationControlled", "--disable-dev-shm-usage"],
297
297
  }
298
298
 
299
299
  async def _enter_setup(self) -> None: