gflow-cli 0.9.0__tar.gz → 0.10.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 (342) hide show
  1. gflow_cli-0.10.0/.claude/commands/gflow/branch-review.md +13 -0
  2. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.claude/commands/gflow/check.md +5 -1
  3. gflow_cli-0.10.0/.claude/commands/gflow/pr-council-review.md +11 -0
  4. gflow_cli-0.10.0/.claude/commands/gflow/predict.md +19 -0
  5. gflow_cli-0.10.0/.claude/commands/gflow/scenario.md +23 -0
  6. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.env.template +28 -0
  7. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.github/PULL_REQUEST_TEMPLATE.md +2 -0
  8. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.github/workflows/ci.yml +11 -10
  9. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.github/workflows/release.yml +2 -1
  10. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.gitignore +5 -0
  11. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/AGENTS.md +4 -2
  12. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/CHANGELOG.md +267 -1
  13. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/CONTRIBUTING.md +27 -3
  14. gflow_cli-0.10.0/GEMINI.md +27 -0
  15. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/KNOWN_ISSUES.md +110 -26
  16. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/PKG-INFO +13 -3
  17. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/PLAN.md +37 -20
  18. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/README.md +6 -2
  19. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/RELEASE.md +17 -1
  20. gflow_cli-0.10.0/conftest.py +48 -0
  21. gflow_cli-0.10.0/docker-compose.yml +47 -0
  22. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/AGENT_GUIDE.md +15 -1
  23. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/ARCHITECTURE.md +12 -8
  24. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/AUTHENTICATION.md +121 -5
  25. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/CONFIGURATION.md +73 -4
  26. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/DATA_LAYER.md +79 -13
  27. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/DEVELOPMENT.md +13 -1
  28. gflow_cli-0.10.0/docs/E2E_TESTING.md +272 -0
  29. gflow_cli-0.10.0/docs/EXTERNAL_STORAGE.md +140 -0
  30. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/GITHUB.md +38 -0
  31. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/INDEX.md +9 -1
  32. gflow_cli-0.10.0/docs/LIVE_VERIFICATION_v0.10.0.md +95 -0
  33. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/LIVE_VERIFICATION_v0.9.0.md +2 -0
  34. gflow_cli-0.10.0/docs/LIVE_VERIFICATION_v0.9.1.md +98 -0
  35. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/PROJECT_STATUS.md +11 -5
  36. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/SECURITY.md +29 -2
  37. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/USAGE.md +108 -7
  38. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/USER_GUIDE.md +70 -1
  39. gflow_cli-0.10.0/docs/superpowers/specs/2026-05-27-public-event-surface-design.md +397 -0
  40. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/examples/README.md +3 -1
  41. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/examples/sample_config.json +1 -1
  42. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/examples/single_image_t2i.py +6 -4
  43. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/llms.txt +1 -0
  44. gflow_cli-0.10.0/pyproject.toml +127 -0
  45. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/ci/check_doc_links.py +13 -0
  46. gflow_cli-0.10.0/scripts/dev/capture_i2v_frame_slots_dom.py +198 -0
  47. gflow_cli-0.10.0/scripts/dev/capture_locale_invariants.py +235 -0
  48. gflow_cli-0.10.0/scripts/dev/cdp_drive_and_probe.py +119 -0
  49. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/record_demo.ps1 +5 -2
  50. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/skills/README.md +8 -0
  51. gflow_cli-0.10.0/skills/pr-council-review/SKILL.md +350 -0
  52. gflow_cli-0.10.0/skills/predict/SKILL.md +208 -0
  53. gflow_cli-0.10.0/skills/scenario/SKILL.md +200 -0
  54. gflow_cli-0.10.0/sonar-project.properties +54 -0
  55. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/__init__.py +1 -1
  56. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/_cli_helpers.py +32 -6
  57. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/_retry.py +7 -4
  58. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/client.py +92 -65
  59. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/dto.py +13 -7
  60. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/image.py +62 -10
  61. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/recaptcha.py +12 -3
  62. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/routes.py +2 -1
  63. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/transports/__init__.py +2 -1
  64. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/transports/_common.py +17 -9
  65. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/transports/_fingerprint.py +5 -5
  66. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/transports/base.py +5 -4
  67. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/transports/experimental/bearer.py +32 -16
  68. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +26 -12
  69. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/transports/experimental/sapisidhash.py +39 -15
  70. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/transports/ui_automation.py +309 -118
  71. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/transports/ui_automation_video.py +216 -80
  72. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/video.py +155 -59
  73. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/auth/__init__.py +5 -2
  74. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/auth/base.py +4 -2
  75. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/auth/factory.py +9 -3
  76. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/auth/internal_chromium.py +31 -10
  77. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/auth/real_chrome.py +19 -7
  78. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/auth/verification.py +18 -9
  79. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/browser_manager.py +23 -10
  80. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/cli.py +90 -8
  81. gflow_cli-0.10.0/src/gflow_cli/cli_data.py +452 -0
  82. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/cli_image.py +139 -35
  83. gflow_cli-0.10.0/src/gflow_cli/cli_models.py +121 -0
  84. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/cli_run.py +34 -16
  85. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/cli_video.py +100 -10
  86. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/config.py +34 -2
  87. gflow_cli-0.10.0/src/gflow_cli/data/migrations/0002_add_cloud_storage.sql +20 -0
  88. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/data/models.py +7 -3
  89. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/data/queries.py +137 -37
  90. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/data/recorder.py +82 -31
  91. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/data/redaction.py +2 -2
  92. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/data/repository.py +68 -17
  93. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/data/store.py +18 -9
  94. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/errors.py +16 -16
  95. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/image_batch.py +125 -50
  96. gflow_cli-0.10.0/src/gflow_cli/json_output.py +176 -0
  97. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/manifest.py +2 -1
  98. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/observability.py +13 -5
  99. gflow_cli-0.10.0/src/gflow_cli/paths.py +212 -0
  100. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/profile_store.py +68 -6
  101. gflow_cli-0.10.0/src/gflow_cli/storage.py +145 -0
  102. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/test_client.py +16 -0
  103. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/test_client_image.py +61 -0
  104. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/test_image.py +44 -0
  105. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/test_video.py +41 -5
  106. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/transports/test_bearer.py +6 -2
  107. gflow_cli-0.10.0/tests/api/transports/test_transport_timeout.py +98 -0
  108. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/transports/test_ui_automation.py +148 -4
  109. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/transports/test_ui_automation_video.py +144 -1
  110. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/auth/strategies/test_strategies.py +6 -0
  111. gflow_cli-0.10.0/tests/cli/test_cli_auth_list.py +143 -0
  112. gflow_cli-0.10.0/tests/cli/test_cli_data.py +277 -0
  113. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/cli/test_cli_image.py +180 -3
  114. gflow_cli-0.10.0/tests/cli/test_cli_models.py +92 -0
  115. gflow_cli-0.10.0/tests/cli/test_cli_video.py +475 -0
  116. gflow_cli-0.10.0/tests/conftest.py +80 -0
  117. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/data/test_recorder.py +59 -0
  118. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/data/test_settings_and_errors.py +2 -1
  119. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/data/test_store_migrations.py +1 -1
  120. gflow_cli-0.10.0/tests/e2e/conftest.py +123 -0
  121. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/e2e/test_auth_verification_e2e.py +1 -1
  122. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/e2e/test_data_layer_e2e.py +10 -31
  123. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/e2e/test_image_batch_e2e.py +10 -19
  124. gflow_cli-0.10.0/tests/e2e/test_image_i2i_ref_cap_e2e.py +117 -0
  125. gflow_cli-0.10.0/tests/e2e/test_json_output_e2e.py +213 -0
  126. gflow_cli-0.10.0/tests/e2e/test_locale_selectors_e2e.py +88 -0
  127. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/e2e/test_transports_e2e.py +157 -127
  128. gflow_cli-0.10.0/tests/e2e/test_video_r2v_ref_cap_e2e.py +161 -0
  129. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/e2e/test_video_t2v_e2e.py +26 -44
  130. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/features/test_image_steps.py +1 -0
  131. gflow_cli-0.10.0/tests/integration/conftest.py +163 -0
  132. gflow_cli-0.10.0/tests/integration/constants.py +13 -0
  133. gflow_cli-0.10.0/tests/integration/test_storage_gcs.py +57 -0
  134. gflow_cli-0.10.0/tests/integration/test_storage_s3.py +87 -0
  135. gflow_cli-0.10.0/tests/scripts/test_capture_locale_invariants.py +77 -0
  136. gflow_cli-0.10.0/tests/smoke/__init__.py +0 -0
  137. gflow_cli-0.10.0/tests/smoke/test_profile_account_smoke.py +181 -0
  138. gflow_cli-0.10.0/tests/smoke/test_real_flow.py +118 -0
  139. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/test_browser_manager.py +8 -2
  140. gflow_cli-0.10.0/tests/test_cli_data.py +414 -0
  141. gflow_cli-0.10.0/tests/test_conftest_isolation.py +40 -0
  142. gflow_cli-0.10.0/tests/test_data_queries.py +613 -0
  143. gflow_cli-0.10.0/tests/test_documentation_gate.py +34 -0
  144. gflow_cli-0.10.0/tests/test_json_output.py +148 -0
  145. gflow_cli-0.10.0/tests/test_marker_registry.py +173 -0
  146. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/test_observability.py +23 -4
  147. gflow_cli-0.10.0/tests/test_paths.py +211 -0
  148. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/test_profile_store.py +50 -0
  149. gflow_cli-0.10.0/uv.lock +2477 -0
  150. gflow_cli-0.9.0/docs/superpowers/notes/v0.9.0-schema-reconciliation.md +0 -108
  151. gflow_cli-0.9.0/docs/superpowers/plans/2026-05-24-v0.9.0-release-implementation.md +0 -2123
  152. gflow_cli-0.9.0/docs/superpowers/specs/2026-05-24-v0.9.0-release-design.md +0 -204
  153. gflow_cli-0.9.0/pyproject.toml +0 -86
  154. gflow_cli-0.9.0/scripts/dev/capture_locale_invariants.py +0 -87
  155. gflow_cli-0.9.0/sonar-project.properties +0 -35
  156. gflow_cli-0.9.0/src/gflow_cli/cli_data.py +0 -299
  157. gflow_cli-0.9.0/src/gflow_cli/paths.py +0 -102
  158. gflow_cli-0.9.0/tests/cli/test_cli_data.py +0 -81
  159. gflow_cli-0.9.0/tests/cli/test_cli_video.py +0 -208
  160. gflow_cli-0.9.0/tests/conftest.py +0 -38
  161. gflow_cli-0.9.0/tests/e2e/conftest.py +0 -67
  162. gflow_cli-0.9.0/tests/smoke/test_real_flow.py +0 -88
  163. gflow_cli-0.9.0/tests/test_cli_data.py +0 -147
  164. gflow_cli-0.9.0/tests/test_data_queries.py +0 -151
  165. gflow_cli-0.9.0/tests/test_paths.py +0 -51
  166. gflow_cli-0.9.0/uv.lock +0 -1169
  167. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.claude/README.md +0 -0
  168. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.claude/commands/gflow/changelog.md +0 -0
  169. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.claude/commands/gflow/doc-review.md +0 -0
  170. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.claude/commands/gflow/known-issues.md +0 -0
  171. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.claude/commands/gflow/plan.md +0 -0
  172. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.claude/commands/gflow/release.md +0 -0
  173. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.continue-here.md +0 -0
  174. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.gitattributes +0 -0
  175. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.github/CODEOWNERS +0 -0
  176. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.github/copilot-instructions.md +0 -0
  177. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.github/dependabot.yml +0 -0
  178. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.github/workflows/external-pr-triage.yml +0 -0
  179. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.gitleaks.toml +0 -0
  180. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.planning/todos/pending/2026-05-11-add-project-logo-and-docs-site-promotion-plan.md +0 -0
  181. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.planning/todos/pending/pr-38-review.md +0 -0
  182. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.pre-commit-config.yaml +0 -0
  183. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/.secrets.baseline +0 -0
  184. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/CLAUDE.md +0 -0
  185. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/CONFIGURATION.md +0 -0
  186. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/DISCLAIMER.md +0 -0
  187. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/LICENSE +0 -0
  188. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/ROADMAP.md +0 -0
  189. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/DEBUGGING.md +0 -0
  190. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/LIVE_VERIFICATION_data_layer.md +0 -0
  191. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/LIVE_VERIFICATION_image_batch.md +0 -0
  192. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/LIVE_VERIFICATION_v0.7.0.md +0 -0
  193. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/LIVE_VERIFICATION_v0.8.1.md +0 -0
  194. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/LIVE_VERIFICATION_video_download.md +0 -0
  195. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/assets/example-run.gif +0 -0
  196. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/2026-05-17-issue-15-handover.md +0 -0
  197. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-09-image-mvp-orchestration.md +0 -0
  198. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-09-image-mvp.md +0 -0
  199. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +0 -0
  200. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-09-video-mvp.md +0 -0
  201. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-10-phase-4-hardening-orchestration.md +0 -0
  202. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-10-phase-4-hardening.md +0 -0
  203. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/2026-05-14-shell-multi-prompt-orchestration.md +0 -0
  204. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_ARCH.md +0 -0
  205. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_SEC_UX.md +0 -0
  206. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_CODE.md +0 -0
  207. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_GEMINI.md +0 -0
  208. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_SECURITY.md +0 -0
  209. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_PYTHON.md +0 -0
  210. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_SECURITY.md +0 -0
  211. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN.md +0 -0
  212. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_CODE.md +0 -0
  213. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_FOLLOWUP.md +0 -0
  214. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_PLANNER.md +0 -0
  215. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY.md +0 -0
  216. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY_FOLLOWUP.md +0 -0
  217. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_FINAL_SEC_UX_VERIFIED.md +0 -0
  218. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_PLAN_SECURITY.md +0 -0
  219. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_SPEC_SECURITY.md +0 -0
  220. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/PLAN.md +0 -0
  221. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/orchestration.md +0 -0
  222. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-17-e2e-test-coverage.md +0 -0
  223. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-17-issue-15-auth-verification-fix.md +0 -0
  224. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-17-issue-15-i2v-bearer-auth.md +0 -0
  225. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-17-issue-15-orchestration.md +0 -0
  226. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-18-video-phase0-submit-spike.md +0 -0
  227. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-19-video-phase-a-execution-state.md +0 -0
  228. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-19-video-phase-a-orchestration.md +0 -0
  229. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-19-video-phase-a-t2v.md +0 -0
  230. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-20-video-download-t2v-cli.md +0 -0
  231. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-21-multi-image-prompt-orchestration.md +0 -0
  232. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-21-multi-image-prompt.md +0 -0
  233. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-22-pr-38-review.md +0 -0
  234. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-22-stay-mounted-batch-session-plan.md +0 -0
  235. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-23-locale-agnostic-selectors.md +0 -0
  236. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/plans/2026-05-24-data-layer.md +0 -0
  237. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-10-phase-4-hardening-design.md +0 -0
  238. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-14-shell-multi-prompt-design.md +0 -0
  239. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-15-auth-login-real-chrome-design.md +0 -0
  240. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-17-e2e-test-coverage-design.md +0 -0
  241. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-17-i2v-uploadimage-401-bearer-auth-design.md +0 -0
  242. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-17-issue-15-auth-verification-fix-design.md +0 -0
  243. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-17-issue-15-root-cause-findings.md +0 -0
  244. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-18-ui-automation-video-generation-design.md +0 -0
  245. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-21-multi-image-prompt-design.md +0 -0
  246. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-22-pr-38-review-design.md +0 -0
  247. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-22-stay-mounted-batch-session-design.md +0 -0
  248. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-23-locale-agnostic-selectors.md +0 -0
  249. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-23-readme-v0.8.1-refresh-design.md +0 -0
  250. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/specs/2026-05-24-data-layer-design.md +0 -0
  251. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +0 -0
  252. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/examples/batch_from_config.py +0 -0
  253. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/examples/multi_prompt_t2i.py +0 -0
  254. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/examples/sample_prompts.txt +0 -0
  255. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/samples/README.md +0 -0
  256. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/samples/captured/01_upload_image.json +0 -0
  257. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
  258. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
  259. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/samples/captured/04_archive_workflow.json +0 -0
  260. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/samples/captured/05_createProject.json +0 -0
  261. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/samples/captured/06_batchGenerateImages.json +0 -0
  262. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
  263. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/samples/captured/08_batchAsyncGenerateVideoStartAndEndImage.json +0 -0
  264. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/samples/captured/09_batchAsyncGenerateVideoReferenceImages.json +0 -0
  265. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/samples/captured/10_batchCheckAsyncVideoGenerationStatus_successful.json +0 -0
  266. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/samples/captured/11_batchCheckAsyncVideoGenerationStatus_failed.json +0 -0
  267. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/ci/check_repo_hygiene.py +0 -0
  268. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/debug_editor.py +0 -0
  269. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/debug_gen_settings.py +0 -0
  270. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/debug_settings.py +0 -0
  271. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/dev/active_plan.py +0 -0
  272. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/dev/capture_image_add_media_dom.py +0 -0
  273. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/dev/monitor_pr_38.py +0 -0
  274. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/diag_capture_flow_traffic.py +0 -0
  275. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/diag_recaptcha_mint.py +0 -0
  276. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/smoke_image.py +0 -0
  277. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/smoke_real_chrome_image.py +0 -0
  278. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/smoke_video_editor.py +0 -0
  279. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/smoke_worker_style.py +0 -0
  280. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/scripts/verify_chrome_auth_viability.py +0 -0
  281. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/skills/gflow-cli/SKILL.md +0 -0
  282. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/__main__.py +0 -0
  283. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/__init__.py +0 -0
  284. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/api/transports/experimental/__init__.py +0 -0
  285. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/auth/strategies.py +0 -0
  286. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/data/__init__.py +0 -0
  287. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/data/migrations/0001_initial.sql +0 -0
  288. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/data/migrations/__init__.py +0 -0
  289. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/src/gflow_cli/exceptions.py +0 -0
  290. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tasks/lessons.md +0 -0
  291. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/test_assets/sample_batch.json +0 -0
  292. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/test_assets/sample_batch.tsv +0 -0
  293. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/test_assets/sample_batch_invalid.tsv +0 -0
  294. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/__init__.py +0 -0
  295. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/__init__.py +0 -0
  296. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/test_concurrency.py +0 -0
  297. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/test_dto.py +0 -0
  298. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/test_image_dto.py +0 -0
  299. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/test_recaptcha.py +0 -0
  300. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/test_retry.py +0 -0
  301. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/test_routes.py +0 -0
  302. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/transports/__init__.py +0 -0
  303. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/transports/test_base.py +0 -0
  304. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/transports/test_common.py +0 -0
  305. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/transports/test_evaluate_fetch.py +0 -0
  306. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/transports/test_factory.py +0 -0
  307. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/transports/test_fingerprint.py +0 -0
  308. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/transports/test_sapisidhash.py +0 -0
  309. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/transports/test_ui_automation_batch.py +0 -0
  310. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/api/transports/test_ui_automation_image_mode.py +0 -0
  311. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/auth/strategies/test_factory.py +0 -0
  312. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/auth/test_verification.py +0 -0
  313. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/cli/__init__.py +0 -0
  314. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/cli/test_cli_image_seed_removed.py +0 -0
  315. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/cli/test_cli_run.py +0 -0
  316. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/cli/test_error_handling.py +0 -0
  317. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/cli/test_helpers.py +0 -0
  318. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/cli/test_t2i_multi_prompt.py +0 -0
  319. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/data/__init__.py +0 -0
  320. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/data/test_packaging.py +0 -0
  321. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/data/test_redaction.py +0 -0
  322. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/data/test_repository.py +0 -0
  323. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/e2e/__init__.py +0 -0
  324. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/features/__init__.py +0 -0
  325. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/features/auth.feature +0 -0
  326. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/features/auth_login.feature +0 -0
  327. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/features/conftest.py +0 -0
  328. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/features/image.feature +0 -0
  329. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/features/test_auth_login_steps.py +0 -0
  330. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/features/test_auth_steps.py +0 -0
  331. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/features/test_step_collision_guard.py +0 -0
  332. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/fixtures/__init__.py +0 -0
  333. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/fixtures/seeded_catalog.py +0 -0
  334. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/image_batch/__init__.py +0 -0
  335. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/image_batch/test_image_manifest.py +0 -0
  336. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/image_batch/test_observability_events.py +0 -0
  337. {gflow_cli-0.9.0/tests/smoke → gflow_cli-0.10.0/tests/integration}/__init__.py +0 -0
  338. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/test_auth.py +0 -0
  339. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/test_config.py +0 -0
  340. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/test_errors.py +0 -0
  341. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/test_manifest.py +0 -0
  342. {gflow_cli-0.9.0 → gflow_cli-0.10.0}/tests/test_smoke.py +0 -0
@@ -0,0 +1,13 @@
1
+ ---
2
+ description: Multi-dimensional LLM council review on the current local feature branch — pre-PR review. Same dimensions as `/gflow:pr-council-review` but reads `git diff <base>..HEAD` instead of a PR; never posts to GitHub. Wrapper around skills/pr-council-review/SKILL.md § 8 (branch mode).
3
+ ---
4
+
5
+ # `/gflow:branch-review [--base <ref>]`
6
+
7
+ **Read `skills/pr-council-review/SKILL.md` and follow its protocol now in BRANCH MODE (§ 8)**, passing `$ARGUMENTS` (optional `--base <ref>`; default `develop`).
8
+
9
+ > Do **not** call `Skill(skill="pr-council-review")` — the repo's `skills/*/SKILL.md` files are plain Markdown, not registered as Skill-tool-invocable (only `.claude/commands/gflow/*` are). Invoking it errors with `Unknown skill: pr-council-review`. Read the file directly instead.
10
+
11
+ The canonical body is `skills/pr-council-review/SKILL.md`. § 8 documents branch-mode-specific behavior: pre-flight, the PR→branch translation table, `release/*` downgrade, SHA drift, and local-only output. All other phases (gather context, detect dimensions, dispatch, synthesize, report) are identical to PR mode.
12
+
13
+ Sibling: `/gflow:pr-council-review <N>` runs the same council against an open PR.
@@ -32,7 +32,7 @@ uv run pyright src
32
32
  **4. Tests + coverage** (report only)
33
33
 
34
34
  ```bash
35
- uv run pytest -q --cov=gflow_cli --cov-fail-under=80
35
+ uv run python -m pytest -q --cov=gflow_cli --cov-fail-under=80
36
36
  ```
37
37
 
38
38
  ## Output
@@ -46,3 +46,7 @@ uv run pytest -q --cov=gflow_cli --cov-fail-under=80
46
46
 
47
47
  Ruff fix and format may rewrite multiple files. Always `git diff` before staging.
48
48
  Pyright errors and test failures require manual intervention — do not attempt silent workarounds.
49
+ If the coverage run crashes the current MCP/sandbox session with `Connection closed`, re-run the
50
+ same marker-filtered suite in smaller chunks without coverage and rely on CI for the coverage XML.
51
+ Project pytest defaults already exclude `e2e` and `live`; those markers are explicit,
52
+ credit-spending gates and must be requested with a separate `-m e2e` / `-m live` command.
@@ -0,0 +1,11 @@
1
+ ---
2
+ description: Multi-dimensional LLM council review of an open PR. Five baseline dimensions (correctness, quality, security, tests, memory-hygiene) plus adaptive per-surface dimensions. Sub-agents invoke specialized skills (security-review, code-review, verify). With no argument, lists open PRs ranked by priority. Wrapper around skills/pr-council-review/SKILL.md (canonical body).
3
+ ---
4
+
5
+ # `/gflow:pr-council-review [PR#]`
6
+
7
+ **Read `skills/pr-council-review/SKILL.md` and follow its protocol now**, treating `$ARGUMENTS` as the PR number (or empty for prioritize-mode). That file is the canonical body: preflight, dimension detection, parallel dispatch, synthesis, report.
8
+
9
+ > Do **not** call `Skill(skill="pr-council-review")` — the repo's `skills/*/SKILL.md` files are plain Markdown, not registered as Skill-tool-invocable (only `.claude/commands/gflow/*` are). Invoking it errors with `Unknown skill: pr-council-review`. Read the file directly instead.
10
+
11
+ Sibling: `/review` is the single-agent Claude-Code built-in (fast, one-pass). Use it for spot-checks; use this command for pre-merge multi-dim audits.
@@ -0,0 +1,19 @@
1
+ ---
2
+ description: >
3
+ Pre-implementation 5-persona adversarial analysis for high-stakes gflow-cli proposals.
4
+ Produces a GO / CAUTION / STOP verdict before any code is written.
5
+ Invoke before new transports, auth changes, selector redesigns, schema migrations,
6
+ or any PLAN.md backlog item gated on an investigation step.
7
+ ---
8
+
9
+ # `/gflow:predict [proposal]`
10
+
11
+ **Read `skills/predict/SKILL.md` and follow its protocol now**, passing `$ARGUMENTS` as the proposal description.
12
+
13
+ > Do **not** call `Skill(skill="predict")` — the repo's `skills/*/SKILL.md` files are plain Markdown, not registered as Skill-tool-invocable (only `.claude/commands/gflow/*` are). Invoking it errors with `Unknown skill: predict`. Read the file directly instead.
14
+
15
+ The skill at `skills/predict/SKILL.md` runs five independent expert personas
16
+ (Architect · Security/reCAPTCHA · Performance/Playwright · CLI UX · Devil's Advocate),
17
+ resolves conflicts, and returns a GO / CAUTION / STOP verdict with a confidence score.
18
+
19
+ **Pair with `/gflow:scenario`** after a GO or CAUTION to enumerate edge cases before EXECUTE.
@@ -0,0 +1,23 @@
1
+ ---
2
+ description: >
3
+ Pre-implementation edge-case explorer for gflow-cli features.
4
+ Decomposes a proposed change across 12 gflow-cli-specific dimensions
5
+ (WAF/reCAPTCHA, selector drift, auth lifecycle, batch resume, data layer,
6
+ cross-platform paths, error propagation, observability) and produces a
7
+ severity-ranked scenario table and BDD skeleton.
8
+ ---
9
+
10
+ # `/gflow:scenario [feature description]`
11
+
12
+ **Read `skills/scenario/SKILL.md` and follow its protocol now**, passing `$ARGUMENTS` as the feature or change description.
13
+
14
+ > Do **not** call `Skill(skill="scenario")` — the repo's `skills/*/SKILL.md` files are plain Markdown, not registered as Skill-tool-invocable (only `.claude/commands/gflow/*` are). Invoking it errors with `Unknown skill: scenario`. Read the file directly instead.
15
+
16
+ The skill at `skills/scenario/SKILL.md` covers 12 dimensions tuned to gflow-cli's
17
+ known failure surfaces and outputs:
18
+ - A severity-ranked scenario table (Critical / High / Medium / Low)
19
+ - Must-cover acceptance criteria for the PLAN.md task
20
+ - Suggested BDD `Scenario:` blocks for `tests/features/`
21
+ - Cross-references to open KNOWN_ISSUES entries
22
+
23
+ **Typical order:** `/gflow:predict` → `/gflow:scenario` → PLAN.md task → `/gflow:check` → PR.
@@ -52,6 +52,34 @@
52
52
  # Get one at https://aistudio.google.com/apikey
53
53
  # GFLOW_CLI_GEMINI_API_KEY=
54
54
 
55
+ # -----------------------------------------------------------------------------
56
+ # Cloud storage
57
+ # -----------------------------------------------------------------------------
58
+
59
+ # Upload generated assets directly to a cloud bucket instead of saving local
60
+ # asset copies. Supported schemes:
61
+ # gs:// – Google Cloud Storage (requires: pip install 'gflow-cli[gcs]')
62
+ # s3:// – Amazon S3 or any S3-compatible store, e.g. MinIO
63
+ # (requires: pip install 'gflow-cli[s3]')
64
+ #
65
+ # Examples:
66
+ # GFLOW_CLI_STORAGE_URI=gs://my-gcs-bucket/gflow/
67
+ # GFLOW_CLI_STORAGE_URI=s3://my-s3-bucket/gflow/
68
+ # GFLOW_CLI_STORAGE_URI=s3://gflow-test/gflow/ # MinIO local dev
69
+ #
70
+ # For S3 / MinIO you also need the standard AWS SDK env vars:
71
+ # AWS_ACCESS_KEY_ID=minioadmin
72
+ # AWS_SECRET_ACCESS_KEY=minioadmin
73
+ # AWS_ENDPOINT_URL=http://localhost:9000 # omit for real AWS
74
+ # AWS_DEFAULT_REGION=us-east-1
75
+ #
76
+ # For GCS (local emulator):
77
+ # STORAGE_EMULATOR_HOST=http://localhost:4443
78
+ #
79
+ # When unset, assets are saved to GFLOW_CLI_OUTPUT_DIR (local disk). gflow-cli
80
+ # does not dual-write local + cloud copies; configure one storage target per run.
81
+ # GFLOW_CLI_STORAGE_URI=
82
+
55
83
  # -----------------------------------------------------------------------------
56
84
  # Runtime tuning
57
85
  # -----------------------------------------------------------------------------
@@ -7,6 +7,8 @@
7
7
  <!-- List the focused commands you ran, plus any checks you could not run. -->
8
8
 
9
9
  - [ ] Focused tests added or updated for behavior changes
10
+ - [ ] Documentation updated or explicitly marked not applicable
11
+ - [ ] `uv run python scripts/ci/check_doc_links.py`
10
12
  - [ ] `uv run ruff check src tests`
11
13
  - [ ] `uv run pyright src`
12
14
  - [ ] Relevant pytest command:
@@ -6,7 +6,9 @@ on:
6
6
  pull_request:
7
7
 
8
8
  env:
9
- FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
9
+ # Suppress Node.js deprecation warnings and align with user request to use Node 22/remove noise.
10
+ ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
11
+ NODE_VERSION: '22'
10
12
 
11
13
  jobs:
12
14
  # ── Security gate: runs first, on every push/PR, never skippable ──────────
@@ -44,6 +46,9 @@ jobs:
44
46
  - name: Repo hygiene (no artefacts, no hardcoded paths)
45
47
  run: uv run python scripts/ci/check_repo_hygiene.py
46
48
 
49
+ - name: Documentation links
50
+ run: uv run python scripts/ci/check_doc_links.py
51
+
47
52
  - name: Lint
48
53
  run: uv run ruff check src tests
49
54
 
@@ -54,14 +59,10 @@ jobs:
54
59
  run: uv run pyright src
55
60
 
56
61
  - name: Test (smoke only) + coverage
57
- # e2e tests (tests/e2e/) require a logged-in Chromium profile
58
- # and live Flow auth never runnable in CI. They self-mark with
59
- # `pytestmark = pytest.mark.e2e` (file-level) and are opt-in via
60
- # `-m e2e` per their module docstring. `live` marker is reserved for
61
- # `GFLOW_LIVE=1` tests that hit the real Flow API. Both are excluded
62
- # from the default smoke run; `tests/smoke/test_real_flow.py` already
63
- # self-skips via `pytest.mark.skipif(GFLOW_E2E != "1")`.
64
- run: uv run python -m pytest -q -m "not e2e and not live" --cov=gflow_cli --cov-report=xml
62
+ # e2e/live tests require a logged-in Chromium profile and may spend
63
+ # Flow credits. pyproject.toml excludes both markers by default; CI
64
+ # intentionally relies on that default smoke set.
65
+ run: uv run python -m pytest -q --cov=gflow_cli --cov-report=xml
65
66
 
66
67
  # Upload coverage XML so the sonar job can consume it
67
68
  - name: Upload coverage report
@@ -98,7 +99,7 @@ jobs:
98
99
  continue-on-error: true # graceful if coverage upload was skipped
99
100
 
100
101
  - name: SonarCloud scan
101
- uses: SonarSource/sonarcloud-github-action@master
102
+ uses: SonarSource/sonarcloud-github-action@v5.0.0
102
103
  env:
103
104
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # PR decoration
104
105
  SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} # set in repo → Settings → Secrets
@@ -16,7 +16,8 @@ jobs:
16
16
  name: pypi
17
17
  url: https://pypi.org/p/gflow-cli
18
18
  env:
19
- FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
19
+ ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
20
+ NODE_VERSION: '22'
20
21
  steps:
21
22
  - uses: actions/checkout@v6
22
23
  with:
@@ -18,6 +18,7 @@ env/
18
18
  pytest-of-*/
19
19
  .coverage
20
20
  .coverage.*
21
+ coverage.xml
21
22
  htmlcov/
22
23
  .tox/
23
24
  .mypy_cache/
@@ -70,6 +71,8 @@ samples/captured/flow_outgoing_*.jsonl
70
71
  samples/captured/flow_outgoing_*.json
71
72
 
72
73
  # Claude Code worktrees and lock files
74
+ .claude/settings.json
75
+ .claude/settings.local.json
73
76
  .claude/worktrees/
74
77
  .claude/scheduled_tasks.lock
75
78
 
@@ -78,3 +81,5 @@ samples/captured/flow_outgoing_*.json
78
81
 
79
82
  worktrees/
80
83
 
84
+ # E2E test logs (live Flow runs — may contain account/profile names)
85
+ .planning/e2e-logs/
@@ -2,7 +2,7 @@
2
2
 
3
3
  > Universal entry point for AI coding agents. Read this first; everything else routes from here.
4
4
 
5
- Supported tools that auto-discover this file: Cursor, Codex, Aider, Gemini CLI, Jules, Devin, Windsurf, Zed, Warp, opencode, RooCode, Amp, Junie, Phoenix, GitHub Copilot, VS Code, Factory, Augment, Semgrep, Kilo Code, UiPath. Claude Code reads [CLAUDE.md](CLAUDE.md), which cross-references this file.
5
+ Supported tools that auto-discover this file: Cursor, Codex, Aider, Jules, Devin, Windsurf, Zed, Warp, opencode, RooCode, Amp, Junie, Phoenix, GitHub Copilot, VS Code, Factory, Augment, Semgrep, Kilo Code, UiPath. Gemini CLI reads [GEMINI.md](GEMINI.md) and Claude Code reads [CLAUDE.md](CLAUDE.md), both of which cross-reference this file.
6
6
 
7
7
  ## Project at a glance
8
8
 
@@ -37,6 +37,7 @@ Run these gates in order before every commit:
37
37
  ```powershell
38
38
  $env:PYTHONUTF8=1
39
39
  uv run python scripts/ci/check_repo_hygiene.py
40
+ uv run python scripts/ci/check_doc_links.py
40
41
  uv run ruff check src tests
41
42
  uv run ruff format --check src tests
42
43
  uv run pyright src
@@ -45,8 +46,9 @@ uv run python -m pytest -q --cov=gflow_cli
45
46
 
46
47
  Or invoke the wrapper: `/gflow:check`.
47
48
 
48
- - Use `pytest -m "not live and not e2e"` locally; full suite OOMs on small dev machines. Scope to changed dirs; trust CI for the full sweep.
49
+ - Use `pytest -m "not live and not e2e and not smoke"` locally; full suite OOMs on small dev machines. Scope to changed dirs; trust CI for the full sweep.
49
50
  - TDD is non-negotiable. Coverage floor: 80% overall.
51
+ - Documentation is a first-class deliverable. Every behavior, workflow, config, or operator-facing change must update the relevant docs or state why no docs changed in the PR/checklist. `scripts/ci/check_doc_links.py` is a merge gate.
50
52
  - Live tests (`@pytest.mark.live`) opt in via `GFLOW_LIVE=1`. E2E tests require `GFLOW_CLI_E2E_PROFILE`.
51
53
 
52
54
  ## Code style
@@ -7,6 +7,270 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.10.0] — 2026-05-29
11
+
12
+ ### Fixed
13
+
14
+ - **Image and video counts leaking across profiles in `gflow data list projects` (issue #113).**
15
+ Fixed an issue where project media counts were combined if two different profiles
16
+ happened to share the same `flow_project_id`. The counts in `_LIST_PROJECTS_SQL`
17
+ are now strictly scoped to the active `profile_name`.
18
+
19
+ - **List queries fan-out when multiple operations claim an asset (issue #111).**
20
+ Fixed a bug in `gflow data list images` and `gflow data list videos` where
21
+ assets would be duplicated or have non-deterministic prompts if multiple
22
+ operations (e.g., retries) claimed the same output asset. The SQL queries
23
+ now use a deterministic subquery grouping by `asset_id` to ensure exactly
24
+ one-to-one cardinality.
25
+
26
+ ### Added
27
+
28
+ - **Google account identity persisted to every profile (`issue #92`).** Both
29
+ auth strategies (`real_chrome`, `internal_chromium`) now write a
30
+ `.gflow_account` file to the profile directory immediately after the session
31
+ is verified, durably associating the signed-in email with the profile on disk.
32
+ `ProfileMeta` gains a `google_account: str | None` field populated by
33
+ `profile_store.list_profiles()` from that file. `gflow auth list` (table and
34
+ `--json`) now includes a **Google account** column so every profile is
35
+ immediately identifiable — no more opaque `default` entries. The `--json`
36
+ output gains the `google_account` key for programmatic callers. Closes #92.
37
+
38
+ - **Auto-rename of the first-run `default` profile to email local-part.** When
39
+ `gflow auth login` creates the first profile and no `--profile` flag was given,
40
+ the profile is named `default` as a placeholder. After the session is verified
41
+ and the email is known, `auth login` automatically renames `profile_default` to
42
+ `profile_<email-local-part>` (e.g. `profile_ffroliva`) and updates
43
+ `config.toml`'s `default_profile` pointer atomically. The local-part is
44
+ sanitized to a filesystem-safe name (characters outside letters, digits, `-`,
45
+ and `_` become `-`), so `flavio.oliva@gmail.com` → `profile_flavio-oliva` and
46
+ `user+flow@gmail.com` → `profile_user-flow`. Existing `default`
47
+ profiles that were created before this change continue to work; they gain the
48
+ email column the next time `gflow auth login` is run against them. Closes #92.
49
+
50
+ - **`profile_store.rename_profile(old_name, new_name)`** — reusable primitive that
51
+ renames a profile directory and updates `config.toml` when the renamed profile
52
+ was the default. Raises `FileNotFoundError` / `FileExistsError` on invalid input.
53
+
54
+ - **Zero-credit smoke test for profile account persistence
55
+ (`tests/smoke/test_profile_account_smoke.py`).** Three smoke tests that verify
56
+ the full observable chain — account file present + readable, `list_profiles()`
57
+ surfaces `google_account`, `gflow auth list --json` includes the field — against
58
+ a real authenticated profile. No image or video generation; zero Flow credits.
59
+ Backfills the `.gflow_account` file for profiles created before the fix so the
60
+ tests work on existing sessions. Opt-in via
61
+ `GFLOW_CLI_E2E_PROFILE=<name> pytest -m smoke tests/smoke/test_profile_account_smoke.py`.
62
+
63
+ - **Aggregated asset view in `gflow data list images/videos`.** By default,
64
+ listing images or videos now returns one row per asset (Flow media ID),
65
+ collapsing multiple local copies into a single entry with a `COPIES` count
66
+ and the path of the latest copy. This prevents duplicate rows when
67
+ re-downloading the same media to different directories. The `copy_count`
68
+ is also exposed in JSONL output.
69
+ - **`--all-copies` flag on `gflow data list images/videos`.** Restores the
70
+ previous behavior of showing every local file as a separate row.
71
+ - **`gflow data prune` command.** New maintenance utility to remove stale
72
+ `local_files` database entries for local paths that no longer exist on
73
+ disk. Only targets local files (ignores cloud-stored assets). Supports
74
+ `--dry-run` to preview deletions and `--profile` to limit the scan.
75
+ - **External storage documentation for S3, MinIO, and Google Cloud Storage.**
76
+ Adds `docs/EXTERNAL_STORAGE.md`, cross-links it from the README, docs index,
77
+ configuration, data-layer, usage, security, and user-guide docs, and clarifies
78
+ that `GFLOW_CLI_STORAGE_URI` is a cloud-only output mode rather than
79
+ local-plus-cloud dual-write.
80
+ - **`--json` flag on `gflow video t2v`, `gflow video i2v`, and `gflow video r2v`.**
81
+ Emits the `VideoResult` (status / command / media_id / generation_status /
82
+ succeeded / local_path / failure_reasons / error_message) plus the request
83
+ echo (model / mode / aspect / duration / count / seed) as a single JSON
84
+ object on stdout. A failed generation still emits its JSON payload and
85
+ then exits 1. The data-layer recorder
86
+ (`record_started_video` / `record_completed_video`) fires regardless of
87
+ `--json` so audit history is independent of the output channel. E2e
88
+ coverage for `--json` shape across image / video / auth / models lives at
89
+ `tests/e2e/test_json_output_e2e.py`.
90
+ - **`--json` flag on `gflow image t2i` and `gflow image i2i`.** Emits the
91
+ complete `GeneratedImage` result (every field — `media_name`,
92
+ `workflow_id`, `seed`, `prompt`, `model_name_type`, `aspect_ratio`,
93
+ `dimensions`, `fife_url`, `is_signed_url`) plus the on-disk `local_path`
94
+ as a single JSON object on stdout. A worker keys `images[0].seed` for
95
+ refine-regen seed continuity. Single-prompt only (`--json` rejects
96
+ multi-prompt batch with a Click usage error); progress chatter is
97
+ suppressed so stdout is pure JSON. `ref_count` surfaces only on i2i.
98
+ - **`gflow models` catalog command.** New top-level command that enumerates
99
+ the image and video model catalog as a Rich table (default) or as a single
100
+ JSON object (`--json`). Per-model: `name`, CLI aliases (filtered to what
101
+ the generation command's `--model` Choice actually accepts), `ref_cap`,
102
+ `default` (image), `max_duration` (video). Built from the
103
+ `Model` / `VideoModel` enums + their alias maps so the catalog can never
104
+ drift from what the generation commands accept. A UI populating its model
105
+ picker from `gflow models --json` is guaranteed to pass any selected alias
106
+ back to `--model`.
107
+ - **`gflow_cli.json_output` module + `--json` error path on
108
+ `run_with_handlers`.** Pure builders for image/video result payloads and
109
+ RFC 9457 problem-details errors (plus a `retryable` flag worker schedulers
110
+ key their retry-vs-absorb decision off — WAF / rate-limit / network /
111
+ timeout). When `as_json=True`, errors emit a parseable JSON payload on
112
+ stdout with the same exit code as the Rich path; the observability event
113
+ still fires.
114
+ - **`--json` flag on `gflow auth list`.** Emits the profile inventory as a JSON
115
+ array (`name` / `is_default` / `cookies_present` / `profile_dir` /
116
+ `last_used_at`) on stdout so a programmatic caller (e.g. a worker discovering
117
+ authenticated profiles) can `json.loads(stdout)` instead of scraping the
118
+ Rich table.
119
+ - **Per-model r2v reference-image cap rebuilt as a data table.** Replaces the
120
+ prior pair of constants (`OMNI_REFERENCE_CAP=7`, `VEO_REFERENCE_CAP=3`) with
121
+ a `VideoModel -> int` mapping consulted by
122
+ `gflow_cli.api.video.reference_cap_for(model)`. New entries:
123
+ `veo_3_1_lite_lower_priority=3` (was implicitly covered by the veo branch),
124
+ and `veo_3_1_quality=0` — Veo 3.1 Quality does NOT support
125
+ Ingredients/References to Video at all per Google Flow's official support
126
+ page; passing it to r2v raises a clear `does not support R2V
127
+ (reference-to-video)` error rather than letting the request fail at the
128
+ wire. CLI guard added on `gflow video r2v` (`click.UsageError`, exit 2)
129
+ mirroring the i2i pattern so over-cap and quality+r2v fail before any
130
+ profile/network work. E2e tripwire at
131
+ `tests/e2e/test_video_r2v_ref_cap_e2e.py` asserts Flow actually consumes
132
+ all `cap` refs at the at-cap boundary.
133
+ - **Per-model i2i reference-image cap.** Flow silently keeps only the first N
134
+ reference images when an i2i request attaches more than the model accepts,
135
+ so a caller could believe every ref was used. `gflow_cli.api.image.reference_cap_for(model)`
136
+ exposes the live-observed per-model cap: NARWHAL (Nano Banana 2) and GEM_PIX_2
137
+ (Nano Pro) accept 10, IMAGEN_3_5 (Imagen 4) accepts 3. Enforced as a domain
138
+ invariant in `GenerateImageRequest.__post_init__` and at the CLI boundary in
139
+ `gflow image i2i` (clean `click.UsageError` / exit 2 before any
140
+ profile/network work). Mirrors the existing video r2v cap pattern. E2e
141
+ tripwire at `tests/e2e/test_image_i2i_ref_cap_e2e.py` asserts Flow actually
142
+ consumes all `cap` refs (one `reference_attached` event per ref) so a future
143
+ silent truncation on the Flow side fails the test.
144
+ - **Layered e2e test strategy with cost sub-markers.** The single `e2e` marker is
145
+ now augmented by cost sub-markers (`e2e_auth`, `e2e_image`, `e2e_video`,
146
+ `e2e_batch`, `e2e_data`, `smoke`) so callers can run only the tier they can
147
+ afford (zero-credit auth checks, single-credit image smoke, etc.). See
148
+ `docs/E2E_TESTING.md` for the full reference.
149
+ - `tests/e2e/conftest.py` — shared `e2e_profile_dir`, `e2e_nosession_profile`,
150
+ and `e2e_env` fixtures replace duplicated inline helpers in individual test files.
151
+ - `tests/api/transports/test_transport_timeout.py` — extracted from e2e as a
152
+ pure-mock integration test; also fixes `Path("/dev/null")` → `Path(os.devnull)`
153
+ for Windows portability.
154
+ - `tests/test_marker_registry.py` — invariant checks that every e2e test carries a
155
+ cost sub-marker, and self-tests for the auto-marker conftest hook.
156
+ - `docs/E2E_TESTING.md` — comprehensive e2e strategy and layer reference document.
157
+
158
+ ### Fixed
159
+
160
+ - Structlog logs are now routed to stderr (via
161
+ `PrintLoggerFactory(file=sys.stderr)`) instead of stdout. Previously every
162
+ CLI event leaked onto stdout, which broke the `--json` contract for
163
+ programmatic callers — `json.loads(stdout)` failed because the JSON
164
+ payload was preceded by event-log lines. Logs are diagnostics; stdout is
165
+ data. No-op for human users (terminals still show logs the same way).
166
+
167
+ ### Changed
168
+
169
+ - `gflow data media` now labels cloud-backed asset records as `cloud_uri_N`
170
+ while keeping local assets under the existing `local_path_N` labels.
171
+ - `gflow_cli.api.video` no longer exposes the standalone `OMNI_REFERENCE_CAP` /
172
+ `VEO_REFERENCE_CAP` constants. Callers that need a per-model R2V cap should
173
+ use `reference_cap_for(model)` (which returns `0` for `VEO_3_1_QUALITY` —
174
+ R2V is unsupported there). `MAX_REFERENCE_IMAGES` (= 7) is unchanged and
175
+ still the absolute ceiling used when the model is unknown.
176
+ - `GFLOW_CLI_E2E_RUN_VIDEO` default flipped from `"1"` to `"0"`. The Veo step in
177
+ `test_data_layer_e2e.py` is now **opt-in**: set `GFLOW_CLI_E2E_RUN_VIDEO=1` to
178
+ include it. This prevents accidental Veo credit burns on unattended CI runs.
179
+ - `pytest` `addopts` now excludes `smoke` in addition to `e2e` and `live`:
180
+ `not e2e and not live and not smoke`. Bare `pytest` never launches a live
181
+ browser session.
182
+ - Auto-marker conftest hook uses `item.path.parts` instead of a slash-delimited
183
+ string substring, fixing Windows backslash path compatibility.
184
+
185
+ ## [0.9.1] — 2026-05-27
186
+
187
+ > **Locale and catalog patch release.** Hardens the headed-browser UI
188
+ > automation path for localized Flow profiles, fixes I2V start/end-frame
189
+ > attachment on non-English Chrome/Flow sessions, and repairs first-run catalog
190
+ > edge cases found after v0.9.0.
191
+
192
+ ### Changed
193
+
194
+ - `NEW_PROJECT_SELECTORS` now covers all 14 supported locales (EN / PT / ES /
195
+ FR / DE / IT / NL / JA / ZH / KO / PL / RU / TR / ID) and leads with
196
+ locale-stable icon selectors (`add_2` Material Symbols ligature on
197
+ `<button>` and on `[role='button']` ARIA-role variants, plus an anchored
198
+ `^\+\s+\S+$` regex for `+ <word>` host elements). English-only
199
+ `[aria-label*='New project']` and `[aria-label*='Project']` ARIA fallbacks
200
+ removed.
201
+ `SUBMIT_BUTTON_SELECTORS` drops its English-only
202
+ `button[aria-label*="Create"]` fallback — the preceding `arrow_forward` icon
203
+ entries already cover this button in every locale. Both selector tuples are
204
+ now fully locale-invariant for non-English Chrome profiles. The `--lang=en-US`
205
+ Chromium launch arg is retained only to stabilise `IMAGE_MODEL_OPTION_SELECTORS`
206
+ (English product names); its removal is tracked as issue #24 Phase 5 (#94).
207
+
208
+ ### Fixed
209
+
210
+ - Bare `pytest` no longer collects live/e2e tests by default. The project-wide
211
+ pytest `addopts` now excludes `e2e` and `live` unless callers explicitly pass
212
+ a different `-m` expression, and `tests/smoke/test_real_flow.py` is marked
213
+ with both markers so marker-filtered local and CI runs cannot accidentally
214
+ launch a real Flow browser session.
215
+ - Browser-manager PID tests no longer call the real `os.kill` while pretending
216
+ to be on POSIX from a Windows runner. The POSIX liveness branches are now
217
+ tested with mocked `os.kill`, avoiding hard interpreter/session exits during
218
+ local test runs.
219
+
220
+ - Running the pytest suite no longer writes fixture rows into the developer's
221
+ production `gflow.db` catalog. A new autouse `_isolate_settings` fixture in
222
+ `tests/conftest.py` redirects `GFLOW_CLI_HOME` and `GFLOW_CLI_DB_PATH` to
223
+ per-test `tmp_path` dirs and clears the `get_settings()` `lru_cache` before
224
+ and after every test, preventing the cached singleton from ever resolving to
225
+ a `platformdirs` production path. Closes
226
+ [#86](https://github.com/ffroliva/gflow-cli/issues/86).
227
+
228
+ - `gflow video i2v` no longer silently breaks on non-English Chrome profiles.
229
+ PR #70's structural-first `_attach_frame` cascade matched **zero** real
230
+ slots — its anchor selector assumed the `swap_horiz` icon used class
231
+ `google-symbols` (it uses `material-icons`) and the slots were `<button>`
232
+ (they're `<div type="button">`). Production I2V therefore relied on the
233
+ English-text fallback, which silently misses on any non-EN profile (pt-BR
234
+ shows `Inicial`/`Final`, DE shows `Anfang`/`Ende`, etc.). Replaced
235
+ `FRAME_SLOTS_STRUCT` with the locale-free pattern
236
+ `div[type='button'][aria-haspopup='dialog']` and added a `.first`-of-remaining
237
+ fallback for the End-frame case (after Start is attached, only one slot
238
+ matches and the prior `.nth(slot_index)` went out-of-bounds). Live-verified
239
+ with `tests/e2e/test_transports_e2e.py::test_e2e_i2v_start_end_frame_attach`
240
+ on `ffroliva` + `GFLOW_CLI_LOCALE=de-DE` (Chrome rendered pt-BR; both
241
+ non-EN). Closes [#63](https://github.com/ffroliva/gflow-cli/issues/63).
242
+
243
+ ### Changed
244
+
245
+ - `gflow data media <id>` now searches across **all** profiles by default,
246
+ matching the cross-profile default of `gflow data list`. Pass
247
+ `--profile NAME` to disambiguate the rare case where the same Flow
248
+ media ID exists under multiple profiles (the command refuses to
249
+ guess and prints the list of candidate profiles, each annotated with
250
+ its `kind`). Closes
251
+ [#87](https://github.com/ffroliva/gflow-cli/issues/87).
252
+
253
+ ### Fixed
254
+
255
+ - `gflow data list` no longer crashes with `no such table: assets` on a
256
+ missing or freshly-created catalog DB. The query path now routes through
257
+ `DataStore.open`, which applies schema migrations on first connect —
258
+ first-time users and anyone recovering from a wiped DB get an empty
259
+ table and exit 0 instead of a `DataStoreError`. Closes
260
+ [#88](https://github.com/ffroliva/gflow-cli/issues/88).
261
+ - `gflow auth list` no longer crashes with `UnicodeEncodeError` on Windows
262
+ consoles whose code page cannot encode the default-profile marker `●`
263
+ (cp1252 in PowerShell / cmd by default). The renderer now picks a glyph
264
+ safe for the active `sys.stdout.encoding` — `●` on UTF-8, ASCII `*` on
265
+ cp1252 / ascii / latin-1 / unknown. Closes [#82](https://github.com/ffroliva/gflow-cli/issues/82).
266
+
267
+ ### Documentation
268
+
269
+ - `PLAN.md` refreshed to reflect develop state through v0.9.0 — marks Phase 6
270
+ (data layer) shipped via PR #58 + #78 + #81, Phase 7 Issue #24 Phase 2
271
+ shipped via PR #70, Phase B I2V/R2V shipped via PR #48, and resolves the
272
+ duplicate Phase 7 numbering (pluggable storage renumbered to Phase 8).
273
+
10
274
  ## [0.9.0] — 2026-05-25
11
275
 
12
276
  > **Maturity & Visibility release.** Surfaces the SQLite catalog (PR #52/#58)
@@ -945,7 +1209,9 @@ shell-script template that branches on these codes.
945
1209
 
946
1210
  First skeleton. Not functional end-to-end yet.
947
1211
 
948
- [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.9.0...HEAD
1212
+ [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.10.0...HEAD
1213
+ [0.10.0]: https://github.com/ffroliva/gflow-cli/compare/v0.9.1...v0.10.0
1214
+ [0.9.1]: https://github.com/ffroliva/gflow-cli/compare/v0.9.0...v0.9.1
949
1215
  [0.9.0]: https://github.com/ffroliva/gflow-cli/compare/v0.8.1...v0.9.0
950
1216
  [0.8.1]: https://github.com/ffroliva/gflow-cli/compare/v0.8.0...v0.8.1
951
1217
  [0.8.0]: https://github.com/ffroliva/gflow-cli/compare/v0.7.0...v0.8.0
@@ -39,6 +39,11 @@ def test_parse_uuid_from_url(): ...
39
39
  async def test_upload_returns_asset(): ...
40
40
 
41
41
  @pytest.mark.e2e # Hits the real Flow API. Requires GFLOW_CLI_E2E_PROFILE env var.
42
+ @pytest.mark.e2e_image # Cost sub-marker: spends ~1 Imagen credit.
43
+ async def test_full_t2i_roundtrip(): ...
44
+
45
+ @pytest.mark.e2e
46
+ @pytest.mark.e2e_video # Cost sub-marker: spends ~1 Veo credit (most expensive).
42
47
  async def test_full_i2v_roundtrip(): ...
43
48
  ```
44
49
 
@@ -46,10 +51,23 @@ CI runs `unit` + `integration` on every push. `e2e` tests require a live authent
46
51
 
47
52
  ```bash
48
53
  export GFLOW_CLI_E2E_PROFILE=<profile-name> # name of a logged-in profile
49
- uv run pytest -m e2e -v
54
+
55
+ # Zero-credit sanity check (auth + health)
56
+ uv run pytest -m e2e_auth -v
57
+
58
+ # Single image (1 Imagen credit)
59
+ uv run pytest -m "e2e_image and not e2e_batch" -v
60
+
61
+ # Full regression (all credits)
62
+ GFLOW_CLI_E2E_RUN_VIDEO=1 uv run pytest -m e2e -v
50
63
  ```
51
64
 
52
- E2e tests spend real Veo/Imagen credits run them on `develop` before opening a release PR to `main`. See [docs/DEVELOPMENT.md § E2e gate](docs/DEVELOPMENT.md#e2e-gate-before-merging-develop--main).
65
+ E2e tests spend real Veo/Imagen credits. Video tests default to opt-out set
66
+ `GFLOW_CLI_E2E_RUN_VIDEO=1` to include them. Run the full suite on `develop`
67
+ before opening a release PR to `main`.
68
+
69
+ See [docs/E2E_TESTING.md](docs/E2E_TESTING.md) for the complete layer reference,
70
+ cost table, and run commands.
53
71
 
54
72
  ### Coverage targets
55
73
 
@@ -64,13 +82,19 @@ E2e tests spend real Veo/Imagen credits — run them on `develop` before opening
64
82
 
65
83
  ```bash
66
84
  uv run python scripts/ci/check_repo_hygiene.py # artefact + path hygiene
85
+ uv run python scripts/ci/check_doc_links.py # internal Markdown links
67
86
  uv run ruff check src tests # lint
68
87
  uv run ruff format src tests # auto-format
69
88
  uv run pyright src # type-check (strict on src/gflow_cli/)
70
89
  uv run pytest -q --cov=gflow_cli # tests + coverage
71
90
  ```
72
91
 
73
- CI runs all five on every push. Install local pre-commit hooks (recommended):
92
+ CI runs all six on every push. Documentation is part of the merge gate: update
93
+ the relevant docs for behavior, workflow, configuration, architecture, or
94
+ operator-facing changes. If no documentation change is needed, state that in
95
+ the PR validation checklist.
96
+
97
+ Install local pre-commit hooks (recommended):
74
98
 
75
99
  ```bash
76
100
  pip install pre-commit && pre-commit install
@@ -0,0 +1,27 @@
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:
14
+ - Starting a feature → `/gflow:plan`
15
+ - Touching auth or reCAPTCHA → `/gflow:known-issues`
16
+ - Cutting a release → `/gflow:release`
17
+ - Before any commit → `/gflow:check`
18
+
19
+ ## Gemini-specific
20
+
21
+ - Use specialized skills when relevant (e.g., `find-docs` for library research, `pr-council-review` for PR audits).
22
+ - Maintain memory via the `mcp-mempalace` tool if available.
23
+ - Prioritize **turn efficiency** and **high-signal output**.
24
+
25
+ ## Active phase
26
+
27
+ See [PLAN.md](PLAN.md) or run `/gflow:plan` for the current detailed plan.