gflow-cli 0.8.1__tar.gz → 0.9.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.claude/commands/gflow/check.md +5 -1
  2. gflow_cli-0.9.1/.claude/commands/gflow/pr-council-review.md +265 -0
  3. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.env.template +9 -0
  4. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.github/workflows/ci.yml +4 -8
  5. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.gitignore +3 -0
  6. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/AGENTS.md +2 -2
  7. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/CHANGELOG.md +212 -1
  8. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/KNOWN_ISSUES.md +130 -14
  9. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/PKG-INFO +21 -5
  10. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/PLAN.md +59 -24
  11. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/README.md +20 -4
  12. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/RELEASE.md +17 -1
  13. gflow_cli-0.9.1/ROADMAP.md +45 -0
  14. gflow_cli-0.9.1/conftest.py +25 -0
  15. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/ARCHITECTURE.md +5 -1
  16. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/CONFIGURATION.md +34 -0
  17. gflow_cli-0.9.1/docs/DATA_LAYER.md +401 -0
  18. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/DEVELOPMENT.md +6 -1
  19. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/INDEX.md +9 -1
  20. gflow_cli-0.9.1/docs/LIVE_VERIFICATION_data_layer.md +209 -0
  21. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_v0.8.1.md +28 -21
  22. gflow_cli-0.9.1/docs/LIVE_VERIFICATION_v0.9.0.md +109 -0
  23. gflow_cli-0.9.1/docs/LIVE_VERIFICATION_v0.9.1.md +98 -0
  24. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_video_download.md +5 -3
  25. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/PROJECT_STATUS.md +13 -2
  26. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/SECURITY.md +33 -0
  27. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/USAGE.md +151 -36
  28. gflow_cli-0.9.1/docs/superpowers/plans/2026-05-23-locale-agnostic-selectors.md +108 -0
  29. gflow_cli-0.9.1/docs/superpowers/plans/2026-05-24-data-layer.md +2452 -0
  30. gflow_cli-0.9.1/docs/superpowers/specs/2026-05-23-locale-agnostic-selectors.md +66 -0
  31. gflow_cli-0.9.1/docs/superpowers/specs/2026-05-23-readme-v0.8.1-refresh-design.md +359 -0
  32. gflow_cli-0.9.1/docs/superpowers/specs/2026-05-24-data-layer-design.md +403 -0
  33. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/examples/README.md +3 -1
  34. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/examples/sample_config.json +1 -1
  35. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/examples/single_image_t2i.py +6 -4
  36. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/llms.txt +3 -1
  37. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/pyproject.toml +7 -1
  38. gflow_cli-0.9.1/scripts/dev/capture_i2v_frame_slots_dom.py +198 -0
  39. gflow_cli-0.9.1/scripts/dev/capture_image_add_media_dom.py +184 -0
  40. gflow_cli-0.9.1/scripts/dev/capture_locale_invariants.py +87 -0
  41. gflow_cli-0.9.1/scripts/dev/cdp_drive_and_probe.py +119 -0
  42. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/record_demo.ps1 +5 -2
  43. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/__init__.py +1 -1
  44. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/client.py +99 -30
  45. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/dto.py +2 -0
  46. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/image.py +5 -0
  47. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/_common.py +16 -0
  48. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/base.py +25 -1
  49. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/ui_automation.py +212 -36
  50. gflow_cli-0.9.1/src/gflow_cli/api/transports/ui_automation_video.py +1058 -0
  51. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/video.py +124 -5
  52. gflow_cli-0.9.1/src/gflow_cli/auth/internal_chromium.py +158 -0
  53. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/auth/real_chrome.py +80 -67
  54. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/browser_manager.py +10 -19
  55. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/cli.py +19 -1
  56. gflow_cli-0.9.1/src/gflow_cli/cli_data.py +347 -0
  57. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/cli_image.py +257 -159
  58. gflow_cli-0.9.1/src/gflow_cli/cli_video.py +464 -0
  59. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/config.py +19 -0
  60. gflow_cli-0.9.1/src/gflow_cli/data/__init__.py +5 -0
  61. gflow_cli-0.9.1/src/gflow_cli/data/migrations/0001_initial.sql +100 -0
  62. gflow_cli-0.9.1/src/gflow_cli/data/migrations/__init__.py +1 -0
  63. gflow_cli-0.9.1/src/gflow_cli/data/models.py +179 -0
  64. gflow_cli-0.9.1/src/gflow_cli/data/queries.py +333 -0
  65. gflow_cli-0.9.1/src/gflow_cli/data/recorder.py +407 -0
  66. gflow_cli-0.9.1/src/gflow_cli/data/redaction.py +48 -0
  67. gflow_cli-0.9.1/src/gflow_cli/data/repository.py +607 -0
  68. gflow_cli-0.9.1/src/gflow_cli/data/store.py +239 -0
  69. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/errors.py +32 -0
  70. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/exceptions.py +3 -0
  71. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/image_batch.py +105 -20
  72. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/paths.py +14 -4
  73. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/test_client.py +60 -0
  74. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/test_concurrency.py +27 -0
  75. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/test_video.py +80 -0
  76. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/transports/test_common.py +16 -0
  77. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/transports/test_ui_automation.py +191 -4
  78. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/transports/test_ui_automation_video.py +262 -7
  79. gflow_cli-0.9.1/tests/cli/test_cli_auth_list.py +80 -0
  80. gflow_cli-0.9.1/tests/cli/test_cli_data.py +221 -0
  81. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/cli/test_cli_image.py +208 -18
  82. gflow_cli-0.9.1/tests/cli/test_cli_video.py +208 -0
  83. gflow_cli-0.9.1/tests/conftest.py +79 -0
  84. gflow_cli-0.9.1/tests/data/test_packaging.py +30 -0
  85. gflow_cli-0.9.1/tests/data/test_recorder.py +155 -0
  86. gflow_cli-0.9.1/tests/data/test_redaction.py +31 -0
  87. gflow_cli-0.9.1/tests/data/test_repository.py +272 -0
  88. gflow_cli-0.9.1/tests/data/test_settings_and_errors.py +48 -0
  89. gflow_cli-0.9.1/tests/data/test_store_migrations.py +114 -0
  90. gflow_cli-0.9.1/tests/e2e/test_data_layer_e2e.py +439 -0
  91. gflow_cli-0.9.1/tests/e2e/test_locale_selectors_e2e.py +87 -0
  92. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/e2e/test_transports_e2e.py +194 -0
  93. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/e2e/test_video_t2v_e2e.py +23 -13
  94. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/features/test_image_steps.py +1 -0
  95. gflow_cli-0.9.1/tests/fixtures/seeded_catalog.py +226 -0
  96. gflow_cli-0.9.1/tests/image_batch/__init__.py +0 -0
  97. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/image_batch/test_image_manifest.py +222 -1
  98. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/image_batch/test_observability_events.py +78 -0
  99. gflow_cli-0.9.1/tests/smoke/__init__.py +0 -0
  100. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/smoke/test_real_flow.py +8 -4
  101. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/test_browser_manager.py +8 -2
  102. gflow_cli-0.9.1/tests/test_cli_data.py +217 -0
  103. gflow_cli-0.9.1/tests/test_conftest_isolation.py +40 -0
  104. gflow_cli-0.9.1/tests/test_data_queries.py +177 -0
  105. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/test_errors.py +2 -2
  106. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/test_paths.py +45 -0
  107. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/uv.lock +1 -1
  108. gflow_cli-0.8.1/src/gflow_cli/api/transports/ui_automation_video.py +0 -543
  109. gflow_cli-0.8.1/src/gflow_cli/auth/internal_chromium.py +0 -147
  110. gflow_cli-0.8.1/src/gflow_cli/cli_video.py +0 -153
  111. gflow_cli-0.8.1/tests/cli/test_cli_video.py +0 -68
  112. gflow_cli-0.8.1/tests/conftest.py +0 -38
  113. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.claude/README.md +0 -0
  114. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.claude/commands/gflow/changelog.md +0 -0
  115. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.claude/commands/gflow/doc-review.md +0 -0
  116. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.claude/commands/gflow/known-issues.md +0 -0
  117. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.claude/commands/gflow/plan.md +0 -0
  118. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.claude/commands/gflow/release.md +0 -0
  119. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.continue-here.md +0 -0
  120. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.gitattributes +0 -0
  121. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.github/CODEOWNERS +0 -0
  122. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  123. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.github/copilot-instructions.md +0 -0
  124. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.github/dependabot.yml +0 -0
  125. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.github/workflows/external-pr-triage.yml +0 -0
  126. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.github/workflows/release.yml +0 -0
  127. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.gitleaks.toml +0 -0
  128. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.planning/todos/pending/2026-05-11-add-project-logo-and-docs-site-promotion-plan.md +0 -0
  129. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.planning/todos/pending/pr-38-review.md +0 -0
  130. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.pre-commit-config.yaml +0 -0
  131. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/.secrets.baseline +0 -0
  132. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/CLAUDE.md +0 -0
  133. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/CONFIGURATION.md +0 -0
  134. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/CONTRIBUTING.md +0 -0
  135. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/DISCLAIMER.md +0 -0
  136. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/LICENSE +0 -0
  137. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/AGENT_GUIDE.md +0 -0
  138. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/AUTHENTICATION.md +0 -0
  139. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/DEBUGGING.md +0 -0
  140. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/GITHUB.md +0 -0
  141. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_image_batch.md +0 -0
  142. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_v0.7.0.md +0 -0
  143. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/USER_GUIDE.md +0 -0
  144. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/assets/example-run.gif +0 -0
  145. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/2026-05-17-issue-15-handover.md +0 -0
  146. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-09-image-mvp-orchestration.md +0 -0
  147. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-09-image-mvp.md +0 -0
  148. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +0 -0
  149. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-09-video-mvp.md +0 -0
  150. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-10-phase-4-hardening-orchestration.md +0 -0
  151. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-10-phase-4-hardening.md +0 -0
  152. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/2026-05-14-shell-multi-prompt-orchestration.md +0 -0
  153. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_ARCH.md +0 -0
  154. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_SEC_UX.md +0 -0
  155. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_CODE.md +0 -0
  156. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_GEMINI.md +0 -0
  157. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_SECURITY.md +0 -0
  158. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_PYTHON.md +0 -0
  159. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_SECURITY.md +0 -0
  160. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN.md +0 -0
  161. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_CODE.md +0 -0
  162. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_FOLLOWUP.md +0 -0
  163. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_PLANNER.md +0 -0
  164. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY.md +0 -0
  165. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY_FOLLOWUP.md +0 -0
  166. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_FINAL_SEC_UX_VERIFIED.md +0 -0
  167. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_PLAN_SECURITY.md +0 -0
  168. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_SPEC_SECURITY.md +0 -0
  169. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/PLAN.md +0 -0
  170. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/orchestration.md +0 -0
  171. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-17-e2e-test-coverage.md +0 -0
  172. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-17-issue-15-auth-verification-fix.md +0 -0
  173. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-17-issue-15-i2v-bearer-auth.md +0 -0
  174. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-17-issue-15-orchestration.md +0 -0
  175. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-18-video-phase0-submit-spike.md +0 -0
  176. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-19-video-phase-a-execution-state.md +0 -0
  177. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-19-video-phase-a-orchestration.md +0 -0
  178. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-19-video-phase-a-t2v.md +0 -0
  179. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-20-video-download-t2v-cli.md +0 -0
  180. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-21-multi-image-prompt-orchestration.md +0 -0
  181. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-21-multi-image-prompt.md +0 -0
  182. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-22-pr-38-review.md +0 -0
  183. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-22-stay-mounted-batch-session-plan.md +0 -0
  184. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-10-phase-4-hardening-design.md +0 -0
  185. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-14-shell-multi-prompt-design.md +0 -0
  186. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-15-auth-login-real-chrome-design.md +0 -0
  187. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-17-e2e-test-coverage-design.md +0 -0
  188. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-17-i2v-uploadimage-401-bearer-auth-design.md +0 -0
  189. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-17-issue-15-auth-verification-fix-design.md +0 -0
  190. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-17-issue-15-root-cause-findings.md +0 -0
  191. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-18-ui-automation-video-generation-design.md +0 -0
  192. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-21-multi-image-prompt-design.md +0 -0
  193. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-22-pr-38-review-design.md +0 -0
  194. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-22-stay-mounted-batch-session-design.md +0 -0
  195. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +0 -0
  196. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/examples/batch_from_config.py +0 -0
  197. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/examples/multi_prompt_t2i.py +0 -0
  198. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/examples/sample_prompts.txt +0 -0
  199. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/samples/README.md +0 -0
  200. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/samples/captured/01_upload_image.json +0 -0
  201. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
  202. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
  203. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/samples/captured/04_archive_workflow.json +0 -0
  204. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/samples/captured/05_createProject.json +0 -0
  205. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/samples/captured/06_batchGenerateImages.json +0 -0
  206. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
  207. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/samples/captured/08_batchAsyncGenerateVideoStartAndEndImage.json +0 -0
  208. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/samples/captured/09_batchAsyncGenerateVideoReferenceImages.json +0 -0
  209. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/samples/captured/10_batchCheckAsyncVideoGenerationStatus_successful.json +0 -0
  210. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/samples/captured/11_batchCheckAsyncVideoGenerationStatus_failed.json +0 -0
  211. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/ci/check_doc_links.py +0 -0
  212. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/ci/check_repo_hygiene.py +0 -0
  213. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/debug_editor.py +0 -0
  214. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/debug_gen_settings.py +0 -0
  215. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/debug_settings.py +0 -0
  216. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/dev/active_plan.py +0 -0
  217. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/dev/monitor_pr_38.py +0 -0
  218. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/diag_capture_flow_traffic.py +0 -0
  219. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/diag_recaptcha_mint.py +0 -0
  220. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/smoke_image.py +0 -0
  221. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/smoke_real_chrome_image.py +0 -0
  222. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/smoke_video_editor.py +0 -0
  223. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/smoke_worker_style.py +0 -0
  224. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/scripts/verify_chrome_auth_viability.py +0 -0
  225. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/skills/README.md +0 -0
  226. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/skills/gflow-cli/SKILL.md +0 -0
  227. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/sonar-project.properties +0 -0
  228. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/__main__.py +0 -0
  229. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/_cli_helpers.py +0 -0
  230. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/__init__.py +0 -0
  231. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/_retry.py +0 -0
  232. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/recaptcha.py +0 -0
  233. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/routes.py +0 -0
  234. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/__init__.py +0 -0
  235. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/_fingerprint.py +0 -0
  236. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/experimental/__init__.py +0 -0
  237. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/experimental/bearer.py +0 -0
  238. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +0 -0
  239. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/experimental/sapisidhash.py +0 -0
  240. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/auth/__init__.py +0 -0
  241. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/auth/base.py +0 -0
  242. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/auth/factory.py +0 -0
  243. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/auth/strategies.py +0 -0
  244. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/auth/verification.py +0 -0
  245. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/cli_run.py +0 -0
  246. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/manifest.py +0 -0
  247. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/observability.py +0 -0
  248. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/src/gflow_cli/profile_store.py +0 -0
  249. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tasks/lessons.md +0 -0
  250. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/test_assets/sample_batch.json +0 -0
  251. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/test_assets/sample_batch.tsv +0 -0
  252. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/test_assets/sample_batch_invalid.tsv +0 -0
  253. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/__init__.py +0 -0
  254. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/__init__.py +0 -0
  255. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/test_client_image.py +0 -0
  256. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/test_dto.py +0 -0
  257. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/test_image.py +0 -0
  258. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/test_image_dto.py +0 -0
  259. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/test_recaptcha.py +0 -0
  260. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/test_retry.py +0 -0
  261. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/test_routes.py +0 -0
  262. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/transports/__init__.py +0 -0
  263. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/transports/test_base.py +0 -0
  264. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/transports/test_bearer.py +0 -0
  265. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/transports/test_evaluate_fetch.py +0 -0
  266. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/transports/test_factory.py +0 -0
  267. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/transports/test_fingerprint.py +0 -0
  268. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/transports/test_sapisidhash.py +0 -0
  269. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/transports/test_ui_automation_batch.py +0 -0
  270. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/api/transports/test_ui_automation_image_mode.py +0 -0
  271. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/auth/strategies/test_factory.py +0 -0
  272. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/auth/strategies/test_strategies.py +0 -0
  273. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/auth/test_verification.py +0 -0
  274. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/cli/__init__.py +0 -0
  275. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/cli/test_cli_image_seed_removed.py +0 -0
  276. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/cli/test_cli_run.py +0 -0
  277. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/cli/test_error_handling.py +0 -0
  278. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/cli/test_helpers.py +0 -0
  279. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/cli/test_t2i_multi_prompt.py +0 -0
  280. {gflow_cli-0.8.1/tests/e2e → gflow_cli-0.9.1/tests/data}/__init__.py +0 -0
  281. {gflow_cli-0.8.1/tests/features → gflow_cli-0.9.1/tests/e2e}/__init__.py +0 -0
  282. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/e2e/conftest.py +0 -0
  283. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/e2e/test_auth_verification_e2e.py +0 -0
  284. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/e2e/test_image_batch_e2e.py +0 -0
  285. {gflow_cli-0.8.1/tests/image_batch → gflow_cli-0.9.1/tests/features}/__init__.py +0 -0
  286. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/features/auth.feature +0 -0
  287. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/features/auth_login.feature +0 -0
  288. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/features/conftest.py +0 -0
  289. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/features/image.feature +0 -0
  290. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/features/test_auth_login_steps.py +0 -0
  291. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/features/test_auth_steps.py +0 -0
  292. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/features/test_step_collision_guard.py +0 -0
  293. {gflow_cli-0.8.1/tests/smoke → gflow_cli-0.9.1/tests/fixtures}/__init__.py +0 -0
  294. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/test_auth.py +0 -0
  295. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/test_config.py +0 -0
  296. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/test_manifest.py +0 -0
  297. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/test_observability.py +0 -0
  298. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/test_profile_store.py +0 -0
  299. {gflow_cli-0.8.1 → gflow_cli-0.9.1}/tests/test_smoke.py +0 -0
@@ -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,265 @@
1
+ ---
2
+ description: Multi-dimensional LLM council review of an open PR. Adaptive dimensions per PR surface (data / transports / CLI / docs / auth). Baseline always includes correctness, code quality, security, and tests. With no argument, lists open PRs ranked by review priority.
3
+ ---
4
+
5
+ # `/gflow:pr-council-review [PR#]` — PR Council Review Gate
6
+
7
+ Council-driven PR review. Dispatches **4 baseline + N adaptive** parallel reviewers, each scoped to one dimension, then synthesizes a single consensus verdict. Validated on PR #93 (2026-05-26) — see memory `llm-council-code-review-pr93`.
8
+
9
+ **Two modes:**
10
+ 1. **No argument** → list open PRs ranked by review priority; user picks.
11
+ 2. **`PR#` argument** → run the full council on that PR.
12
+
13
+ Treat **YELLOW as soft block** (per memory `llm-council-data-layer-fixes`).
14
+
15
+ ---
16
+
17
+ ## 0 · Pre-flight
18
+
19
+ **All four checks are mandatory. Any failure halts before Phase 1/2.**
20
+
21
+ 1. **`gh` authenticated** — run `gh auth status`. Non-zero exit → stop with: *"`gh` is not authenticated. Run `gh auth login` and re-invoke."* Do NOT proceed to dispatch agents that would all fail opaquely.
22
+ 2. **Inside the repo** — assert `AGENTS.md` AND `CLAUDE.md` exist in the working directory.
23
+ 3. **Resolve the argument:**
24
+ - **Empty** → jump to **Phase 1 (Prioritize)**.
25
+ - **PR number** → validate it with `gh pr view <N> --json number`. If error → stop with the error verbatim. Do NOT silently fall back to Phase 1.
26
+ 4. **Draft check** (PR# mode only) — if `gh pr view <N> --json isDraft` returns `true`, surface a banner citing memory `draft-pr-merge-trap`: *"PR #N is DRAFT. Reviewing is fine, but do NOT merge a draft (the merge API can close it + delete the head ref). Run `gh pr ready N` first if you intend to merge. Continue review? (yes/no)"*. Ask the user before dispatching.
27
+
28
+ ---
29
+
30
+ ## 1 · Prioritize (no-argument mode)
31
+
32
+ Run once, list open PRs in recommended order, then stop and ask the user which to review.
33
+
34
+ ```bash
35
+ gh pr list --state open --json number,title,author,isDraft,headRefName,updatedAt,additions,deletions,labels,reviewDecision,statusCheckRollup
36
+ ```
37
+
38
+ **Empty-list short-circuit:** if the result is `[]`, print *"No open PRs to review."* and exit. Do NOT render an empty table or fall through to Phase 2.
39
+
40
+ Rank with these heuristics (highest priority first):
41
+
42
+ | Signal | Weight | Why |
43
+ |---|---|---|
44
+ | `isDraft == false` AND CI all-green | +3 | Ready to merge once approved — highest ROI |
45
+ | Touched path includes `src/gflow_cli/api/transports/` | +2 | UI-automation is the highest-risk surface (memory `pr-must-verify-on-affected-surface`) |
46
+ | Touched path includes `src/gflow_cli/auth/` or `recaptcha` | +2 | Auth changes need security-deep-dive |
47
+ | Touched path includes `src/gflow_cli/data/` | +2 | Migration safety + #86 hygiene history |
48
+ | Older than 7 days (stale risk) | +1 | Conflict risk grows with age |
49
+ | `additions + deletions <= 300` | +1 | Small PRs ship faster |
50
+ | Label contains `release-blocker`, `security`, `hotfix` | +5 | Anything labelled urgent jumps the queue |
51
+ | `isDraft == true` AND CI red | −2 | Author still iterating; review wastes their time |
52
+
53
+ Present a numbered table:
54
+
55
+ ```
56
+ | Rank | PR# | Title | Ready? | CI | Surface | Why prioritized |
57
+ |------|-----|-------|--------|----|---------| ---------------|
58
+ | 1 | #71 | feat(image): native count selector … | ✅ | green | transports | Ready + transports surface + small (220 LOC) |
59
+ | 2 | …
60
+ ```
61
+
62
+ Then **stop and ask** the user to pick a PR number. Do NOT auto-start a review on Rank 1 — *recommend*, do not *pre-select*. The user MUST type the PR number they want reviewed.
63
+
64
+ ---
65
+
66
+ ## 2 · Gather context (PR# mode)
67
+
68
+ Pull in parallel. Use `ctx_batch_execute` to avoid context-window flood.
69
+
70
+ **Commands** (label → cmd):
71
+ - `PR_META` → `gh pr view <N> --json title,body,author,baseRefName,headRefName,state,isDraft,additions,deletions,changedFiles,labels,files,statusCheckRollup`
72
+ - `PR_DIFF` → `gh pr diff <N>`
73
+ - `PR_CHECKS` → `gh pr checks <N>`
74
+ - `TOUCHED_PATHS` → `gh pr view <N> --json files --jq '.files[].path' | sort -u`
75
+ - `RECENT_COMMITS` → `gh pr view <N> --json commits --jq '.commits[-5:] | .[] | "\(.oid[:7]) \(.messageHeadline)"'`
76
+
77
+ **Reference files** (Read inline; small enough to load):
78
+ - `CLAUDE.md` — Claude-Code-specific protocol
79
+ - `AGENTS.md` — universal agent rules
80
+ - `docs/INDEX.md` — docs routing
81
+ - `~/.claude/projects/C--development-github-gflow-cli/memory/MEMORY.md` — memory index
82
+
83
+ **Memory traversal:** For each `TOUCHED_PATH`, glob memory for related entries:
84
+ - `transports/` (image OR video) → `[[pr-must-verify-on-affected-surface]]`, `[[flow-locale-leak-icon-ligatures]]`, `[[playwright-click-no-downstream-event-signature]]`, `[[rest-transports-drop-ui-fields]]`, `[[image-video-mode-switch-symmetry]]`, `[[video-generation-spec]]`, `[[image-generation-401-next]]`
85
+ - `data/` → `[[data-layer-overview]]`, `[[data-layer-test-pollution-trap]]`, `[[data-layer-v0.9.0-bugs]]`, `[[exit-code-16-data-store]]`, `[[on-started-callback-recorder-safety]]`
86
+ - `auth/` → `[[real-browser-auth-mandatory]]`, `[[release-signing]]`
87
+ - `cli` → `[[release-back-merge-gap-recovery]]`, `[[wheel-build-sanity-gate]]`
88
+ - `tests/` (any) → `[[bdd-stubs-mirror-runtime-signatures]]`, `[[background-e2e-pytest-pattern]]`, `[[full-test-suite-ooms]]`, `[[stale-test-discovery]]`, `[[structlog-cache-logger-off-for-tests]]`
89
+ - `tests/features/` (BDD) → also `[[bdd-stubs-mirror-runtime-signatures]]` (silent TypeError trap)
90
+ - `scripts/` (dev / CI / release helpers) → `[[wheel-build-sanity-gate]]`, `[[release-back-merge-gap-recovery]]`
91
+ - `.planning/`, `docs/superpowers/` (process artifacts) → `[[release-spec-plan-memory-consolidation]]`
92
+ - `docs/`, `*.md` → `[[readme-hybrid-router-pattern]]`, `[[llm-council-doc-review-v0.9.0]]`, `[[agents-md-vs-llms-txt]]`, `[[pypi-readme-staleness-fix]]`
93
+ - `pyproject.toml`, `.github/` → `[[release-spec-plan-memory-consolidation]]`, `[[pr-hygiene-revert-and-multi-commit]]`, `[[draft-pr-merge-trap]]`, `[[pypi-rejected-filename-reusable]]`
94
+
95
+ ---
96
+
97
+ ## 3 · Detect adaptive dimensions
98
+
99
+ The **baseline** 4 dimensions run for every PR. **Adaptive** dimensions activate only when the touched paths or labels match. Build the council roster before dispatching.
100
+
101
+ | Dimension | Always? | Activates when… |
102
+ |---|---|---|
103
+ | **D1 — Correctness & completeness** | ✅ baseline | always |
104
+ | **D2 — Code quality & best practices** | ✅ baseline | always |
105
+ | **D3 — Security** | ✅ baseline | always |
106
+ | **D4 — Tests & coverage** | ✅ baseline | always |
107
+ | **D5 — UI / live-verification** | adaptive | any path under `src/gflow_cli/api/transports/` or `tests/e2e/` |
108
+ | **D6 — Data-migration safety** | adaptive | any path under `src/gflow_cli/data/` or `*.sql` |
109
+ | **D7 — CLI UX & help-text consistency** | adaptive | any path matching `src/gflow_cli/cli*.py` or `src/gflow_cli/commands/` |
110
+ | **D8 — Docs cross-reference & drift** | adaptive | ≥2 of these touched: `README.md`, `docs/**`, `CHANGELOG.md`, `AGENTS.md`, `CLAUDE.md`, `PLAN.md` |
111
+ | **D9 — Auth / reCAPTCHA / Chrome-profile** | adaptive | any path under `src/gflow_cli/auth/` or label `security` |
112
+ | **D10 — Release-gate compliance** | adaptive | `pyproject.toml`, `src/gflow_cli/__init__.py`, `.github/workflows/`, or `release/*` branch |
113
+ | **D11 — BDD step-stub signatures** | adaptive | any path under `tests/features/` (silent TypeError trap, memory `bdd-stubs-mirror-runtime-signatures`) |
114
+ | **D12 — Dev / release scripts** | adaptive | any path under `scripts/` |
115
+
116
+ **Baseline floor is non-negotiable.** D1–D4 ALWAYS run, even on docs-only PRs. The user spec explicitly required quality / security / best-practices / tests as a floor — do not skip.
117
+
118
+ **Docs-only PRs** (defined as: 100% of touched paths match `*.md`, `docs/**`, `CHANGELOG.md`, `README.md`, `LICENSE`, `AUTHORS`) → D4 reframes from "test code coverage" to "docs-verification" (broken cross-references, dead links, code examples that don't run). The dimension still runs; only its lens shifts.
119
+
120
+ ---
121
+
122
+ ## 4 · Dispatch the council
123
+
124
+ Use `superpowers:dispatching-parallel-agents`. Send **all** agents in one message — they must run concurrently. Each agent must:
125
+
126
+ - Get the PR number, base branch, and head branch.
127
+ - Be told its dimension AND told what NOT to duplicate (the other dimensions' scope).
128
+ - Use `ctx_execute` for large outputs (diff, file reads) — never flood the context.
129
+ - Output a structured report: **Verdict (GREEN / YELLOW / RED)**, **Must-fix** (numbered, file:line refs), **Nice-to-have** (numbered), **Confirmed-good/safe/correct** (1-line bullets).
130
+ - Be word-limited to **under 500 words** so the synthesizer doesn't drown.
131
+
132
+ **Per-dimension prompt skeleton** (fill in `<…>`):
133
+
134
+ ```
135
+ You are one of <N> parallel reviewers on a council reviewing PR #<N> of `gflow-cli` at C:\development\github\gflow-cli.
136
+
137
+ Your dimension is **<DIMENSION NAME>**. Other agents handle <other dimensions> — do NOT duplicate their work.
138
+
139
+ Get the diff with `gh pr diff <N>` via ctx_execute. If `additions + deletions > 5000`, do NOT pull the full diff at once — instead enumerate touched files with `gh pr view <N> --json files --jq '.files[].path'`, then read per-directory with `gh pr diff <N> -- <path>` to keep each call under 2k lines. Read the unchanged surrounding code with Read for any file you flag.
140
+
141
+ Assess specifically:
142
+ 1. <dimension-specific question 1, with code citation hooks>
143
+ 2. <…>
144
+ 3. <…>
145
+
146
+ **Mandatory memory you MUST consult and cite if relevant** (from the Dimension → Slugs table below): <fixed slug list for this dimension>.
147
+
148
+ Output a structured report under 500 words:
149
+ - Verdict: GREEN / YELLOW / RED
150
+ - Must-fix (numbered, file:line refs)
151
+ - Nice-to-have (numbered)
152
+ - Confirmed-<good/safe/correct> (1-line bullets)
153
+
154
+ Be skeptical. Cite file paths and line numbers. **If you have nothing to flag in your dimension, say so explicitly and state GREEN with a one-line justification — do NOT manufacture findings to look thorough.**
155
+ ```
156
+
157
+ **Dimension → mandatory slugs table** (always pass these in the prompt, regardless of which paths the PR touches — they encode the recurring traps for that dimension):
158
+
159
+ | Dim | Mandatory memory slugs |
160
+ |---|---|
161
+ | D1 | `[[pr-must-verify-on-affected-surface]]` |
162
+ | D2 | (none mandatory; consult surrounding code style) |
163
+ | D3 | `[[real-browser-auth-mandatory]]`, `[[release-signing]]` |
164
+ | D4 | `[[pr-must-verify-on-affected-surface]]`, `[[full-test-suite-ooms]]`, `[[stale-test-discovery]]`, `[[structlog-cache-logger-off-for-tests]]` |
165
+ | D5 | `[[flow-locale-leak-icon-ligatures]]`, `[[playwright-click-no-downstream-event-signature]]`, `[[rest-transports-drop-ui-fields]]`, `[[image-video-mode-switch-symmetry]]`, `[[verification-ledger-5-layer]]` |
166
+ | D6 | `[[on-started-callback-recorder-safety]]`, `[[data-layer-test-pollution-trap]]`, `[[exit-code-16-data-store]]`, `[[data-layer-v0.9.0-bugs]]` |
167
+ | D7 | (none mandatory) |
168
+ | D8 | `[[readme-hybrid-router-pattern]]`, `[[agents-md-vs-llms-txt]]`, `[[pypi-readme-staleness-fix]]`, `[[llm-council-doc-review-v0.9.0]]` |
169
+ | D9 | `[[real-browser-auth-mandatory]]` |
170
+ | D10 | `[[release-back-merge-gap-recovery]]`, `[[wheel-build-sanity-gate]]`, `[[pypi-rejected-filename-reusable]]`, `[[draft-pr-merge-trap]]` |
171
+ | D11 | `[[bdd-stubs-mirror-runtime-signatures]]` |
172
+ | D12 | `[[wheel-build-sanity-gate]]` |
173
+
174
+ **Per-dimension specifics** (concrete checks each agent must perform):
175
+
176
+ - **D1 Correctness & completeness:**
177
+ - Does the fix address the *root cause* or only the symptom? Cite the function being changed.
178
+ - Are edge cases handled? Spot-check 2 boundary conditions.
179
+ - Does the CHANGELOG entry match what shipped? Quote both.
180
+ - **PR-body compliance:** does the PR body's description match the diff? Are the PR body's test-plan checkboxes (the `- [ ]` / `- [x]` markers) accurate? If any unchecked box represents work the PR claims to deliver, flag it. If the PR claims `Closes #N` for an issue whose acceptance criteria are not met by the diff, flag it.
181
+ - **D2 Code quality:** Style consistency with surrounding code? Comments explain WHY not WHAT (per `CLAUDE.md`)? Any abstraction that doesn't earn its keep? SRP intact? Type annotations on every new signature?
182
+ - **D3 Security:** Injection vectors? Env-var trust boundary? Shell interpolation (`subprocess`, `shell=True`)? Path traversal? Secret-shaped literals? `--no-verify` or signature-bypass in commits?
183
+ - **D4 Tests:**
184
+ - **Mandatory affected-surface check** (cardinal rule, memory `pr-must-verify-on-affected-surface`): identify the runtime surface the fix touches (T2V / I2V / R2V / data / CLI / auth / etc.). If the test suite does not exercise that exact surface (e.g. a fix for `_attach_frame` with only T2V tests), this is **automatically YELLOW**. Cite the test `file:line` that proves coverage of the affected surface — or state explicitly that no such test exists.
185
+ - Test pyramid placement (unit vs integration vs e2e)?
186
+ - Do tests verify *behavior* or just shape (static strings, mocked returns)?
187
+ - Coverage delta meaningful, or dead-coverage (counts new constants without exercising them)?
188
+ - **D5 UI/live-verify:** Will this selector match real Flow DOM on non-EN locales? Is there runtime evidence beyond static-string invariants? Has the PR author pasted live-verify evidence (file count + magic bytes + Pillow dims + structlog events such as `new_project_clicked` / `submit_clicked` / `frame_attached` / `image_mode_entered` / `count_setter_completed` / `reference_attached`) in the PR body or a comment? **Absent live-verify on a UI-automation PR is YELLOW per memory `pr-must-verify-on-affected-surface`.**
189
+ - **D6 Data-migration & on_started safety:**
190
+ - **Mandatory on_started callback check** (memory `on-started-callback-recorder-safety`): grep the diff for `VideoStartedCallback` / `on_started` / any new callback invoked inside a transport during a paid Flow generation. Verify each callsite is wrapped in `try/except DataStoreError` (and ideally a broad guard). **A bare callback in a paid-generation path is automatically RED** — uncaught exceptions abort paid generation.
191
+ - Schema-compat with existing rows? Migration script idempotent?
192
+ - `DataStoreError` vs `DataMigrationError` vs `DataIntegrityError` semantics correct? Pre-Flow failures vs post-success-warn-and-return-0 per memory `exit-code-16-data-store`?
193
+ - **D7 CLI UX:** Help text matches behavior? Flag names follow `--kebab-case`? Does the new flag appear in `--help` golden-snapshot tests? Examples in docstring runnable?
194
+ - **D8 Docs drift:** Cross-references mutually consistent (CLAUDE.md / AGENTS.md / docs/INDEX.md / README.md / PLAN.md)? Code examples actually run? Version strings consistent across files?
195
+ - **D9 Auth:** Chrome-strategy profile required (memory `real-browser-auth-mandatory`)? Profile-dir SecurityError boundary intact (`outside of GFLOW_CLI_HOME`)? No new secret-shaped strings?
196
+ - **D10 Release-gate:**
197
+ - **Quote the version string** from `pyproject.toml` AND from `src/gflow_cli/__init__.py` and confirm they match exactly. If only one was bumped → RED.
198
+ - Verify `CHANGELOG.md` `[Unreleased]` was emptied and a new version section added — cite the line range.
199
+ - Wheel build clean (`uv build` + ZIP-dupe check per memory `wheel-build-sanity-gate`)?
200
+ - Back-merge gap from prior releases addressed (memory `release-back-merge-gap-recovery`)?
201
+ - **D11 BDD step-stub signatures:** any new `_run_*` kwarg or runtime signature change requires mirroring in `tests/features/_fake_*` stubs — silent `TypeError` trap. Cite each fake stub touched (or assert no signature change occurred).
202
+ - **D12 Dev/release scripts:** any new script must run cleanly on Windows (memory `windows-dev-quirks`); release scripts must include the wheel-build sanity gate.
203
+
204
+ ---
205
+
206
+ ## 5 · Synthesize the verdict
207
+
208
+ After all agents return:
209
+
210
+ 1. **Tally verdicts:** count GREEN / YELLOW / RED per dimension.
211
+ 2. **Handle missing agents:** if any dimension failed to return (timeout, dispatch error), mark it `UNKNOWN` and downgrade the consensus by one step (GREEN → YELLOW, YELLOW → YELLOW, RED stays RED). Never wait indefinitely. Surface which dimension is missing so the user can re-dispatch if they want.
212
+ 3. **Consensus rule:**
213
+ - Any RED → **RED** (block merge).
214
+ - Any YELLOW → **YELLOW** (soft block — must address before merge, per memory `llm-council-data-layer-fixes`).
215
+ - All GREEN → **GREEN** (mergeable).
216
+ 4. **Deduplicate must-fix AND confirmed-good items:** if two dimensions flag the same issue (or confirm the same positive), list it once and credit both.
217
+ 5. **Live-verify gate** (D5 fired + PR body has unchecked live-verify boxes): emit an explicit `AskUserQuestion` with three options — (a) *Run now (estimate: ~1 Flow image credit per locale)*, (b) *Block merge — add to PR body as required reviewer action*, (c) *Skip and accept the risk*. Cite memory `verification-ledger-5-layer` in the question body so the user is reminded that file count alone is not proof. Do NOT spend credits without an explicit affirmative click.
218
+ 6. **YELLOW escape valve:** when reporting in Phase 6, the `AskUserQuestion` MUST include a *"Dismiss YELLOW with justification (logged)"* option so the user is never trapped without a path forward. Dismissal requires a one-line reason that gets appended to the PR body or comment, so the override is auditable.
219
+
220
+ ---
221
+
222
+ ## 6 · Report
223
+
224
+ Output to the user, in this exact shape:
225
+
226
+ ```
227
+ # PR #<N> — Council Review Verdict
228
+
229
+ ## Consensus: <emoji> <GREEN | YELLOW | RED>
230
+
231
+ | Dimension | Verdict | Headline |
232
+ |---|---|---|
233
+ | <D1> | … | <one-line summary> |
234
+ | <D2> | … | … |
235
+
236
+
237
+ ## Must-fix (<N>)
238
+ 1. **<short title>** — `<file>:<line>`. <description>. <which dimension flagged>.
239
+ 2. …
240
+
241
+ ## Nice-to-have (<N>)
242
+ 1. …
243
+
244
+ ## Confirmed-good (high-confidence positives)
245
+ - …
246
+
247
+ ## How to proceed
248
+ <AskUserQuestion: which must-fixes to apply now, whether to run live-verify, etc.>
249
+ ```
250
+
251
+ Always end with an `AskUserQuestion` so the user can drive next steps (apply fixes, post evidence, dismiss findings).
252
+
253
+ ---
254
+
255
+ ## 7 · Provenance & extensions
256
+
257
+ > **Provenance:** the council protocol below was validated on PR #93 (locale selectors + DB isolation, merged 2026-05-26). The audit found an unanchored regex + a silent-test-pyramid gap that 152 passing unit tests missed. Then a meta-council audited *this* command itself, surfacing 13 must-fix items now applied. See memory `[[llm-council-code-review-pr93]]`.
258
+
259
+ - Council baseline = 4 dimensions (D1–D4) always run. Adaptive ceiling = D5–D12 (currently). Going beyond ~12 dimensions adds noise faster than signal — split into two reviews instead.
260
+ - Each agent currently uses `general-purpose`. If a future dedicated `code-reviewer` subagent ships, swap it in.
261
+ - If a PR touches paths that don't match any adaptive dimension, document the gap and add a new dimension here (D13+).
262
+ - The command is **stateless** — concurrent invocations on different PR numbers don't share data, so two instances can run in parallel without interference.
263
+ - **Idempotence:** running the same council on the same PR SHA should produce comparable verdicts on different days. If verdicts drift, the cause is usually (a) memory grew new precedents, or (b) the mandatory-slug table here needs an update. Drift is informational, not a defect.
264
+ - No destructive git/gh actions are taken by this command. Reviews are read-only. The user always drives apply-fix / push / merge through subsequent commands.
265
+ - **Sibling commands.** `/review` is the single-agent Claude-Code built-in (one-pass code review, fast and cheap) — use it for spot-checks, draft iteration, or when the council is overkill. `/gflow:pr-council-review` is the multi-agent council version — use it before merge, on high-risk surfaces (auth, transports, data, release-gate), or whenever a single-agent pass would miss the cross-dimension defects the council is designed to catch.
@@ -77,3 +77,12 @@
77
77
  # (Google's bot-detection sometimes refuses headless Chromium but accepts a
78
78
  # visible window). The session is still reused from the persistent profile.
79
79
  # GFLOW_CLI_HEADLESS=true
80
+
81
+ # BCP-47 locale tag passed to Playwright's launch `locale=` parameter
82
+ # (controls Accept-Language only — Chrome's UI language is forced to
83
+ # en-US via the `--lang=en-US` launch arg regardless of this setting, so
84
+ # Flow stays on /fx/tools/flow/ instead of /fx/<locale>/). Default:
85
+ # `en-US`. Override to capture locale-invariant DOM via
86
+ # scripts/dev/capture_locale_invariants.py or to live-verify a non-EN
87
+ # language end-to-end (see KNOWN_ISSUES § issue #24).
88
+ # GFLOW_CLI_LOCALE=en-US
@@ -54,14 +54,10 @@ jobs:
54
54
  run: uv run pyright src
55
55
 
56
56
  - 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
57
+ # e2e/live tests require a logged-in Chromium profile and may spend
58
+ # Flow credits. pyproject.toml excludes both markers by default; CI
59
+ # intentionally relies on that default smoke set.
60
+ run: uv run python -m pytest -q --cov=gflow_cli --cov-report=xml
65
61
 
66
62
  # Upload coverage XML so the sonar job can consume it
67
63
  - name: Upload coverage report
@@ -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/
@@ -78,3 +79,5 @@ samples/captured/flow_outgoing_*.json
78
79
 
79
80
  worktrees/
80
81
 
82
+ # E2E test logs (live Flow runs — may contain account/profile names)
83
+ .planning/e2e-logs/
@@ -8,7 +8,7 @@ Supported tools that auto-discover this file: Cursor, Codex, Aider, Gemini CLI,
8
8
 
9
9
  - Unofficial Python CLI for [Google Flow](https://labs.google/fx/tools/flow) — drives Veo (image-to-video, text-to-video) and Imagen (text-to-image) generations from the terminal by reverse-engineering Flow's private REST API at `aisandbox-pa.googleapis.com`.
10
10
  - Python 3.11+ · `uv`-managed · `hatchling` builds · Playwright Chromium transport · `pyright` strict · `ruff` · `pytest`.
11
- - Single-package modular monolith. Top-level modules under `src/gflow_cli/`: `api/`, `auth/`, `browser_manager.py`, `cli.py`, `_cli_helpers.py`, `cli_image.py`, `cli_run.py`, `cli_video.py`, `config.py`, `errors.py`, `exceptions.py`, `image_batch.py`, `manifest.py`, `observability.py`, `paths.py`, `profile_store.py`.
11
+ - Single-package modular monolith. Top-level modules under `src/gflow_cli/`: `api/`, `auth/`, `browser_manager.py`, `cli.py`, `_cli_helpers.py`, `cli_data.py`, `cli_image.py`, `cli_run.py`, `cli_video.py`, `config.py`, `data/`, `errors.py`, `exceptions.py`, `image_batch.py`, `manifest.py`, `observability.py`, `paths.py`, `profile_store.py`.
12
12
  - Requires a Google AI Ultra or Pro subscription with Flow access. All generations bill against the user's own Google account.
13
13
 
14
14
  ## Headed-browser dependency (architectural reality)
@@ -53,7 +53,7 @@ Or invoke the wrapper: `/gflow:check`.
53
53
 
54
54
  - Type hints everywhere; `pyright` strict on `src/gflow_cli`.
55
55
  - Structured logging only (`structlog`) — **never** raw `print()` or `import logging` in `src/`.
56
- - Errors as RFC 9457 Problem Details with stable per-class exit codes (3–15). See `src/gflow_cli/errors.py::EXIT_CODE_MAP` for the complete mapping.
56
+ - Errors as RFC 9457 Problem Details with stable per-class exit codes (3–16, where 16 is the `DataStoreError` family from `gflow_cli.data`). See `src/gflow_cli/errors.py::EXIT_CODE_MAP` for the complete mapping.
57
57
  - 100-char line length, `ruff` configured. Imports sorted by `ruff` (isort rules).
58
58
 
59
59
  ## PR instructions
@@ -7,6 +7,214 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.9.1] — 2026-05-27
11
+
12
+ > **Locale and catalog patch release.** Hardens the headed-browser UI
13
+ > automation path for localized Flow profiles, fixes I2V start/end-frame
14
+ > attachment on non-English Chrome/Flow sessions, and repairs first-run catalog
15
+ > edge cases found after v0.9.0.
16
+
17
+ ### Changed
18
+
19
+ - `NEW_PROJECT_SELECTORS` now covers all 14 supported locales (EN / PT / ES /
20
+ FR / DE / IT / NL / JA / ZH / KO / PL / RU / TR / ID) and leads with
21
+ locale-stable icon selectors (`add_2` Material Symbols ligature on
22
+ `<button>` and on `[role='button']` ARIA-role variants, plus an anchored
23
+ `^\+\s+\S+$` regex for `+ <word>` host elements). English-only
24
+ `[aria-label*='New project']` and `[aria-label*='Project']` ARIA fallbacks
25
+ removed.
26
+ `SUBMIT_BUTTON_SELECTORS` drops its English-only
27
+ `button[aria-label*="Create"]` fallback — the preceding `arrow_forward` icon
28
+ entries already cover this button in every locale. Both selector tuples are
29
+ now fully locale-invariant for non-English Chrome profiles. The `--lang=en-US`
30
+ Chromium launch arg is retained only to stabilise `IMAGE_MODEL_OPTION_SELECTORS`
31
+ (English product names); its removal is tracked as issue #24 Phase 5 (#94).
32
+
33
+ ### Fixed
34
+
35
+ - Bare `pytest` no longer collects live/e2e tests by default. The project-wide
36
+ pytest `addopts` now excludes `e2e` and `live` unless callers explicitly pass
37
+ a different `-m` expression, and `tests/smoke/test_real_flow.py` is marked
38
+ with both markers so marker-filtered local and CI runs cannot accidentally
39
+ launch a real Flow browser session.
40
+ - Browser-manager PID tests no longer call the real `os.kill` while pretending
41
+ to be on POSIX from a Windows runner. The POSIX liveness branches are now
42
+ tested with mocked `os.kill`, avoiding hard interpreter/session exits during
43
+ local test runs.
44
+
45
+ - Running the pytest suite no longer writes fixture rows into the developer's
46
+ production `gflow.db` catalog. A new autouse `_isolate_settings` fixture in
47
+ `tests/conftest.py` redirects `GFLOW_CLI_HOME` and `GFLOW_CLI_DB_PATH` to
48
+ per-test `tmp_path` dirs and clears the `get_settings()` `lru_cache` before
49
+ and after every test, preventing the cached singleton from ever resolving to
50
+ a `platformdirs` production path. Closes
51
+ [#86](https://github.com/ffroliva/gflow-cli/issues/86).
52
+
53
+ - `gflow video i2v` no longer silently breaks on non-English Chrome profiles.
54
+ PR #70's structural-first `_attach_frame` cascade matched **zero** real
55
+ slots — its anchor selector assumed the `swap_horiz` icon used class
56
+ `google-symbols` (it uses `material-icons`) and the slots were `<button>`
57
+ (they're `<div type="button">`). Production I2V therefore relied on the
58
+ English-text fallback, which silently misses on any non-EN profile (pt-BR
59
+ shows `Inicial`/`Final`, DE shows `Anfang`/`Ende`, etc.). Replaced
60
+ `FRAME_SLOTS_STRUCT` with the locale-free pattern
61
+ `div[type='button'][aria-haspopup='dialog']` and added a `.first`-of-remaining
62
+ fallback for the End-frame case (after Start is attached, only one slot
63
+ matches and the prior `.nth(slot_index)` went out-of-bounds). Live-verified
64
+ with `tests/e2e/test_transports_e2e.py::test_e2e_i2v_start_end_frame_attach`
65
+ on `ffroliva` + `GFLOW_CLI_LOCALE=de-DE` (Chrome rendered pt-BR; both
66
+ non-EN). Closes [#63](https://github.com/ffroliva/gflow-cli/issues/63).
67
+
68
+ ### Changed
69
+
70
+ - `gflow data media <id>` now searches across **all** profiles by default,
71
+ matching the cross-profile default of `gflow data list`. Pass
72
+ `--profile NAME` to disambiguate the rare case where the same Flow
73
+ media ID exists under multiple profiles (the command refuses to
74
+ guess and prints the list of candidate profiles, each annotated with
75
+ its `kind`). Closes
76
+ [#87](https://github.com/ffroliva/gflow-cli/issues/87).
77
+
78
+ ### Fixed
79
+
80
+ - `gflow data list` no longer crashes with `no such table: assets` on a
81
+ missing or freshly-created catalog DB. The query path now routes through
82
+ `DataStore.open`, which applies schema migrations on first connect —
83
+ first-time users and anyone recovering from a wiped DB get an empty
84
+ table and exit 0 instead of a `DataStoreError`. Closes
85
+ [#88](https://github.com/ffroliva/gflow-cli/issues/88).
86
+ - `gflow auth list` no longer crashes with `UnicodeEncodeError` on Windows
87
+ consoles whose code page cannot encode the default-profile marker `●`
88
+ (cp1252 in PowerShell / cmd by default). The renderer now picks a glyph
89
+ safe for the active `sys.stdout.encoding` — `●` on UTF-8, ASCII `*` on
90
+ cp1252 / ascii / latin-1 / unknown. Closes [#82](https://github.com/ffroliva/gflow-cli/issues/82).
91
+
92
+ ### Documentation
93
+
94
+ - `PLAN.md` refreshed to reflect develop state through v0.9.0 — marks Phase 6
95
+ (data layer) shipped via PR #58 + #78 + #81, Phase 7 Issue #24 Phase 2
96
+ shipped via PR #70, Phase B I2V/R2V shipped via PR #48, and resolves the
97
+ duplicate Phase 7 numbering (pluggable storage renumbered to Phase 8).
98
+
99
+ ## [0.9.0] — 2026-05-25
100
+
101
+ > **Maturity & Visibility release.** Surfaces the SQLite catalog (PR #52/#58)
102
+ > via a read-only `gflow data list {projects,images,videos,profiles}` CLI,
103
+ > publishes `ROADMAP.md`, and ships the locale-agnostic media-dialog
104
+ > selectors that unblock non-English Chrome profiles. Plus the previously-
105
+ > unreleased video model picker, i2v/r2v, and the I2I ref-attach + model-
106
+ > select fixes. Sponsorship wiring will land in a follow-up patch release
107
+ > once GitHub Sponsors / Buy Me a Coffee accounts are fully provisioned.
108
+
109
+ ### Added
110
+
111
+ - `gflow data list {projects,images,videos,profiles}` — read-only catalog
112
+ query CLI over the local SQLite data layer. Flags: `--limit` (1..1000,
113
+ default 20), `--offset` (≥0, default 0), `--profile NAME`, `--json`.
114
+ Rich table on TTY, JSONL on pipe or `--json`. Default sort: newest first.
115
+ `DataStoreError` family maps to exit code 16. See
116
+ [`docs/DATA_LAYER.md § Querying the data layer`](docs/DATA_LAYER.md#querying-the-data-layer).
117
+ - `ROADMAP.md` at repo root — themed milestones from v0.9 through v1.0 (no
118
+ dates).
119
+ - `gflow video t2v` model picker: `--model` (`omni-flash` | `veo-lite` |
120
+ `veo-fast` | `veo-quality` | `veo-lite-lp`), `--duration` (`4`/`6`/`8`, plus
121
+ `10` for `omni-flash` only), and `--count` (1–4). Driven via the editor's
122
+ generation-settings panel; live-verified against a Pro/Ultra profile.
123
+ - `gflow video i2v <image> "<prompt>"` — image-to-video with a start frame and
124
+ an optional `--end-image` (interpolation). Fires
125
+ `batchAsyncGenerateVideoStartImage` / `…StartAndEndImage`.
126
+ - `gflow video r2v "<prompt>" --ref <img> [--ref …]` — reference-to-video
127
+ (Flow "ingredients"). Model-aware reference cap (omni_flash ≤7, veo_3_1_* ≤3)
128
+ enforced in the request DTO; the transport stops gracefully if Flow hides the
129
+ add-media button at the cap. Fires `batchAsyncGenerateVideoReferenceImages`.
130
+ - `GFLOW_CLI_LOCALE` env var — overrides Playwright's launch `locale=` parameter
131
+ (default: `en-US`). Controls `Accept-Language` only; Chrome's UI language is
132
+ still forced to en-US via `--lang=en-US`. Prep for issue #24 (locale-agnostic
133
+ selectors); live-verified end-to-end with `GFLOW_CLI_LOCALE=pt-BR` against a
134
+ Pro/Ultra account. See `docs/CONFIGURATION.md § GFLOW_CLI_LOCALE`.
135
+ - **Local data layer** — `gflow-cli` now keeps a SQLite catalog of every new
136
+ image, batch, and video operation under `$GFLOW_CLI_DB_PATH` (default:
137
+ `~/.local/share/gflow-cli/data.db`). Records profile, project, asset
138
+ (model / aspect / dimensions / Flow media ID), operation provenance
139
+ (mode / prompt / model / timing / error), input↔output links, and
140
+ downloaded local files. New `gflow data media <id>` command resolves a
141
+ Flow media ID to its origin. `DataRepository` exposes seed-image resolvers
142
+ (`resolve_seed_image_by_path` / `resolve_seed_image` /
143
+ `resolve_latest_image`) — foundation for the upcoming I2V seed-reuse
144
+ path. Pre-Flow store failures exit `16` (`DataStoreError` /
145
+ `DataMigrationError` / `DataIntegrityError`); post-success store
146
+ failures warn and exit `0` (Flow already charged the credits). See
147
+ [`docs/DATA_LAYER.md`](docs/DATA_LAYER.md). (PR #58, stacked on #52.)
148
+
149
+ ### Changed
150
+
151
+ - `MAX_REFERENCE_IMAGES` (in `api/video.py`) now tracks the `omni_flash`
152
+ ceiling of **7** (was **3**). The tighter per-model cap (`veo_3_1_* ≤ 3`) is
153
+ still enforced in `GenerateVideoRequest.__post_init__` when the model is
154
+ known; the constant is only the absolute upper bound. Anyone pinning to the
155
+ old value of 3 should re-check against the per-model caps.
156
+
157
+ ### Fixed
158
+
159
+ - `FlowApiClient.__aenter__` now tears down a partially-launched browser if any
160
+ step after the Playwright driver starts raises (e.g. the persistent-context
161
+ launch, the bootstrap navigation, or `transport.setup`). Python does not call
162
+ `__aexit__` when `__aenter__` raises, so an unguarded failure orphaned the
163
+ chrome process, which then held the profile's user-data-dir lock — the next
164
+ run could not acquire it and spiralled into rapid `about:blank` tabs +
165
+ `TargetClosedError`. Context close + driver stop are now shared by
166
+ `__aenter__`'s guard and `__aexit__` via `_close_browser_resources`.
167
+ - `gflow image i2i --ref <local-file>` now binds the reference through the
168
+ editor's media dialog instead of the REST `uploadImage` endpoint (which 401s —
169
+ same root as #15/#39). Local-path refs ride a new `GenerateImageRequest.ref_paths`
170
+ field and are attached via the inherited R2V `_attach_references` (the image-mode
171
+ add-media dialog is the same `add_2` surface). Bare-UUID `--ref` still flows
172
+ through `refs` unchanged. Re-introduces #50 (reverted in #57 for the account/
173
+ locale variant tracked in #56); the media-dialog selectors are now
174
+ locale-agnostic (see the next entry).
175
+ - The media-dialog upload selectors are now **locale-agnostic** (issue #56/#24).
176
+ `UPLOAD_MEDIA_BUTTON` matched localized text (`has-text('Upload media')`), so on
177
+ a non-English Chrome profile (Flow follows the *Chrome profile* language, which
178
+ the `--lang=en-US` arg cannot override) the click missed and the file chooser
179
+ never opened — a silent ~34s hang. It now anchors on the locale-free `upload`
180
+ icon ligature (`:text-is('upload')`, exact, so it doesn't grab the `Uploads`
181
+ tab), with the original English-text selector kept as a graceful **fallback
182
+ tier** (matches if Google ever changes the icon but keeps the English label);
183
+ 'Add to Prompt' (which has no icon) is selected structurally as the only
184
+ iconless button in the open dialog. If neither tier opens a chooser,
185
+ `_upload_via_open_dialog` raises a clear error + writes a screenshot (no silent
186
+ hang) and points the operator at the Chrome-profile-language workaround. Fixes
187
+ I2I/I2V/R2V upload alike.
188
+ - `gflow image t2i/i2i --model` now actually selects the requested model. It was
189
+ a no-op under `ui_automation` (the wire field was set but the model picker was
190
+ never clicked, so Flow used its UI default). Adds `_select_image_model`.
191
+ - Video selector mismatches: the output-count selector `[id*=-trigger-1]`
192
+ collided with the `-trigger-10` duration tab; the aspect selector matched a
193
+ non-existent `aria-controls*=9_16`; the video-mode tab match was ambiguous.
194
+ All now use exact `[id$=-trigger-X]` suffixes + aria-label text.
195
+
196
+ ### Build
197
+
198
+ - **Wheel build no longer emits duplicate ZIP entries.** An earlier attempt at
199
+ tagging v0.9.0 was rejected by PyPI with HTTP 400 ("Duplicate filename in
200
+ local headers") because `pyproject.toml` had
201
+ `[tool.hatch.build.targets.wheel.force-include]` and
202
+ `[tool.hatch.build.targets.sdist.force-include]` blocks pointing at
203
+ `src/gflow_cli/data/migrations`, on top of the already-comprehensive
204
+ `packages = ["src/gflow_cli"]` directive — hatchling included the
205
+ migrations directory twice (both `__init__.py` and `0001_initial.sql`). The
206
+ force-include blocks have been removed; hatchling's default package
207
+ inclusion already covers `.sql` files inside the package tree. (PR #74.)
208
+
209
+ ### Notes
210
+
211
+ - I2V/R2V image inputs bind through the editor's media dialog (frame slot /
212
+ add-media → "Upload media" → file chooser → "Add to Prompt"). `set_input_files`
213
+ on the generic hidden input only adds to the library and Flow then ignores the
214
+ image (plain Text route). The editor is forced to English via the
215
+ `--lang=en-US` Chromium launch arg because the slot/dialog labels are localized
216
+ with no locale-free anchor.
217
+
10
218
  ## [0.8.1] — 2026-05-23
11
219
 
12
220
  ### Documentation
@@ -826,7 +1034,10 @@ shell-script template that branches on these codes.
826
1034
 
827
1035
  First skeleton. Not functional end-to-end yet.
828
1036
 
829
- [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.8.0...HEAD
1037
+ [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.9.1...HEAD
1038
+ [0.9.1]: https://github.com/ffroliva/gflow-cli/compare/v0.9.0...v0.9.1
1039
+ [0.9.0]: https://github.com/ffroliva/gflow-cli/compare/v0.8.1...v0.9.0
1040
+ [0.8.1]: https://github.com/ffroliva/gflow-cli/compare/v0.8.0...v0.8.1
830
1041
  [0.8.0]: https://github.com/ffroliva/gflow-cli/compare/v0.7.0...v0.8.0
831
1042
  [0.7.0]: https://github.com/ffroliva/gflow-cli/compare/v0.6.0a6...v0.7.0
832
1043
  [0.6.0a6]: https://github.com/ffroliva/gflow-cli/compare/v0.6.0a5...v0.6.0a6