gflow-cli 0.29.0__tar.gz → 0.31.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 (524) hide show
  1. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/CHANGELOG.md +23 -1
  2. gflow_cli-0.31.0/GEMINI.md +37 -0
  3. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/KNOWN_ISSUES.md +102 -0
  4. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/PKG-INFO +1 -1
  5. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/PLAN.md +3 -1
  6. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/INDEX.md +1 -1
  7. gflow_cli-0.31.0/docs/LIVE_VERIFICATION_v0.30.0.md +53 -0
  8. gflow_cli-0.31.0/docs/LIVE_VERIFICATION_v0.31.0.md +83 -0
  9. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/MCP.md +1 -1
  10. gflow_cli-0.31.0/docs/superpowers/plans/2026-07-09-camoufox-adoption/PLAN.md +342 -0
  11. gflow_cli-0.31.0/docs/superpowers/spikes/2026-07-09-camoufox-waf-403.md +75 -0
  12. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/pyproject.toml +1 -1
  13. gflow_cli-0.31.0/scripts/spike_waf_camoufox.py +352 -0
  14. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/__init__.py +1 -1
  15. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/drivers/agentic.py +61 -8
  16. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/drivers/factory.py +6 -0
  17. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/ui_automation_video.py +63 -8
  18. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/cli_image.py +25 -4
  19. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/recorder.py +138 -1
  20. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/errors.py +34 -0
  21. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/image_batch.py +100 -22
  22. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/mcp/tools.py +35 -0
  23. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/worker/daemon.py +42 -16
  24. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/drivers/test_agentic.py +119 -4
  25. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_ui_automation_video.py +275 -0
  26. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_image.py +177 -0
  27. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/data/test_recorder.py +237 -0
  28. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/data/test_recorder_character.py +48 -0
  29. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/test_video_agent_ui_steps.py +3 -2
  30. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/image_batch/test_image_manifest.py +325 -0
  31. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/image_batch/test_observability_events.py +26 -0
  32. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/mcp/test_tools_wired.py +74 -0
  33. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_errors.py +25 -0
  34. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/worker/test_daemon.py +183 -1
  35. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/uv.lock +1 -1
  36. gflow_cli-0.29.0/GEMINI.md +0 -34
  37. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/README.md +0 -0
  38. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/active.md +0 -0
  39. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/branch-review.md +0 -0
  40. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/changelog.md +0 -0
  41. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/check.md +0 -0
  42. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/doc-review.md +0 -0
  43. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/issue-assessment.md +0 -0
  44. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/issue-resolve.md +0 -0
  45. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/known-issues.md +0 -0
  46. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/next.md +0 -0
  47. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/plan.md +0 -0
  48. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/pr-council-review.md +0 -0
  49. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/predict.md +0 -0
  50. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/release.md +0 -0
  51. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/scenario.md +0 -0
  52. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/sonar.md +0 -0
  53. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.claude/commands/gflow/status.md +0 -0
  54. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.env.template +0 -0
  55. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.gitattributes +0 -0
  56. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.github/CODEOWNERS +0 -0
  57. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  58. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.github/copilot-instructions.md +0 -0
  59. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.github/dependabot.yml +0 -0
  60. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.github/workflows/ci.yml +0 -0
  61. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.github/workflows/external-pr-triage.yml +0 -0
  62. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.github/workflows/governance-advisory.yml +0 -0
  63. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.github/workflows/governance-benchmark.yml +0 -0
  64. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.github/workflows/main-base-guard.yml +0 -0
  65. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.github/workflows/release.yml +0 -0
  66. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.gitignore +0 -0
  67. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.gitleaks.toml +0 -0
  68. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.pre-commit-config.yaml +0 -0
  69. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/.secrets.baseline +0 -0
  70. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/AGENTS.md +0 -0
  71. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/CLAUDE.md +0 -0
  72. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/CONFIGURATION.md +0 -0
  73. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/CONTRIBUTING.md +0 -0
  74. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/DISCLAIMER.md +0 -0
  75. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/LICENSE +0 -0
  76. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/README.md +0 -0
  77. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/RELEASE.md +0 -0
  78. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/ROADMAP.md +0 -0
  79. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/conftest.py +0 -0
  80. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docker-compose.yml +0 -0
  81. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/AGENT_GUIDE.md +0 -0
  82. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/AGENT_UI_E2E.md +0 -0
  83. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/AGENT_UI_RECON.md +0 -0
  84. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/ARCHITECTURE.md +0 -0
  85. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/AUTHENTICATION.md +0 -0
  86. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/CHARACTER.md +0 -0
  87. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/CHARACTER_RECON.md +0 -0
  88. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/CONFIGURATION.md +0 -0
  89. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/DATA_LAYER.md +0 -0
  90. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/DEBUGGING.md +0 -0
  91. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/DEMOS.md +0 -0
  92. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/DEVELOPMENT.md +0 -0
  93. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/E2E_TESTING.md +0 -0
  94. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/EXTERNAL_STORAGE.md +0 -0
  95. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/GITHUB.md +0 -0
  96. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/GOVERNANCE_BENCHMARK.md +0 -0
  97. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/IMAGE_UPSCALE_RECON.md +0 -0
  98. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/INSTRUCTIONS.md +0 -0
  99. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_data_layer.md +0 -0
  100. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_image_batch.md +0 -0
  101. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.10.0.md +0 -0
  102. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.11.0.md +0 -0
  103. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.12.0.md +0 -0
  104. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.13.0.md +0 -0
  105. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.16.0.md +0 -0
  106. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.17.0.md +0 -0
  107. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.18.0.md +0 -0
  108. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.19.0.md +0 -0
  109. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.20.0.md +0 -0
  110. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.20.1.md +0 -0
  111. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.21.0.md +0 -0
  112. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.22.0.md +0 -0
  113. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.23.0.md +0 -0
  114. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.24.0.md +0 -0
  115. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.25.0.md +0 -0
  116. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.26.0.md +0 -0
  117. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.27.0.md +0 -0
  118. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.27.1.md +0 -0
  119. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.28.0.md +0 -0
  120. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.29.0.md +0 -0
  121. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.7.0.md +0 -0
  122. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.8.1.md +0 -0
  123. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.9.0.md +0 -0
  124. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_v0.9.1.md +0 -0
  125. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/LIVE_VERIFICATION_video_download.md +0 -0
  126. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/MOVIE.md +0 -0
  127. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/PROJECT_STATUS.md +0 -0
  128. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/PROMPT_EXPANSION.md +0 -0
  129. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/SECURITY.md +0 -0
  130. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/TOOLS.md +0 -0
  131. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/USAGE.md +0 -0
  132. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/USER_GUIDE.md +0 -0
  133. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/assets/demo-split-pf.gif +0 -0
  134. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/assets/example-run.gif +0 -0
  135. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/assets/examples.webp +0 -0
  136. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/medium_tutorial.md +0 -0
  137. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/schemas/movie-handoff.schema.json +0 -0
  138. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/sonar-cleanup-tracker.md +0 -0
  139. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/superpowers/plans/2026-06-12-issue-174-library-ui-attach/PLAN.md +0 -0
  140. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/superpowers/plans/2026-06-22-mcp-server/PLAN.md +0 -0
  141. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/superpowers/plans/2026-06-22-mcp-server/PREDICT.md +0 -0
  142. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/superpowers/plans/2026-06-22-mcp-server/SCENARIO.md +0 -0
  143. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/superpowers/plans/2026-06-22-prompt-expansion/PLAN.md +0 -0
  144. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/superpowers/plans/2026-06-22-prompt-expansion/PREDICT.md +0 -0
  145. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/superpowers/plans/2026-06-22-prompt-expansion/SCENARIO.md +0 -0
  146. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/superpowers/plans/2026-06-24-gflow-studio-scaffold/PLAN.md +0 -0
  147. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/superpowers/plans/2026-06-24-rest-api-layer/PLAN.md +0 -0
  148. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/superpowers/plans/2026-06-26-mcp-e2e-test/PLAN.md +0 -0
  149. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/superpowers/research/2026-06-27-tool-abstraction-evaluation.md +0 -0
  150. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/docs/superpowers/specs/2026-06-29-issue-assessment-workflow-design.md +0 -0
  151. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/examples/README.md +0 -0
  152. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/examples/batch_from_config.py +0 -0
  153. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/examples/multi_prompt_t2i.py +0 -0
  154. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/examples/sample_config.json +0 -0
  155. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/examples/sample_prompts.txt +0 -0
  156. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/examples/single_image_t2i.py +0 -0
  157. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/examples/workflow_chain.py +0 -0
  158. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/llms.txt +0 -0
  159. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/README.md +0 -0
  160. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/01_upload_image.json +0 -0
  161. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
  162. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
  163. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/04_archive_workflow.json +0 -0
  164. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/05_createProject.json +0 -0
  165. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/06_batchGenerateImages.json +0 -0
  166. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
  167. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/08_batchAsyncGenerateVideoStartAndEndImage.json +0 -0
  168. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/09_batchAsyncGenerateVideoReferenceImages.json +0 -0
  169. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/10_batchCheckAsyncVideoGenerationStatus_successful.json +0 -0
  170. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/11_batchCheckAsyncVideoGenerationStatus_failed.json +0 -0
  171. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/12_create_scene.json +0 -0
  172. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/13_sceneWorkflows_update.json +0 -0
  173. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/14_get_scene_workflows.json +0 -0
  174. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/samples/captured/15_commit_flowWorkflow.json +0 -0
  175. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/ci/check_doc_links.py +0 -0
  176. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/ci/check_materiality.py +0 -0
  177. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/ci/check_repo_hygiene.py +0 -0
  178. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/debug_editor.py +0 -0
  179. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/debug_gen_settings.py +0 -0
  180. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/debug_settings.py +0 -0
  181. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/_recording_client.py +0 -0
  182. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/_spike_common.py +0 -0
  183. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/active_plan.py +0 -0
  184. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/analyze_agent_ui_capture.py +0 -0
  185. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/capture_i2v_frame_slots_dom.py +0 -0
  186. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/capture_i2v_intercept_submit.py +0 -0
  187. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/capture_i2v_model_select_repro.py +0 -0
  188. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/capture_i2v_post_bind_state.py +0 -0
  189. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/capture_image_add_media_dom.py +0 -0
  190. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/capture_locale_invariants.py +0 -0
  191. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/cdp_drive_and_probe.py +0 -0
  192. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/character_create_spike.py +0 -0
  193. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/character_create_spike_v2.py +0 -0
  194. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/dump_character_selectors.js +0 -0
  195. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/make_project.py +0 -0
  196. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/materiality_backtest.py +0 -0
  197. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/monitor_pr_38.py +0 -0
  198. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/patch_character.py +0 -0
  199. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/skillopt/README.md +0 -0
  200. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/skillopt/harness.py +0 -0
  201. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/skillopt/tasks.json +0 -0
  202. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_char_editor_dom.py +0 -0
  203. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_char_gen_capture.py +0 -0
  204. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_image_upscale_capture.py +0 -0
  205. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_image_upscale_drive.py +0 -0
  206. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_image_upscale_recaptcha_action.py +0 -0
  207. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_image_upscale_rest_probe.py +0 -0
  208. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_issue170_picker_locale_recon.py +0 -0
  209. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_issue174_library_ui_recon.py +0 -0
  210. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_movie_attach_payload.py +0 -0
  211. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_movie_entity_recon.py +0 -0
  212. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_movie_gen_capture.py +0 -0
  213. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_movie_picker_select.py +0 -0
  214. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_movie_voice_list.py +0 -0
  215. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_patch_entity.py +0 -0
  216. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/dev/spike_patchright.py +0 -0
  217. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/diag/README.md +0 -0
  218. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/diag/capture_flow_traffic.py +0 -0
  219. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/diag/memory_profile.py +0 -0
  220. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/diag/recaptcha_mint.py +0 -0
  221. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/e2e/agentic_image_e2e.ps1 +0 -0
  222. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/e2e/capture_agent_toggle.py +0 -0
  223. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/record_demo.ps1 +0 -0
  224. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/smoke_image.py +0 -0
  225. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/smoke_real_chrome_image.py +0 -0
  226. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/smoke_video_editor.py +0 -0
  227. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/smoke_worker_style.py +0 -0
  228. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/scripts/verify_chrome_auth_viability.py +0 -0
  229. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/skills/README.md +0 -0
  230. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/skills/gflow-cli/SKILL.md +0 -0
  231. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/skills/issue-assessment/SKILL.md +0 -0
  232. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/skills/issue-resolve/SKILL.md +0 -0
  233. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/skills/plan/SKILL.md +0 -0
  234. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/skills/pr-council-review/SKILL.md +0 -0
  235. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/skills/predict/SKILL.md +0 -0
  236. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/skills/scenario/SKILL.md +0 -0
  237. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/skills/status/SKILL.md +0 -0
  238. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/sonar-project.properties +0 -0
  239. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/__main__.py +0 -0
  240. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/_cli_helpers.py +0 -0
  241. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/__init__.py +0 -0
  242. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/_engine.py +0 -0
  243. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/_retry.py +0 -0
  244. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/_sapisidhash.py +0 -0
  245. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/character.py +0 -0
  246. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/client.py +0 -0
  247. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/dto.py +0 -0
  248. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/image.py +0 -0
  249. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/image_upscale.py +0 -0
  250. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/recaptcha.py +0 -0
  251. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/routes.py +0 -0
  252. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/scene.py +0 -0
  253. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/__init__.py +0 -0
  254. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/_common.py +0 -0
  255. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/_fingerprint.py +0 -0
  256. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/base.py +0 -0
  257. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/drivers/__init__.py +0 -0
  258. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/drivers/base.py +0 -0
  259. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/drivers/classic.py +0 -0
  260. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/experimental/__init__.py +0 -0
  261. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/experimental/bearer.py +0 -0
  262. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +0 -0
  263. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/experimental/sapisidhash.py +0 -0
  264. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/transports/ui_automation.py +0 -0
  265. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/api/video.py +0 -0
  266. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/auth/__init__.py +0 -0
  267. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/auth/base.py +0 -0
  268. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/auth/cookies.py +0 -0
  269. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/auth/factory.py +0 -0
  270. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/auth/internal_chromium.py +0 -0
  271. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/auth/real_chrome.py +0 -0
  272. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/auth/strategies.py +0 -0
  273. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/auth/verification.py +0 -0
  274. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/browser_manager.py +0 -0
  275. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/chain.py +0 -0
  276. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/chain_manifest.py +0 -0
  277. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/cli.py +0 -0
  278. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/cli_character.py +0 -0
  279. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/cli_data.py +0 -0
  280. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/cli_instructions.py +0 -0
  281. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/cli_models.py +0 -0
  282. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/cli_movie.py +0 -0
  283. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/cli_run.py +0 -0
  284. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/cli_scene.py +0 -0
  285. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/cli_tools.py +0 -0
  286. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/cli_video.py +0 -0
  287. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/composition.py +0 -0
  288. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/config.py +0 -0
  289. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/__init__.py +0 -0
  290. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/chain_repo.py +0 -0
  291. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/migrations/0001_initial.sql +0 -0
  292. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/migrations/0002_add_cloud_storage.sql +0 -0
  293. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/migrations/0003_add_scene_tables.sql +0 -0
  294. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/migrations/0004_add_scene_output_path.sql +0 -0
  295. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/migrations/0005_add_chain_links.sql +0 -0
  296. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/migrations/0006_add_operations_metadata.sql +0 -0
  297. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/migrations/0007_queue.sql +0 -0
  298. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/migrations/0008_add_operation_expanded_prompt.sql +0 -0
  299. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/migrations/__init__.py +0 -0
  300. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/models.py +0 -0
  301. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/queries.py +0 -0
  302. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/redaction.py +0 -0
  303. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/repository.py +0 -0
  304. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/data/store.py +0 -0
  305. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/exceptions.py +0 -0
  306. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/json_output.py +0 -0
  307. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/manifest.py +0 -0
  308. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/mcp/__init__.py +0 -0
  309. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/mcp/prompts.py +0 -0
  310. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/mcp/resources.py +0 -0
  311. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/mcp/server.py +0 -0
  312. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/media.py +0 -0
  313. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/movie_manifest.py +0 -0
  314. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/observability.py +0 -0
  315. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/paths.py +0 -0
  316. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/profile_store.py +0 -0
  317. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/services/__init__.py +0 -0
  318. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/services/character_create.py +0 -0
  319. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/storage.py +0 -0
  320. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/tools/__init__.py +0 -0
  321. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/tools/banned.py +0 -0
  322. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/tools/builtin/__init__.py +0 -0
  323. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/tools/builtin/creative-director.toml +0 -0
  324. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/tools/expander.py +0 -0
  325. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/tools/invocation.py +0 -0
  326. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/tools/loader.py +0 -0
  327. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/tools/registry.py +0 -0
  328. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/tools/runtime.py +0 -0
  329. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/tools/spec.py +0 -0
  330. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/ui/app.py +0 -0
  331. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/ui/server.py +0 -0
  332. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/src/gflow_cli/worker/queue.py +0 -0
  333. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tasks/lessons.md +0 -0
  334. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/test_assets/sample_batch.json +0 -0
  335. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/test_assets/sample_batch.tsv +0 -0
  336. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/test_assets/sample_batch_invalid.tsv +0 -0
  337. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/__init__.py +0 -0
  338. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/__init__.py +0 -0
  339. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/fixtures/character_gen_response.json +0 -0
  340. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/fixtures/patch_entity_response.json +0 -0
  341. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_aisandbox_auth_error.py +0 -0
  342. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_aisandbox_auth_headers.py +0 -0
  343. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_bearer_redaction.py +0 -0
  344. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_character.py +0 -0
  345. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_client.py +0 -0
  346. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_client_character.py +0 -0
  347. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_client_delete_characters.py +0 -0
  348. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_client_generate_character.py +0 -0
  349. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_client_image.py +0 -0
  350. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_client_launch_kwargs.py +0 -0
  351. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_client_patch_entity.py +0 -0
  352. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_client_scene.py +0 -0
  353. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_client_upscale.py +0 -0
  354. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_concurrency.py +0 -0
  355. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_dto.py +0 -0
  356. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_engine.py +0 -0
  357. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_image.py +0 -0
  358. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_image_dto.py +0 -0
  359. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_image_upscale.py +0 -0
  360. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_post_json_aisandbox_auth.py +0 -0
  361. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_recaptcha.py +0 -0
  362. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_retry.py +0 -0
  363. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_routes.py +0 -0
  364. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_routes_character.py +0 -0
  365. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_routes_scene.py +0 -0
  366. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_sapisidhash_helper.py +0 -0
  367. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_scene_models.py +0 -0
  368. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_video.py +0 -0
  369. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/test_video_request.py +0 -0
  370. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/__init__.py +0 -0
  371. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/conftest.py +0 -0
  372. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/drivers/__init__.py +0 -0
  373. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/drivers/test_factory.py +0 -0
  374. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_base.py +0 -0
  375. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_bearer.py +0 -0
  376. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_common.py +0 -0
  377. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_evaluate_fetch.py +0 -0
  378. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_factory.py +0 -0
  379. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_fingerprint.py +0 -0
  380. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_sapisidhash.py +0 -0
  381. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_selector_symmetry.py +0 -0
  382. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_transport_timeout.py +0 -0
  383. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_ui_automation.py +0 -0
  384. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_ui_automation_batch.py +0 -0
  385. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_ui_automation_image_mode.py +0 -0
  386. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/api/transports/test_ui_character_editor.py +0 -0
  387. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/auth/strategies/test_factory.py +0 -0
  388. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/auth/strategies/test_strategies.py +0 -0
  389. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/auth/test_cookies.py +0 -0
  390. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/auth/test_verification.py +0 -0
  391. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/__init__.py +0 -0
  392. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_auth_list.py +0 -0
  393. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_character.py +0 -0
  394. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_character_create.py +0 -0
  395. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_data.py +0 -0
  396. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_image_seed_removed.py +0 -0
  397. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_image_selector_drift.py +0 -0
  398. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_image_upscale.py +0 -0
  399. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_instructions.py +0 -0
  400. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_models.py +0 -0
  401. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_movie.py +0 -0
  402. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_run.py +0 -0
  403. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_scene.py +0 -0
  404. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_tools.py +0 -0
  405. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_video.py +0 -0
  406. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_cli_video_chain.py +0 -0
  407. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_error_handling.py +0 -0
  408. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_helpers.py +0 -0
  409. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_movie_manifest.py +0 -0
  410. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_movie_manifest_style_variants.py +0 -0
  411. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_settings_validation.py +0 -0
  412. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/cli/test_t2i_multi_prompt.py +0 -0
  413. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/composition/test_character.py +0 -0
  414. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/composition/test_compose_prompt.py +0 -0
  415. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/composition/test_handoff.py +0 -0
  416. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/composition/test_style_variants.py +0 -0
  417. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/composition/test_style_variants_e2e.py +0 -0
  418. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/conftest.py +0 -0
  419. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/data/__init__.py +0 -0
  420. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/data/test_chain_repo.py +0 -0
  421. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/data/test_find_incomplete_character.py +0 -0
  422. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/data/test_models.py +0 -0
  423. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/data/test_packaging.py +0 -0
  424. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/data/test_redaction.py +0 -0
  425. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/data/test_repository.py +0 -0
  426. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/data/test_scene_persistence.py +0 -0
  427. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/data/test_settings_and_errors.py +0 -0
  428. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/data/test_store_migrations.py +0 -0
  429. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/dev/test_recording_client.py +0 -0
  430. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/__init__.py +0 -0
  431. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/conftest.py +0 -0
  432. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_aisandbox_auth_live.py +0 -0
  433. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_auth_verification_e2e.py +0 -0
  434. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_chain_e2e.py +0 -0
  435. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_character_create_e2e.py +0 -0
  436. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_daemon_e2e.py +0 -0
  437. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_data_layer_e2e.py +0 -0
  438. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_i2v_flags_e2e.py +0 -0
  439. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_image_batch_e2e.py +0 -0
  440. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_image_i2i_ref_cap_e2e.py +0 -0
  441. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_json_output_e2e.py +0 -0
  442. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_live_agentic_instructions.py +0 -0
  443. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_locale_selectors_e2e.py +0 -0
  444. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_scene_compose_live.py +0 -0
  445. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_tools_e2e.py +0 -0
  446. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_transports_e2e.py +0 -0
  447. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_video_r2v_ref_cap_e2e.py +0 -0
  448. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/e2e/test_video_t2v_e2e.py +0 -0
  449. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/__init__.py +0 -0
  450. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/auth.feature +0 -0
  451. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/auth_login.feature +0 -0
  452. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/character_create.feature +0 -0
  453. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/character_read.feature +0 -0
  454. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/conftest.py +0 -0
  455. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/image.feature +0 -0
  456. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/image_upscale.feature +0 -0
  457. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/instructions.feature +0 -0
  458. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/locale_picker_include.feature +0 -0
  459. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/test_auth_login_steps.py +0 -0
  460. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/test_auth_steps.py +0 -0
  461. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/test_character_create_steps.py +0 -0
  462. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/test_character_read_steps.py +0 -0
  463. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/test_image_steps.py +0 -0
  464. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/test_image_upscale_steps.py +0 -0
  465. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/test_instructions_steps.py +0 -0
  466. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/test_locale_picker_include_steps.py +0 -0
  467. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/test_step_collision_guard.py +0 -0
  468. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/test_video_chain_steps.py +0 -0
  469. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/video_agent_ui.feature +0 -0
  470. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/features/video_chain.feature +0 -0
  471. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/fixtures/__init__.py +0 -0
  472. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/fixtures/seeded_catalog.py +0 -0
  473. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/image_batch/__init__.py +0 -0
  474. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/integration/__init__.py +0 -0
  475. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/integration/conftest.py +0 -0
  476. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/integration/constants.py +0 -0
  477. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/integration/test_storage_gcs.py +0 -0
  478. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/integration/test_storage_s3.py +0 -0
  479. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/mcp/__init__.py +0 -0
  480. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/mcp/conftest.py +0 -0
  481. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/mcp/test_cli_parity.py +0 -0
  482. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/mcp/test_server.py +0 -0
  483. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/mcp/test_stdio_transport.py +0 -0
  484. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/mcp/test_tools_helpers.py +0 -0
  485. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/mcp/test_tools_instructions.py +0 -0
  486. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/scripts/test_analyze_agent_ui_capture.py +0 -0
  487. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/scripts/test_capture_locale_invariants.py +0 -0
  488. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/scripts/test_check_materiality.py +0 -0
  489. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/scripts/test_check_repo_hygiene.py +0 -0
  490. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/scripts/test_materiality_backtest.py +0 -0
  491. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/services/__init__.py +0 -0
  492. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/services/test_character_create_redaction.py +0 -0
  493. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/services/test_character_create_saga.py +0 -0
  494. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/services/test_character_gen_no_direct_post.py +0 -0
  495. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/smoke/__init__.py +0 -0
  496. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/smoke/test_profile_account_smoke.py +0 -0
  497. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/smoke/test_real_flow.py +0 -0
  498. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_auth.py +0 -0
  499. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_browser_manager.py +0 -0
  500. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_chain.py +0 -0
  501. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_chain_manifest.py +0 -0
  502. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_cli_data.py +0 -0
  503. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_config.py +0 -0
  504. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_conftest_isolation.py +0 -0
  505. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_data_queries.py +0 -0
  506. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_documentation_gate.py +0 -0
  507. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_errors_403.py +0 -0
  508. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_json_output.py +0 -0
  509. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_manifest.py +0 -0
  510. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_marker_registry.py +0 -0
  511. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_media.py +0 -0
  512. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_observability.py +0 -0
  513. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_paths.py +0 -0
  514. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_profile_store.py +0 -0
  515. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/test_smoke.py +0 -0
  516. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/tools/__init__.py +0 -0
  517. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/tools/test_banned.py +0 -0
  518. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/tools/test_expander.py +0 -0
  519. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/tools/test_invocation.py +0 -0
  520. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/tools/test_loader.py +0 -0
  521. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/tools/test_registry.py +0 -0
  522. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/tools/test_runtime.py +0 -0
  523. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/tools/test_spec.py +0 -0
  524. {gflow_cli-0.29.0 → gflow_cli-0.31.0}/tests/ui/test_app.py +0 -0
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.31.0] — 2026-07-10
11
+
12
+ ### Fixed
13
+
14
+ - **Agentic image generation no longer risks attributing a pre-existing project asset to the current request.** `await_images` settled its new-media baseline with a single DOM scrape, which could miss a lazily-rendered pre-existing tile and let `_build_generated_images` slice an arbitrary UUID out of an unordered set as "the" generated image — the 2026-07-10 production incident: an old project logo was silently downloaded and reported as a fresh generation. The baseline is now the **union of two `_scrape_img_srcs` passes** one poll interval apart, absorbing lazy-render stragglers before they're mistaken for new media, and if more new UUIDs still appear than were requested, `await_images` now fails fast with the new `MediaAttributionError` (**exit code 26**, RFC 9457 type `media-attribution`) naming every candidate UUID and the expected count instead of guessing (#281).
15
+ - **A pre-download attribution guard now runs ahead of every image download, with `DataIntegrityError` escalated instead of warned.** Even a driver that never hits the agentic ambiguity check above can still hand back a `flow_media_id` already recorded for the profile. `OperationRecorder.verify_media_attribution()` (called from `cli_image.py`, `image_batch.py`'s manifest batch path, and `FlowWorker.process_task`) checks `is_media_recorded()` before `_download_images` and raises `MediaAttributionError` rather than downloading — it also now rejects an intra-batch duplicate `flow_media_id` (the classic transport can return the same media twice in one submission) with no DB lookup needed. Separately, a `DataIntegrityError` from the recorder's `UNIQUE(profile_name, flow_media_id)` constraint — previously caught by the generic `DataStoreError` path and reported as a warn-only "Generated media was saved, but local history was not updated." — now escalates to the same `MediaAttributionError` when (and only when) the failing write is that exact constraint (`route == "data.upsert_asset"`); any other `DataIntegrityError` (e.g. an unrelated `insert_operation`/`link_operation_asset` failure) falls through to the ordinary warn-and-continue path instead of being mislabeled as a media collision. The escalation message now names the full candidate set of `flow_media_id`s / saved paths ("one of ...") rather than always fingering the first image, since the colliding index can't be recovered from sqlite's bare constraint violation (#281).
16
+ - **The pre-download attribution guard and the collision-escalation logic are each now a single shared implementation instead of three near-identical copies.** Both originally shipped duplicated across `cli_image.py`, `image_batch.py`, and `worker/daemon.py` (each call site already held a recorder instance), which tripped SonarCloud's duplicated-lines gate. The guard is consolidated onto `OperationRecorder.verify_media_attribution()`; the escalation is consolidated onto the new `gflow_cli.data.recorder.escalate_asset_collision()` — both with no behavior change beyond the route-scoping and intra-batch-duplicate fixes above (#281, #282, #283).
17
+ - **`gflow image batch` (the manifest path) now honors `--continue-on-error` for a media-attribution collision.** A collision on one row — from either the pre-download guard or the post-download collision escalation — used to propagate out of the whole batch run regardless of `--continue-on-error`, discarding every other row's already-completed outcome. With `--continue-on-error` the colliding row is now marked as a normal "fail" outcome (nothing was downloaded/recorded for that row) and the batch continues; without it, the collision still aborts the run as before (#281, #282).
18
+ - **`--ref <uuid>` picker selection now resolves every ref, not just the first.** `_select_existing_asset` gave up as soon as a tile wasn't in the initial viewport or surfaced by the display-name search, so any `--ref` after the first raised `TransportTimeoutError` once the virtualised (react-virtuoso) media grid hadn't rendered it yet. It now falls back to scrolling and re-checking between scrolls, mirroring the entity picker's `_find_picker_entity_tile` strategy, and `_attach_image_uuid_refs` clears the picker search input at the start of every ref iteration so a search typed while resolving one ref can't shadow the next ref's tile lookup. `_select_existing_asset` itself now also clears a failed display-name search before falling back to scrolling, so it doesn't scroll a grid still filtered by the failed term (#282).
19
+
20
+ ## [0.30.0] — 2026-07-09
21
+
22
+ ### Added
23
+
24
+ - **MCP `gflow_generate_video` model/duration/count parameters (CLI↔MCP parity):** agents can now select the Veo model (`veo_lite`/`veo_fast`/`veo_quality`/`omni_flash`, aliases accepted), clip duration, and batch count through MCP, matching the CLI `gflow video` flags. An unknown model is rejected up front with a 400 instead of failing deep in the worker; an omitted model still lets the transport apply its i2v veo-lite default (issue #125). Co-authored-by C1ph3r404 (from the closed PR #258). Note: the pre-existing transport-level i2v veo-lite default already protected the MCP path, so this is parity + agent control, not a new credit guard.
25
+
26
+ ### Fixed
27
+
28
+ - **Character-create recorder no longer crashes on a duplicated `flow_media_id`.** Under the agentic cohort the classic character-editor slot-add control is absent, so the body prompt lands in the still-active face slot and both slots report the same `flow_media_id`; `_record_character_local_files` minted a fresh asset `id` per slot and the second slot violated `UNIQUE(profile_name, flow_media_id)` → `DataIntegrityError`. The recorder now reuses the existing asset id (mirroring `record_completed_video`), making character local-file recording idempotent on the business key. Regression test in `tests/data/test_recorder_character.py`.
29
+ - **`prefer_classic` no longer logs a misleading `WARNING` on the agentic cohort.** The server-gated agentic (`tune`) cohort cannot be exited client-side, and `prefer_classic` is best-effort by contract, so `get_ui_driver` now logs that expected fall-through at `INFO` (`ui_driver.prefer_classic.cohort_natively_agentic`) and reserves `WARNING` for genuinely unexpected exit failures.
30
+
10
31
  ## [0.29.0] — 2026-07-09
11
32
 
12
33
  ### Added
@@ -1887,7 +1908,8 @@ shell-script template that branches on these codes.
1887
1908
 
1888
1909
  First skeleton. Not functional end-to-end yet.
1889
1910
 
1890
- [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.29.0...HEAD
1911
+ [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.30.0...HEAD
1912
+ [0.30.0]: https://github.com/ffroliva/gflow-cli/compare/v0.29.0...v0.30.0
1891
1913
  [0.29.0]: https://github.com/ffroliva/gflow-cli/compare/v0.28.0...v0.29.0
1892
1914
  [0.28.0]: https://github.com/ffroliva/gflow-cli/compare/v0.27.1...v0.28.0
1893
1915
  [0.27.1]: https://github.com/ffroliva/gflow-cli/compare/v0.27.0...v0.27.1
@@ -0,0 +1,37 @@
1
+ # GEMINI.md
2
+
3
+ > Project memory hub for **Gemini CLI**. The universal coding-agent rules for any tool (Cursor, Codex, Aider, Gemini CLI, etc.) live in [AGENTS.md](AGENTS.md) — this file carries Gemini-specific session protocol only.
4
+
5
+ ## What this project is
6
+
7
+ `gflow-cli` is an unofficial Python CLI that drives [Google Flow](https://labs.google/fx/tools/flow) (Veo image-to-video, Imagen text-to-image) from the terminal by reverse-engineering Flow's private REST API. See [README.md](README.md) for the user-facing overview.
8
+
9
+ ## On every session start
10
+
11
+ 1. Read **[AGENTS.md](AGENTS.md)** — universal rules every agent must follow.
12
+ 2. Read **[docs/INDEX.md](docs/INDEX.md)** — routing layer for all project docs and commands.
13
+ 3. Pull deeper context on demand (type as plain text in the `agy` TUI prompt):
14
+ - Current task / where we left off → `gflow:status`
15
+ - Starting a new feature → `gflow:predict` → `gflow:scenario` → `gflow:plan <feature>`
16
+ - Touching auth or reCAPTCHA → `gflow:known-issues`
17
+ - Cutting a release → `gflow:release`
18
+ - Before any commit → `gflow:check`
19
+
20
+ ## Gemini-specific
21
+
22
+ - Use specialized skills when relevant (e.g., `find-docs` for library research, `pr-council-review` for PR audits).
23
+ - Maintain memory via the `mcp-mempalace` tool if available.
24
+ - Prioritize **turn efficiency** and **high-signal output**.
25
+
26
+ ## Active phase
27
+
28
+ - **v0.29.0 shipped (2026-07-09):** persistent `gflow instructions` CRUD + movie-manifest instructions brief-sync + six `gflow_instructions_*` MCP tools, with a CI-enforced MCP↔CLI parity contract (`tests/mcp/test_cli_parity.py`) and the agentic-indicator selectors consolidated onto `drivers/factory.py`. Released to PyPI; issue #192 closed.
29
+ - **PR #258 (Camoufox stealth engine, external contribution) — taken over and CLOSED-OUT (2026-07-09).** A 5-persona `/gflow:predict` rejected a rebase in favour of a decomposed, evidence-gated series: Phase 1 landed the MCP video param parity (#273, contributor-credited); a WAF-evidence harness (#274/#275) measured a **0.0% WAF 403 rate over 20 live generations**, so per ADR-13 the Camoufox engine was **NOT built** (#276). The i2i "UUID-ref bug" was investigated and found not-a-bug (#277, stale comment fixed). Contributor thanked + credited on the closed PR. Evidence: `docs/superpowers/spikes/2026-07-09-camoufox-waf-403.md`.
30
+ - **Decoupled Daemon/Worker Plan:** The MCP→FlowWorker wiring shipped in v0.23.0 (PR #228). The remaining headless SSE Daemon + Tauri/React editor blueprint is scheduled in [gflow-studio-scaffold/PLAN.md](file:///C:/development/github/gflow-cli/docs/superpowers/plans/2026-06-24-gflow-studio-scaffold/PLAN.md) and [rest-api-layer/PLAN.md](file:///C:/development/github/gflow-cli/docs/superpowers/plans/2026-06-24-rest-api-layer/PLAN.md).
31
+ - **Core Lesson (Retrospective):**
32
+ - **Verify before adopting — measure, don't assume.** The PR #258 takeover's value was checking every claim against the real code and real data instead of adopting on assertion: a stealth engine we didn't build (0% WAF baseline), a "credit guard" already enforced one layer down, a `display_name` already shipped in v0.26.0, an i2i "bug" that wasn't one, and a concurrency bug that never merged. Five claims, five dismissals — the cheapest correct outcome came from investigation, not implementation.
33
+ - **ADR gates pay for themselves.** ADR-13 ("confirm the current stealth fix insufficient before implementing an alternative") turned a "build Camoufox" epic into a one-afternoon 20-generation spike that said "don't." Encode the gate as a runnable measurement (`scripts/spike_waf_camoufox.py`), not a debate.
34
+ - **Decompose contested external PRs; never rebase a branch that's 60+ commits behind.** Cherry-pick/re-express the genuinely-valuable pieces onto fresh branches with `Co-authored-by` credit, evidence-gate the risky parts, and split by concern — one PR per slice.
35
+ - Kept `gflow-cli` strictly headless (Uvicorn + FastMCP over localhost HTTP/SSE); browser-context locks bypassed by serializing task writes in the SQLite queue with WAL-mode parallel reads. Relational instruction cards must be phrased conversationally (imperative prompts bypass the brief); multi-scene movie sync is read-modify-write to preserve server-assigned card IDs.
36
+
37
+ See [PLAN.md](PLAN.md) or type `gflow:status` for the current task. Type `gflow:plan <feature>` to create a new feature plan.
@@ -663,6 +663,108 @@ key — surfaces as a `RuntimeError` that `auth/cookies.py` normalizes to
663
663
 
664
664
  ## Resolved
665
665
 
666
+ ### Agentic image generation could silently attribute a pre-existing project asset as the "generated" image
667
+
668
+ - **Status:** Resolved · **Severity:** Was-High (wrong file downloaded and reported as success, silently) · **Was-affecting:** the agentic driver through v0.30.0 (and, for the pre-download guard below, every transport) · **Fixed in:** unreleased (0.31.0) · **Tracked:** [#281](https://github.com/ffroliva/gflow-cli/issues/281); related picker fix [#282](https://github.com/ffroliva/gflow-cli/issues/282)
669
+
670
+ Discovered 2026-07-10 in a live production run: `gflow image t2i` under the
671
+ agentic driver downloaded an **old project logo** and reported it as a freshly
672
+ generated "portrait" — no error, just the pre-existing warn-only line
673
+ `"Generated media was saved, but local history was not updated."` — and 11
674
+ downstream `i2i` scenes were then anchored to the wrong file.
675
+
676
+ **Root cause — two defects in `await_images` (agentic driver):**
677
+ 1. The new-media baseline was a **single** DOM scrape (`_scrape_img_srcs`); a
678
+ pre-existing tile that rendered lazily (after generation had already
679
+ started) was missed by that scrape and then counted as "new" once it
680
+ appeared.
681
+ 2. `_build_generated_images` sliced an **unordered** UUID set down to
682
+ `expected_count` — an arbitrary pick when more "new" UUIDs were present
683
+ than were actually requested, with no signal for which UUID(s) belonged to
684
+ this generation.
685
+
686
+ **A third, independent gap** existed downstream of the driver: even a transport
687
+ that never hits the agentic DOM-scrape path above could still hand back a
688
+ `flow_media_id` already present in local history for the profile. That case
689
+ was caught by the generic `DataStoreError` path, which only warned and
690
+ continued — a silently duplicated/misattributed history row, not a hard
691
+ failure.
692
+
693
+ **Fix — three defense layers, all raising the new `MediaAttributionError`
694
+ (exit code 26, RFC 9457 type `media-attribution`) instead of a silent or
695
+ warn-only outcome:**
696
+ 1. **Baseline settle.** The baseline is now the **union of two
697
+ `_scrape_img_srcs` passes** one poll interval apart, absorbing lazy-render
698
+ stragglers before they can be mistaken for new media.
699
+ 2. **Ambiguity fail-fast.** If more new UUIDs still appear than were
700
+ requested, `await_images` raises `MediaAttributionError` naming every
701
+ candidate UUID and the expected count, rather than guessing via
702
+ `_build_generated_images`'s old arbitrary slice.
703
+ 3. **Pre-download attribution guard + collision escalation.**
704
+ `OperationRecorder.verify_media_attribution()` (called from `cli_image.py`,
705
+ `image_batch.py`'s manifest batch path, and the worker daemon's
706
+ `FlowWorker.process_task`; consolidated onto the recorder in #283 after
707
+ shipping as three near-identical module-level copies) checks
708
+ `is_media_recorded()` and raises before any download if the driver
709
+ returned a `flow_media_id` already recorded for the profile.
710
+ Separately, a `DataIntegrityError` from the recorder's
711
+ `UNIQUE(profile_name, flow_media_id)` constraint now escalates to
712
+ `MediaAttributionError` (naming the suspect file) instead of being caught
713
+ by the generic `DataStoreError` warn-only path.
714
+
715
+ Precedent for this class of fix: the `--model` silent no-op entry below (same
716
+ section) — an error the user sees beats a wrong artifact reported as success.
717
+
718
+ **Related, but distinct.** [#282](https://github.com/ffroliva/gflow-cli/issues/282)
719
+ fixed a separate defect in the same media-picker surface (`--ref <uuid>`
720
+ selection failing on any ref after the first once the virtualised
721
+ (react-virtuoso) grid needed to scroll to render it) — a picker-navigation
722
+ bug, not a data-integrity one. [#174](https://github.com/ffroliva/gflow-cli/issues/174)
723
+ (open, in the "Open" section above) is a Flow-side full-page media-library
724
+ UI rollout that breaks entity attach on affected accounts — a different
725
+ code path, but the same general theme that the media-picker surface needs
726
+ ongoing hardening.
727
+
728
+ **Residual risk (post-fix, not fully closed).** The two-pass baseline settle
729
+ narrows the window, it doesn't remove it: the agentic poll loop still stops
730
+ scraping the moment the new-UUID count on a single scrape equals the
731
+ requested count. A pre-existing tile that lazy-renders *after* the 0.5s
732
+ baseline settle but *before* the real generation actually completes
733
+ (generations take 30–60s) lands inside that window at exactly the expected
734
+ count — the ambiguity fail-fast in layer 2 only triggers on an *excess* of
735
+ new UUIDs, so it never sees this case. Layer 3's pre-download guard and
736
+ collision escalation then only catch it if the misattributed asset happens
737
+ to already be in **local** history for the profile — an asset created in the
738
+ Flow web UI, generated on another machine, or recorded under a different
739
+ profile DB has no local history row to collide with, so it can still slip
740
+ through all three layers: wrong file on disk, exit 0. Mitigations until this
741
+ is closed: run generations in a dedicated, low-asset project (fewer
742
+ pre-existing tiles means a smaller lazy-render population to collide with),
743
+ and visually verify anchor/canonical images before referencing them
744
+ downstream in `i2i`. Follow-up hardening (a break condition stable across
745
+ two consecutive scrapes, not one) is tracked upstream against this issue.
746
+
747
+ **Known gap: the shell multi-prompt path records no history at all.**
748
+ `gflow run --config <file>` and `gflow image t2i` with multiple prompts
749
+ (positional, `--prompts-file`, or `--stdin`) both go through
750
+ `image_batch.run_image_batch` / `run_one_image_prompt`, which never opens an
751
+ `OperationRecorder` or calls `record_generated_images` — no local history row
752
+ is written for these runs at all. Layer 1 (the agentic driver's two-pass
753
+ baseline settle + ambiguity fail-fast in `await_images`) still applies since
754
+ it lives in the transport, independent of recording. Layers 2 and 3
755
+ (`verify_media_attribution`'s pre-download guard and the post-download
756
+ collision escalation) both depend on local history via
757
+ `OperationRecorder.is_media_recorded()` / `record_generated_images()`, so
758
+ neither guard exists on this path — this is a pre-existing gap, not a
759
+ regression from this fix. `gflow image batch` (the manifest path, via
760
+ `run_manifest_image_batch`) already threads a recorder through and is covered
761
+ by all three layers. Follow-up tracked in #283.
762
+
763
+ **Workaround (pre-fix):** none — on an affected version, manually verify the
764
+ downloaded file matches the prompt before trusting a `t2i`/`i2i` result.
765
+
766
+ ---
767
+
666
768
  ### Profile named `default` is opaque — no Google account identity
667
769
 
668
770
  - **Status:** Resolved · **Severity:** Was-Low (UX confusion, no data loss) · **Was-affecting:** all versions through v0.9.x · **Fixed in:** v0.10.0 via PR #110 (2026-05-28) · **Tracked:** issue #92
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gflow-cli
3
- Version: 0.29.0
3
+ Version: 0.31.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
@@ -653,6 +653,8 @@ Records image, batch, T2V, I2V, and R2V provenance in a local SQLite catalog. Re
653
653
 
654
654
  **Status:** NOT implemented. Parked until the stealth-flag fix (`--disable-blink-features=AutomationControlled` + init script) is confirmed insufficient, or until a contributor picks it up.
655
655
 
656
+ **2026-07-09 verification — the current stealth fix is CONFIRMED SUFFICIENT (so this stays parked).** A 20-generation baseline on a live authed profile through the default stealth stack produced a **0.0% WAF 403 rate** (19/20 success; the one miss was a UI-scrape timeout, not a WAF block). This met ADR-13's "must verify before implementing" gate and closed the [Camoufox adoption roadmap](superpowers/plans/2026-07-09-camoufox-adoption/PLAN.md) at Phase 2 — the Camoufox engine was NOT built. Evidence: [superpowers/spikes/2026-07-09-camoufox-waf-403.md](superpowers/spikes/2026-07-09-camoufox-waf-403.md). Re-run `scripts/spike_waf_camoufox.py` if a repeatable WAF-403 is later observed; a materially non-zero rate would reopen CDP-Attach / Camoufox.
657
+
656
658
  ---
657
659
 
658
660
  ### Phase 8 — Pluggable storage backend — BACKLOG
@@ -699,7 +701,7 @@ Today the CLI writes media to `$GFLOW_CLI_OUTPUT_DIR` on the local filesystem. P
699
701
  | 10 | Both `gflow` and `flow` binary names installed | `flow` is friendlier; `gflow` avoids conflicts with Facebook Flow / MS Power Automate |
700
702
  | 11 | LF-only line endings via `.gitattributes` | Single repo source of truth; cross-platform contributors don't think about it |
701
703
  | 12 | `Provider` indirection (legacy `providers/`) removed | Superseded by `api.FlowApiClient`. Re-introduce when we add `OfficialVeoProvider` (planned v0.5+) |
702
- | 13 | CDP attach transport deferred | Must first confirm whether CDP-attached Chrome still sets `navigator.webdriver=true` (which would negate any reCAPTCHA advantage over the current stealth fix). See CDP Attach backlog entry. |
704
+ | 13 | CDP attach / stealth-engine alternatives deferred; **current stealth fix confirmed sufficient 2026-07-09** | Gate met: a 20-gen live baseline through the default stealth stack showed a **0.0% WAF 403 rate**, so the "confirm insufficient before implementing" bar is unmet — CDP-Attach and the Camoufox engine stay parked (Camoufox roadmap closed at Phase 2). Evidence: [superpowers/spikes/2026-07-09-camoufox-waf-403.md](superpowers/spikes/2026-07-09-camoufox-waf-403.md). |
703
705
  | 14 | HTTP status path (`get_video_status`) retired alongside `generate_video` | It is the same 401-dead path and would collide with the new `api/video.py:VideoStatus` value object — retiring both together keeps the domain clean. |
704
706
 
705
707
  ---
@@ -122,7 +122,7 @@ Slash commands for Claude Code, stored in `.claude/commands/gflow/`. All prefixe
122
122
  **"A gflow command hangs / fails — where do I start?"** → [DEBUGGING § Quick reference](DEBUGGING.md#quick-reference)
123
123
  **"Flow's UI broke a selector — how do I diagnose it?"** → [DEBUGGING § Inspecting Flow's live UI](DEBUGGING.md#inspecting-flows-live-ui)
124
124
  **"What does each `ui_automation.*` log event mean?"** → [DEBUGGING § Listener & HTTP-layer debugging](DEBUGGING.md#listener--http-layer-debugging)
125
- **"What was actually live-verified for the latest release?"** → latest: [LIVE_VERIFICATION_v0.29.0](LIVE_VERIFICATION_v0.29.0.md) (**persistent `gflow instructions` CRUD proven live e2e GREEN, credit-free** — 11-command sequence on a fresh project: add incl. `--ref <image-UUID>` attach, list/enable/disable, master toggle both ways, TOML `apply` destructive full-sync with `enabled=false` honored, `rm` with server card-id preserved across mutations; movie brief-sync code-path-verified via the same primitives, deferred-with-reason on credits; MCP `gflow_instructions_*` tools are thin adapters over the live-verified primitives). Prior: [v0.28.0](LIVE_VERIFICATION_v0.28.0.md) (**agent instructions `-i` now steer agentic generation — crayon e2e GREEN**: a style-neutral prompt + an enabled "crayon" card produced an unmistakable crayon drawing through the real transport; root causes were conversational phrasing + the `project_brief.enabled` master switch). Prior: [v0.27.1](LIVE_VERIFICATION_v0.27.1.md) (**v0.27.0 release follow-up fixes and documentation sync**). Prior: [v0.27.0](LIVE_VERIFICATION_v0.27.0.md) (**`[style]` block with named variants + prompt-aware resume — credit-free CLI verification**: real `movie run --dry-run` 3-way ledger proving resolved-style display, `skip (done)` on matching `style_hash`, and `re-run (style changed)` after a style edit; composition is local, wire path untouched, so no Veo credits spent — first credited styled run will confirm visually). Prior: [v0.26.0](LIVE_VERIFICATION_v0.26.0.md) (**image i2i by generated-image UUID proven live e2e GREEN** — the existing asset is *selected in place* by its media UUID, no duplicate upload, producing an i2i output that references it; plus generated-image `display_name` capture, credited @C1ph3r404). Prior: [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)
125
+ **"What was actually live-verified for the latest release?"** → latest: [LIVE_VERIFICATION_v0.31.0](LIVE_VERIFICATION_v0.31.0.md) (**#281 wrong-media defenses live-verified in BOTH directions, credit-free** — correct attribution downloads with real wire metadata [seed, 768×1376]; the incident-class lazy-render ambiguity reproduced live and hard-stopped with `MediaAttributionError` exit 26 naming every candidate UUID, no file written; **#282 two-UUID-ref i2i proven e2e** — both freshly generated portrait UUIDs picker-selected into one scene with both canonical identities visually transferred). Prior: [v0.30.0](LIVE_VERIFICATION_v0.30.0.md) (**agentic-cohort image path + both fixes live-verified credit-free** — native 768×1376 stills, i2i-chain + canonical-ref identity hold; the character-create `DataIntegrityError` and the `prefer_classic` WARNING were observed live then fixed [recorder idempotent + INFO log]; MCP video-param feature deferred-with-reason on Veo credits, per the stills-only goal). Prior: [v0.29.0](LIVE_VERIFICATION_v0.29.0.md) (**persistent `gflow instructions` CRUD proven live e2e GREEN, credit-free** — 11-command sequence on a fresh project: add incl. `--ref <image-UUID>` attach, list/enable/disable, master toggle both ways, TOML `apply` destructive full-sync with `enabled=false` honored, `rm` with server card-id preserved across mutations; movie brief-sync code-path-verified via the same primitives, deferred-with-reason on credits; MCP `gflow_instructions_*` tools are thin adapters over the live-verified primitives). Prior: [v0.28.0](LIVE_VERIFICATION_v0.28.0.md) (**agent instructions `-i` now steer agentic generation — crayon e2e GREEN**: a style-neutral prompt + an enabled "crayon" card produced an unmistakable crayon drawing through the real transport; root causes were conversational phrasing + the `project_brief.enabled` master switch). Prior: [v0.27.1](LIVE_VERIFICATION_v0.27.1.md) (**v0.27.0 release follow-up fixes and documentation sync**). Prior: [v0.27.0](LIVE_VERIFICATION_v0.27.0.md) (**`[style]` block with named variants + prompt-aware resume — credit-free CLI verification**: real `movie run --dry-run` 3-way ledger proving resolved-style display, `skip (done)` on matching `style_hash`, and `re-run (style changed)` after a style edit; composition is local, wire path untouched, so no Veo credits spent — first credited styled run will confirm visually). Prior: [v0.26.0](LIVE_VERIFICATION_v0.26.0.md) (**image i2i by generated-image UUID proven live e2e GREEN** — the existing asset is *selected in place* by its media UUID, no duplicate upload, producing an i2i output that references it; plus generated-image `display_name` capture, credited @C1ph3r404). Prior: [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)
126
126
  **"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.
127
127
  **"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)
128
128
  **"What was live-verified for the video-download feature (#29)?"** → [LIVE_VERIFICATION_video_download](LIVE_VERIFICATION_video_download.md)
@@ -0,0 +1,53 @@
1
+ # Live Verification — v0.30.0
2
+
3
+ Release gate evidence for the user-facing changes in v0.30.0, using the 5-layer
4
+ ledger (file count · magic bytes · dimensions/shape · structlog invariants ·
5
+ user-confirmable artifact). Credit-free wherever possible.
6
+
7
+ ## Scope of v0.30.0
8
+
9
+ - **Added:** MCP `gflow_generate_video` model/duration/count parameters (CLI↔MCP parity, #125).
10
+ - **Fixed:** agentic character-recorder idempotency (DataIntegrityError); `prefer_classic`
11
+ WARNING→INFO on the server-gated agentic cohort.
12
+
13
+ ---
14
+
15
+ ## 1. Agentic-cohort image path + both Fixed items — LIVE, credit-free ✅
16
+
17
+ Exercised end-to-end on **2026-07-09** against live Flow (account `denon82`, **agentic**
18
+ cohort) as part of the parable image-consistency spike. Image generation is **credit-free**
19
+ (no Veo credits).
20
+
21
+ - **File count:** multiple stills downloaded per run (t2i baseline, i2i chain, canonical-ref,
22
+ multi-ref) — 1 file per generation, all present on disk.
23
+ - **Magic bytes:** JPEG (`ffprobe`-decodable) for every downloaded still.
24
+ - **Dimensions/shape:** **768×1376** (native 9:16) on every generation — the no-crop invariant
25
+ held under the agentic cohort.
26
+ - **Structlog invariants:** the two Fixed conditions were **observed live** before the fix and
27
+ are now handled:
28
+ - `ui_driver.prefer_classic.exit_agent_failed` (WARNING) fired on the agentic (`tune`) cohort —
29
+ now logged at INFO (`ui_driver.prefer_classic.cohort_natively_agentic`); best-effort by contract.
30
+ - `character create` on the agentic cohort raised `DataIntegrityError`
31
+ (`UNIQUE constraint failed: assets.profile_name, assets.flow_media_id`) — now idempotent
32
+ (recorder reuses the existing asset id). Covered by regression test
33
+ `tests/data/test_recorder_character.py::test_record_character_completed_duplicate_media_id_is_idempotent`.
34
+ - **User-confirmable artifact:** the side-by-side still gallery + scorecard recorded in the
35
+ consuming project's spike results (`out/spike/…` + `docs/superpowers/specs/2026-07-09-parable-image-consistency-spike-results.md`).
36
+
37
+ ## 2. MCP `gflow_generate_video` params (#125) — deferred this cycle, unit-test-covered ⚠️
38
+
39
+ This feature is exercised only by **video generation**, which **costs Veo credits**, and the
40
+ consuming pipeline's explicit goal this cycle is **stills-only (skip video generation)**. Per the
41
+ release gate's escape hatch, it is **not live-verified this cycle** for that reason — it is **not
42
+ silently omitted**. Coverage:
43
+
44
+ - Unit/contract tests: `tests/mcp/` (including the MCP↔CLI parity contract
45
+ `tests/mcp/test_cli_parity.py`) — model/duration/count validation and the 400-on-unknown-model
46
+ path are covered without spending credits.
47
+ - Recommended follow-up: a credit-spending i2v smoke on the next cycle that budgets Veo credits.
48
+
49
+ ---
50
+
51
+ **Gate summary:** ruff ✓ · format ✓ · pyright 0 errors ✓ · pytest 2145 passed / 7 skipped ✓ ·
52
+ repo-hygiene exit 0 ✓. Agentic image path + both fixes live-verified credit-free; MCP video
53
+ feature deferred with documented reason.
@@ -0,0 +1,83 @@
1
+ # Live Verification — v0.31.0
2
+
3
+ **Date:** 2026-07-10 · **Profile:** `denon82` · **Project:** `f6caf027-ad68-49e3-aac9-ee32f1582bf3`
4
+ (the standing production project — deliberately asset-heavy, i.e. the exact environment of the
5
+ 2026-07-10 wrong-media incident this release fixes) · **Build:** develop @ `ecfb5ed`
6
+ (merge of PR #285) run via `uv run gflow` · **Model:** nano-pro · **Aspect:** 9:16 ·
7
+ **Credit cost:** 0 Veo credits (image generation only).
8
+
9
+ Features under verification (CHANGELOG `[Unreleased]` → 0.31.0):
10
+ 1. **#281 layer 1** — agentic ambiguity fail-fast + two-pass baseline settle (`MediaAttributionError`, exit 26)
11
+ 2. **#281 layers 2/3** — pre-download attribution guard + route-scoped collision escalation
12
+ 3. **#282** — UUID `--ref` picker: virtualised-grid scroll + search-state hygiene
13
+
14
+ ## Run 1 — t2i portrait (musician): correct attribution end-to-end ✅
15
+
16
+ `gflow image t2i "<musician portrait prompt>" --model nano-pro --aspect 9:16 --project f6caf027-… --out <dir>`
17
+
18
+ 5-layer ledger:
19
+ 1. **File count:** exactly 1 file produced: `98a404e7-766d-443c-9385-a16fdb37c799_1.jpg` (886,886 bytes; sha256 `e25e96be454f0215…`).
20
+ 2. **Magic bytes:** `ff d8 ff` (JPEG).
21
+ 3. **Dimensions:** 768×1376 (native 9:16, no crop).
22
+ 4. **Structlog invariants:** real wire metadata surfaced — `seed=648895`, `dimensions=768x1376`
23
+ (not the agentic scrape sentinels seed=0/0x0); **no** `data.persistence_failed_after_success`
24
+ warning (the 0.30.0 incident's tell); recorder wrote history cleanly.
25
+ 5. **User-confirmable artifact:** image visually inspected — weathered street musician, late 50s,
26
+ grey beard, black beanie, worn dark jacket, guitar, plain neutral background, front view.
27
+ Exactly the prompt; NOT a pre-existing project asset. (Under 0.30.0 in this same project, this
28
+ exact call once returned an old brand logo.)
29
+
30
+ ## Run 2 — t2i portrait (mentor), attempt 1: ambiguity fail-fast fires ✅ (negative-path proof)
31
+
32
+ Same command shape, mentor prompt. The generation hit the incident-class condition live: the
33
+ asset-heavy project lazy-rendered multiple prior assets after the baseline settle, and the run
34
+ **failed loudly instead of guessing**:
35
+
36
+ - `MediaAttributionError` raised naming **every** candidate UUID (the list included
37
+ `6a0b44d5-…` and `64fc2c31-…` — assets generated earlier that day, i.e. genuinely pre-existing
38
+ media that 0.30.0 would have been free to silently download) plus the remediation text
39
+ ("Re-run the generation; a dedicated project with fewer pre-existing assets avoids lazy-render
40
+ ambiguity (issue #281)").
41
+ - **No file was written** for this attempt (output dir unchanged).
42
+
43
+ This is the strongest possible live evidence for #281: the exact failure environment reproduced,
44
+ and the new behavior is a actionable hard stop, not a wrong artifact with exit 0.
45
+
46
+ ## Run 2 — t2i portrait (mentor), attempt 2: clean ✅
47
+
48
+ Retry of the same command: 1 file `dacdc6ee-2725-4e5c-b08f-c7143c36d9b6_1.jpg` (591,180 bytes;
49
+ sha256 `e82cc96b3bba60cf…`; JPEG magic `ff d8 ff`; 768×1376; real `seed=744814`; no persistence
50
+ warning). Visually inspected: elegant silver-haired man, 60s, tailored black suit, pocket square,
51
+ neutral background — exactly the prompt.
52
+
53
+ ## Run 3 — i2i with two UUID `--ref`s (#282 picker) ✅
54
+
55
+ `gflow image i2i "<street scene prompt>" --ref dacdc6ee-… --ref 98a404e7-… --model nano-pro
56
+ --aspect 9:16 --project f6caf027-… --out <dir>` — both refs are the freshly generated portrait
57
+ UUIDs from Runs 1–2, attached by picker selection (no local file passed). Under v0.30.0 this exact
58
+ call failed structurally: only the first UUID was picker-selectable (#282).
59
+
60
+ Two attempts noted for completeness: attempt 1 failed pre-submission with
61
+ `UiSelectorDriftError probe=mode_switch_trigger` whose debug screenshot was an entirely black
62
+ viewport — a page-that-never-rendered transient, not selector drift; zero generations spent.
63
+ Attempt 2 succeeded.
64
+
65
+ 5-layer ledger:
66
+ 1. **File count:** exactly 1 file: `d6f1927a-3eae-4626-bc90-9a6ea7637bab_1.jpg` (670,708 bytes;
67
+ sha256 `fd828df1a33e37c0…`).
68
+ 2. **Magic bytes:** `ff d8 ff` (JPEG).
69
+ 3. **Dimensions:** 768×1376 (native 9:16).
70
+ 4. **Structlog invariants:** real `seed=244712`; both refs attached (no
71
+ "could not be selected in the picker" error, no upload fallback); no persistence warning.
72
+ 5. **User-confirmable artifact:** visually inspected — BOTH canonical identities transferred:
73
+ the mentor is the same silver-haired man from Run 2's portrait (same face, suit, and paisley
74
+ pocket square), the musician the same man from Run 1's (same beanie, beard, work jacket).
75
+ Monochrome street scene with the iridescent coin accent confined to the guitar case. No
76
+ pre-existing project asset leaked into the frame.
77
+
78
+ ## Verdict
79
+
80
+ All three release features live-verified: #281's defense layers in both directions (correct
81
+ attribution succeeds with ground-truth metadata; incident-class ambiguity hard-stops with
82
+ actionable output and no file written), and #282's multi-UUID-ref picker selection end-to-end —
83
+ which simultaneously validates the canonical-reference identity workflow the fixes exist to serve.
@@ -46,7 +46,7 @@ The server registers three protocol surfaces:
46
46
 
47
47
  ### Tools (Executable actions)
48
48
  * `gflow_generate_image(prompt, model, aspect, count, seed, reference_images, tools, profile, project, instructions)`: Triggers text-to-image / image-to-image (Imagen / Nano Banana). `instructions` is an optional list of ephemeral agent-instruction strings (agentic cohort only). `reference_images` switches to i2i and accepts **either a local file path or a generated image's Flow media UUID**. A UUID reference is attached by **selecting the already-existing asset in Flow's reference picker — no duplicate copy is uploaded** (locating the tile by the media id in its thumbnail URL, and searching the recorded display name to surface it when needed); gflow falls back to uploading the asset's on-disk local file only when it can't be located in place (e.g. it lives in a different project's picker). `project` generates into an existing Flow project id (mirrors CLI `--project`) — pass the reference's project to keep it selectable in place.
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).
49
+ * `gflow_generate_video(prompt, mode, aspect, initial_frame, end_frame, reference_images, model, duration, count, tools, profile, project)`: Triggers vertical or landscape video generation (Veo). `mode` is `t2v`/`i2v`/`r2v`; `model` (`veo_lite`/`veo_fast`/`veo_quality`/`omni_flash`, aliases accepted), `duration` (seconds), and `count` mirror the CLI `gflow video` flags — an omitted `model` lets the transport apply its i2v veo-lite default (issue #125), and `omni_flash` is rejected for i2v-with-frames; `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
  * `gflow_list_tools()`: Lists the prompt tools (name/title/description/category) accepted by the generate tools' `tools` param.