gflow-cli 0.9.0__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.9.0 → 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.9.0 → gflow_cli-0.9.1}/.github/workflows/ci.yml +4 -8
  4. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.gitignore +3 -0
  5. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/CHANGELOG.md +91 -1
  6. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/KNOWN_ISSUES.md +85 -28
  7. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/PKG-INFO +2 -2
  8. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/PLAN.md +36 -20
  9. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/README.md +1 -1
  10. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/RELEASE.md +17 -1
  11. gflow_cli-0.9.1/conftest.py +25 -0
  12. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/DATA_LAYER.md +4 -2
  13. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/DEVELOPMENT.md +6 -1
  14. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/INDEX.md +1 -1
  15. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_v0.9.0.md +2 -0
  16. gflow_cli-0.9.1/docs/LIVE_VERIFICATION_v0.9.1.md +98 -0
  17. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/PROJECT_STATUS.md +5 -5
  18. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/USAGE.md +5 -2
  19. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/examples/README.md +3 -1
  20. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/examples/sample_config.json +1 -1
  21. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/examples/single_image_t2i.py +6 -4
  22. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/pyproject.toml +7 -1
  23. gflow_cli-0.9.1/scripts/dev/capture_i2v_frame_slots_dom.py +198 -0
  24. gflow_cli-0.9.1/scripts/dev/cdp_drive_and_probe.py +119 -0
  25. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/record_demo.ps1 +5 -2
  26. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/__init__.py +1 -1
  27. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/ui_automation.py +133 -24
  28. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/ui_automation_video.py +70 -25
  29. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/cli.py +17 -1
  30. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/cli_data.py +66 -18
  31. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/queries.py +22 -15
  32. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/repository.py +23 -1
  33. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/paths.py +9 -4
  34. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_ui_automation.py +148 -4
  35. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_ui_automation_video.py +144 -1
  36. gflow_cli-0.9.1/tests/cli/test_cli_auth_list.py +80 -0
  37. gflow_cli-0.9.1/tests/cli/test_cli_data.py +221 -0
  38. gflow_cli-0.9.1/tests/conftest.py +79 -0
  39. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/test_settings_and_errors.py +2 -1
  40. gflow_cli-0.9.1/tests/e2e/test_locale_selectors_e2e.py +87 -0
  41. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/test_transports_e2e.py +128 -0
  42. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/test_video_t2v_e2e.py +23 -13
  43. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/smoke/test_real_flow.py +8 -4
  44. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_browser_manager.py +8 -2
  45. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_cli_data.py +77 -7
  46. gflow_cli-0.9.1/tests/test_conftest_isolation.py +40 -0
  47. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_data_queries.py +26 -0
  48. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_paths.py +45 -0
  49. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/uv.lock +1 -1
  50. gflow_cli-0.9.0/docs/superpowers/notes/v0.9.0-schema-reconciliation.md +0 -108
  51. gflow_cli-0.9.0/docs/superpowers/plans/2026-05-24-v0.9.0-release-implementation.md +0 -2123
  52. gflow_cli-0.9.0/docs/superpowers/specs/2026-05-24-v0.9.0-release-design.md +0 -204
  53. gflow_cli-0.9.0/tests/cli/test_cli_data.py +0 -81
  54. gflow_cli-0.9.0/tests/conftest.py +0 -38
  55. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.claude/README.md +0 -0
  56. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.claude/commands/gflow/changelog.md +0 -0
  57. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.claude/commands/gflow/doc-review.md +0 -0
  58. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.claude/commands/gflow/known-issues.md +0 -0
  59. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.claude/commands/gflow/plan.md +0 -0
  60. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.claude/commands/gflow/release.md +0 -0
  61. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.continue-here.md +0 -0
  62. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.env.template +0 -0
  63. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.gitattributes +0 -0
  64. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.github/CODEOWNERS +0 -0
  65. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  66. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.github/copilot-instructions.md +0 -0
  67. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.github/dependabot.yml +0 -0
  68. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.github/workflows/external-pr-triage.yml +0 -0
  69. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.github/workflows/release.yml +0 -0
  70. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.gitleaks.toml +0 -0
  71. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.planning/todos/pending/2026-05-11-add-project-logo-and-docs-site-promotion-plan.md +0 -0
  72. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.planning/todos/pending/pr-38-review.md +0 -0
  73. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.pre-commit-config.yaml +0 -0
  74. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.secrets.baseline +0 -0
  75. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/AGENTS.md +0 -0
  76. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/CLAUDE.md +0 -0
  77. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/CONFIGURATION.md +0 -0
  78. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/CONTRIBUTING.md +0 -0
  79. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/DISCLAIMER.md +0 -0
  80. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/LICENSE +0 -0
  81. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/ROADMAP.md +0 -0
  82. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/AGENT_GUIDE.md +0 -0
  83. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/ARCHITECTURE.md +0 -0
  84. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/AUTHENTICATION.md +0 -0
  85. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/CONFIGURATION.md +0 -0
  86. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/DEBUGGING.md +0 -0
  87. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/GITHUB.md +0 -0
  88. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_data_layer.md +0 -0
  89. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_image_batch.md +0 -0
  90. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_v0.7.0.md +0 -0
  91. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_v0.8.1.md +0 -0
  92. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_video_download.md +0 -0
  93. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/SECURITY.md +0 -0
  94. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/USER_GUIDE.md +0 -0
  95. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/assets/example-run.gif +0 -0
  96. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/2026-05-17-issue-15-handover.md +0 -0
  97. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-09-image-mvp-orchestration.md +0 -0
  98. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-09-image-mvp.md +0 -0
  99. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +0 -0
  100. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-09-video-mvp.md +0 -0
  101. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-10-phase-4-hardening-orchestration.md +0 -0
  102. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-10-phase-4-hardening.md +0 -0
  103. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/2026-05-14-shell-multi-prompt-orchestration.md +0 -0
  104. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_ARCH.md +0 -0
  105. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_SEC_UX.md +0 -0
  106. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_CODE.md +0 -0
  107. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_GEMINI.md +0 -0
  108. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_SECURITY.md +0 -0
  109. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_PYTHON.md +0 -0
  110. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_SECURITY.md +0 -0
  111. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN.md +0 -0
  112. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_CODE.md +0 -0
  113. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_FOLLOWUP.md +0 -0
  114. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_PLANNER.md +0 -0
  115. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY.md +0 -0
  116. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY_FOLLOWUP.md +0 -0
  117. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_FINAL_SEC_UX_VERIFIED.md +0 -0
  118. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_PLAN_SECURITY.md +0 -0
  119. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_SPEC_SECURITY.md +0 -0
  120. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/PLAN.md +0 -0
  121. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/orchestration.md +0 -0
  122. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-17-e2e-test-coverage.md +0 -0
  123. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-17-issue-15-auth-verification-fix.md +0 -0
  124. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-17-issue-15-i2v-bearer-auth.md +0 -0
  125. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-17-issue-15-orchestration.md +0 -0
  126. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-18-video-phase0-submit-spike.md +0 -0
  127. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-19-video-phase-a-execution-state.md +0 -0
  128. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-19-video-phase-a-orchestration.md +0 -0
  129. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-19-video-phase-a-t2v.md +0 -0
  130. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-20-video-download-t2v-cli.md +0 -0
  131. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-21-multi-image-prompt-orchestration.md +0 -0
  132. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-21-multi-image-prompt.md +0 -0
  133. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-22-pr-38-review.md +0 -0
  134. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-22-stay-mounted-batch-session-plan.md +0 -0
  135. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-23-locale-agnostic-selectors.md +0 -0
  136. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-24-data-layer.md +0 -0
  137. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-10-phase-4-hardening-design.md +0 -0
  138. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-14-shell-multi-prompt-design.md +0 -0
  139. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-15-auth-login-real-chrome-design.md +0 -0
  140. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-17-e2e-test-coverage-design.md +0 -0
  141. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-17-i2v-uploadimage-401-bearer-auth-design.md +0 -0
  142. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-17-issue-15-auth-verification-fix-design.md +0 -0
  143. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-17-issue-15-root-cause-findings.md +0 -0
  144. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-18-ui-automation-video-generation-design.md +0 -0
  145. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-21-multi-image-prompt-design.md +0 -0
  146. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-22-pr-38-review-design.md +0 -0
  147. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-22-stay-mounted-batch-session-design.md +0 -0
  148. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-23-locale-agnostic-selectors.md +0 -0
  149. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-23-readme-v0.8.1-refresh-design.md +0 -0
  150. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-24-data-layer-design.md +0 -0
  151. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +0 -0
  152. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/examples/batch_from_config.py +0 -0
  153. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/examples/multi_prompt_t2i.py +0 -0
  154. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/examples/sample_prompts.txt +0 -0
  155. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/llms.txt +0 -0
  156. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/README.md +0 -0
  157. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/01_upload_image.json +0 -0
  158. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
  159. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
  160. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/04_archive_workflow.json +0 -0
  161. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/05_createProject.json +0 -0
  162. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/06_batchGenerateImages.json +0 -0
  163. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
  164. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/08_batchAsyncGenerateVideoStartAndEndImage.json +0 -0
  165. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/09_batchAsyncGenerateVideoReferenceImages.json +0 -0
  166. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/10_batchCheckAsyncVideoGenerationStatus_successful.json +0 -0
  167. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/11_batchCheckAsyncVideoGenerationStatus_failed.json +0 -0
  168. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/ci/check_doc_links.py +0 -0
  169. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/ci/check_repo_hygiene.py +0 -0
  170. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/debug_editor.py +0 -0
  171. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/debug_gen_settings.py +0 -0
  172. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/debug_settings.py +0 -0
  173. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/dev/active_plan.py +0 -0
  174. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/dev/capture_image_add_media_dom.py +0 -0
  175. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/dev/capture_locale_invariants.py +0 -0
  176. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/dev/monitor_pr_38.py +0 -0
  177. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/diag_capture_flow_traffic.py +0 -0
  178. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/diag_recaptcha_mint.py +0 -0
  179. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/smoke_image.py +0 -0
  180. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/smoke_real_chrome_image.py +0 -0
  181. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/smoke_video_editor.py +0 -0
  182. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/smoke_worker_style.py +0 -0
  183. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/verify_chrome_auth_viability.py +0 -0
  184. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/skills/README.md +0 -0
  185. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/skills/gflow-cli/SKILL.md +0 -0
  186. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/sonar-project.properties +0 -0
  187. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/__main__.py +0 -0
  188. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/_cli_helpers.py +0 -0
  189. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/__init__.py +0 -0
  190. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/_retry.py +0 -0
  191. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/client.py +0 -0
  192. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/dto.py +0 -0
  193. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/image.py +0 -0
  194. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/recaptcha.py +0 -0
  195. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/routes.py +0 -0
  196. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/__init__.py +0 -0
  197. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/_common.py +0 -0
  198. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/_fingerprint.py +0 -0
  199. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/base.py +0 -0
  200. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/experimental/__init__.py +0 -0
  201. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/experimental/bearer.py +0 -0
  202. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +0 -0
  203. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/experimental/sapisidhash.py +0 -0
  204. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/video.py +0 -0
  205. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/__init__.py +0 -0
  206. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/base.py +0 -0
  207. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/factory.py +0 -0
  208. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/internal_chromium.py +0 -0
  209. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/real_chrome.py +0 -0
  210. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/strategies.py +0 -0
  211. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/verification.py +0 -0
  212. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/browser_manager.py +0 -0
  213. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/cli_image.py +0 -0
  214. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/cli_run.py +0 -0
  215. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/cli_video.py +0 -0
  216. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/config.py +0 -0
  217. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/__init__.py +0 -0
  218. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/migrations/0001_initial.sql +0 -0
  219. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/migrations/__init__.py +0 -0
  220. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/models.py +0 -0
  221. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/recorder.py +0 -0
  222. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/redaction.py +0 -0
  223. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/store.py +0 -0
  224. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/errors.py +0 -0
  225. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/exceptions.py +0 -0
  226. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/image_batch.py +0 -0
  227. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/manifest.py +0 -0
  228. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/observability.py +0 -0
  229. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/profile_store.py +0 -0
  230. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tasks/lessons.md +0 -0
  231. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/test_assets/sample_batch.json +0 -0
  232. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/test_assets/sample_batch.tsv +0 -0
  233. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/test_assets/sample_batch_invalid.tsv +0 -0
  234. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/__init__.py +0 -0
  235. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/__init__.py +0 -0
  236. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_client.py +0 -0
  237. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_client_image.py +0 -0
  238. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_concurrency.py +0 -0
  239. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_dto.py +0 -0
  240. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_image.py +0 -0
  241. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_image_dto.py +0 -0
  242. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_recaptcha.py +0 -0
  243. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_retry.py +0 -0
  244. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_routes.py +0 -0
  245. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_video.py +0 -0
  246. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/__init__.py +0 -0
  247. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_base.py +0 -0
  248. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_bearer.py +0 -0
  249. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_common.py +0 -0
  250. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_evaluate_fetch.py +0 -0
  251. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_factory.py +0 -0
  252. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_fingerprint.py +0 -0
  253. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_sapisidhash.py +0 -0
  254. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_ui_automation_batch.py +0 -0
  255. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_ui_automation_image_mode.py +0 -0
  256. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/auth/strategies/test_factory.py +0 -0
  257. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/auth/strategies/test_strategies.py +0 -0
  258. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/auth/test_verification.py +0 -0
  259. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/__init__.py +0 -0
  260. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_cli_image.py +0 -0
  261. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_cli_image_seed_removed.py +0 -0
  262. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_cli_run.py +0 -0
  263. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_cli_video.py +0 -0
  264. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_error_handling.py +0 -0
  265. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_helpers.py +0 -0
  266. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_t2i_multi_prompt.py +0 -0
  267. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/__init__.py +0 -0
  268. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/test_packaging.py +0 -0
  269. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/test_recorder.py +0 -0
  270. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/test_redaction.py +0 -0
  271. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/test_repository.py +0 -0
  272. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/test_store_migrations.py +0 -0
  273. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/__init__.py +0 -0
  274. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/conftest.py +0 -0
  275. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/test_auth_verification_e2e.py +0 -0
  276. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/test_data_layer_e2e.py +0 -0
  277. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/test_image_batch_e2e.py +0 -0
  278. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/__init__.py +0 -0
  279. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/auth.feature +0 -0
  280. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/auth_login.feature +0 -0
  281. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/conftest.py +0 -0
  282. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/image.feature +0 -0
  283. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/test_auth_login_steps.py +0 -0
  284. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/test_auth_steps.py +0 -0
  285. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/test_image_steps.py +0 -0
  286. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/test_step_collision_guard.py +0 -0
  287. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/fixtures/__init__.py +0 -0
  288. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/fixtures/seeded_catalog.py +0 -0
  289. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/image_batch/__init__.py +0 -0
  290. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/image_batch/test_image_manifest.py +0 -0
  291. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/image_batch/test_observability_events.py +0 -0
  292. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/smoke/__init__.py +0 -0
  293. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_auth.py +0 -0
  294. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_config.py +0 -0
  295. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_errors.py +0 -0
  296. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_manifest.py +0 -0
  297. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_observability.py +0 -0
  298. {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_profile_store.py +0 -0
  299. {gflow_cli-0.9.0 → 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.
@@ -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/
@@ -7,6 +7,95 @@ 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
+
10
99
  ## [0.9.0] — 2026-05-25
11
100
 
12
101
  > **Maturity & Visibility release.** Surfaces the SQLite catalog (PR #52/#58)
@@ -945,7 +1034,8 @@ shell-script template that branches on these codes.
945
1034
 
946
1035
  First skeleton. Not functional end-to-end yet.
947
1036
 
948
- [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.9.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
949
1039
  [0.9.0]: https://github.com/ffroliva/gflow-cli/compare/v0.8.1...v0.9.0
950
1040
  [0.8.1]: https://github.com/ffroliva/gflow-cli/compare/v0.8.0...v0.8.1
951
1041
  [0.8.0]: https://github.com/ffroliva/gflow-cli/compare/v0.7.0...v0.8.0
@@ -319,19 +319,76 @@ issue and not blocked by any code change in this repo.
319
319
 
320
320
  - **Status:** Mitigated · **Severity:** Medium · **Tracking:** [issue #24](https://github.com/ffroliva/gflow-cli/issues/24)
321
321
 
322
- **Progress (2026-05-24, develop / post-v0.8.1, unreleased):**
323
-
324
- - **PR #51** Playwright's launch `locale=` is now env-overridable via
325
- `GFLOW_CLI_LOCALE` (default: `en-US`). Live-verified end-to-end with
326
- `GFLOW_CLI_LOCALE=pt-BR uv run pytest -m e2e tests/e2e/test_video_t2v_e2e.py`
327
- (1 credit, ~2.5 MB mp4, `MEDIA_GENERATION_STATUS_SUCCESSFUL`).
328
- - **PR #48** added the `--lang=en-US` Chromium launch arg so the editor UI
329
- itself stays in English regardless of the user's profile/system language.
330
- Currently mandatory because the I2V frame-slot labels and parts of
331
- `ONBOARDING_SELECTORS` / `NEW_PROJECT_SELECTORS` / `SUBMIT_BUTTON_SELECTORS`
332
- still match by localized text. Dropping `--lang=en-US` is the goal but
333
- requires invariant capture across the remaining text-matched selectors
334
- (`scripts/dev/capture_locale_invariants.py` is the diagnostic).
322
+ Status stays *Mitigated* (not *Resolved*) because `--lang=en-US` is still
323
+ passed and `NEW_PROJECT_SELECTORS` / `SUBMIT_BUTTON_SELECTORS` tails still
324
+ carry English-text fallbacks; the icon-first leads cover the common path,
325
+ but the dependency only fully clears after a live e2e on a non-English
326
+ Chrome profile.
327
+
328
+ **Phase 2 progress (2026-05-25, develop / post-v0.8.1, unreleased):**
329
+
330
+ - **`ONBOARDING_SELECTORS` restructured** replaced the original 9 English/PT-BR
331
+ text-only entries with a two-tier cascade:
332
+ 1. `_ONBOARDING_STRUCTURAL_SELECTORS` (3 strict entries) locale-free ARIA/ID
333
+ anchors: `button#L2AGLb` (Google Funding Choices SDK stable ID) plus exact
334
+ ARIA-label matches (`Accept all`, `I agree`). These are programmatic SDK
335
+ constants, not UI strings.
336
+ 2. `_ONBOARDING_TEXT_SELECTORS` (~37 entries) — leads with two
337
+ case-insensitive ARIA-partial entries (`aria-label*='Accept' i` /
338
+ `*='Agree' i`) that catch many CMP dialogs (OneTrust, Cookiebot) whose
339
+ aria-label values stay in English even on non-EN pages, followed by
340
+ `:has-text()` selectors covering 14 locales: EN, PT, DE, ES, FR, IT, NL,
341
+ JA, ZH, KO, PL, RU, TR, ID. The ARIA-partial entries live in this tier
342
+ because English aria-label values are not guaranteed across every CMP.
343
+ 3. `ONBOARDING_SELECTORS = (*_ONBOARDING_STRUCTURAL_SELECTORS, *_ONBOARDING_TEXT_SELECTORS)`
344
+ so structural entries are always tried first.
345
+ Cascade-ordering invariant is verified by `TestBypassOnboarding` in
346
+ `tests/api/transports/test_ui_automation.py`.
347
+
348
+ - **`_attach_frame` (I2V/R2V frame slots) flipped to structural-first** — was
349
+ English text-label first (`FRAME_SLOT_BY_LABEL`) with structural fallback; now
350
+ tries `FRAME_SLOTS_STRUCT` first, falls back to `FRAME_SLOT_BY_LABEL` only
351
+ when structural count is insufficient. Slot selection unit tests live in
352
+ `TestAttachFrameSlotSelection` (`tests/api/transports/test_ui_automation_video.py`).
353
+
354
+ **Correction (2026-05-26, issue #63):** PR #70's original
355
+ `FRAME_SLOTS_STRUCT = "div:has(> button:has(i.google-symbols:text-is('swap_horiz'))) > div[aria-haspopup='dialog']"`
356
+ matched **zero** elements on real Flow DOMs — the `swap_horiz` icon uses class
357
+ `material-icons` (NOT `google-symbols`) and the slots are `<div type="button">`,
358
+ not children of any `div > button` wrapper. Production I2V therefore relied on
359
+ the English-text fallback and silently broke on non-EN profiles. Discovered
360
+ via DOM probe + LIVE e2e on `ffroliva` (de-DE → pt-BR effective). Replaced
361
+ with `FRAME_SLOTS_STRUCT = "div[type='button'][aria-haspopup='dialog']"` (a
362
+ unique pattern in Flow's editor). Also added a `.first` fallback for the
363
+ End-frame case — after Start is attached, only one structural slot remains
364
+ and the prior `.nth(slot_index)` went out-of-bounds. Both fixes shipped
365
+ together via [#63](https://github.com/ffroliva/gflow-cli/issues/63).
366
+
367
+ - **`GFLOW_CLI_LOCALE`** — Playwright `locale=` env override from PR #51 remains
368
+ available (default `en-US`).
369
+
370
+ - **`--lang=en-US` dependency reduced** — `ONBOARDING_SELECTORS` and `_attach_frame`
371
+ no longer require it. The arg is still passed because removing it requires a
372
+ broader live-e2e sweep (I2V/R2V across multiple locales); it will be dropped
373
+ once that completes.
374
+
375
+ - **Live e2e on `de-DE` (2026-05-25)** — `GFLOW_CLI_LOCALE=de-DE` T2V on
376
+ `ffroliva` (Pro) completed in 70.9 s and returned `MEDIA_GENERATION_STATUS_SUCCESSFUL`
377
+ with a 3.1 MB 1280×720 H.264 mp4 (8 s clip). Confirms the structural-first
378
+ selectors and `GFLOW_CLI_LOCALE` env override work end-to-end on a locale
379
+ outside the original 9-entry English/PT-BR list.
380
+
381
+ - **Live I2V e2e on `de-DE` (2026-05-26, issue #63 closure)** —
382
+ `GFLOW_CLI_LOCALE=de-DE` I2V (Start + End frames) on `ffroliva` via
383
+ `tests/e2e/test_transports_e2e.py::test_e2e_i2v_start_end_frame_attach`
384
+ completed in 124 s and returned a terminal `SUCCESSFUL` `VideoResult` with a
385
+ downloaded mp4 carrying valid `ftyp` magic bytes. The test asserts on the
386
+ `ui_automation_video.frame_attached` structlog event for both Start and End,
387
+ proving the structural cascade resolved both slots without falling through
388
+ to the EN-text tier. Note: Chrome's UI rendered in pt-BR despite
389
+ `GFLOW_CLI_LOCALE=de-DE` (env affects Playwright's `Accept-Language`, not
390
+ Chrome's profile language) — both are non-EN so the test still verifies the
391
+ locale-leak fix.
335
392
 
336
393
  **Earlier — Phase 7 multi-image-prompt work** addressed the count-tab selectors:
337
394
  - `_COUNT_TAB_TEXT_RE = ^(1x|x[2-4])$` only matches the digit+x format Flow
@@ -339,21 +396,21 @@ issue and not blocked by any code change in this repo.
339
396
  - `_set_count` falls back to positional `.nth(count - 1)` when the read-back
340
397
  text is unrecognised — locale-invariant.
341
398
 
342
- Still localized as of this writing:
343
-
344
- - **`ONBOARDING_SELECTORS`** (`src/gflow_cli/api/transports/ui_automation.py:183-193`)
345
- nine button-text selectors only (`Agree` / `Aceitar` / `I agree` / `Concordo`
346
- / `Accept` / `Create with Flow` / `Criar com o Flow` / `Get Started` /
347
- `Começar`). An account whose Flow renders in an unlisted language (German,
348
- Japanese, ...) **cannot pass onboarding**. This is the issue's stated
349
- priority-1 item.
350
- - **`NEW_PROJECT_SELECTORS` localized fallbacks** + **`SUBMIT_BUTTON_SELECTORS` tail**
351
- — icon-first selectors lead, so these work today; the localized fallbacks
352
- remain as "maintenance debt and silent-failure risk" per the issue body.
353
-
354
- **Workaround:** the account must be in a locale that matches one of the
355
- hard-coded text selectors. For automation, prefer accounts whose Flow renders
356
- in English or Portuguese.
399
+ **Earlier PR #48:**
400
+ - Added `--lang=en-US` Chromium launch arg; parts of `NEW_PROJECT_SELECTORS` /
401
+ `SUBMIT_BUTTON_SELECTORS` tails still match by English text (icon-first selectors
402
+ lead and cover the common path, so these are maintenance debt rather than
403
+ active blockers).
404
+
405
+ **Full resolution requires:** live e2e verification on a non-English Chrome profile
406
+ (`GFLOW_CLI_LOCALE=<non-EN>` + a non-English browser profile) to confirm no
407
+ regression, then removing `--lang=en-US`.
408
+
409
+ **Workaround:** with Phase 2 changes, most locales are handled automatically.
410
+ For locales outside the 14 covered by `_ONBOARDING_TEXT_SELECTORS`, ARIA-based
411
+ structural selectors fire first and cover Google's Funding Choices consent SDK.
412
+ For non-standard CMP dialogs not covered, prefer accounts whose Flow renders in
413
+ one of the 14 supported locales or in English.
357
414
 
358
415
  ---
359
416
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gflow-cli
3
- Version: 0.9.0
3
+ Version: 0.9.1
4
4
  Summary: Unofficial CLI for Google Flow — drive Veo image-to-video generations from the terminal.
5
5
  Project-URL: Homepage, https://github.com/ffroliva/gflow-cli
6
6
  Project-URL: Issues, https://github.com/ffroliva/gflow-cli/issues
@@ -158,7 +158,7 @@ gflow CLI → Provider (interchangeable) → Flow (ui_automation) / Mock (te
158
158
 
159
159
  ## Project status
160
160
 
161
- **v0.9.0 — alpha.** Image (T2I / I2I / upload) + Video T2V / I2V / R2V live end-to-end on `ui_automation`, with a video `--model` picker (5 Veo models) + `--duration` / `--count`. New in v0.9.0: `gflow data list {projects,images,videos,profiles}` read CLI over the local SQLite catalog, `ROADMAP.md`, and locale-agnostic media-dialog selectors that fix non-English Chrome profiles. Only video `batch` (manifest runner) is still queued for Phase B — use a shell for-loop until then ([USAGE](docs/USAGE.md#gflow-video-batch)). Full milestone history → [docs/PROJECT_STATUS.md](docs/PROJECT_STATUS.md). Changelog → [CHANGELOG.md](CHANGELOG.md). Where the project is heading → [ROADMAP.md](ROADMAP.md).
161
+ **v0.9.1 — alpha.** Image (T2I / I2I / upload) + Video T2V / I2V / R2V live end-to-end on `ui_automation`, with a video `--model` picker (5 Veo models) + `--duration` / `--count`. New in v0.9.1: hardened locale-invariant Flow selectors, fixed I2V start/end-frame attachment for non-English Chrome/Flow sessions, and safer first-run catalog behavior. Only video `batch` (manifest runner) is still queued for Phase B — use a shell for-loop until then ([USAGE](docs/USAGE.md#gflow-video-batch)). Full milestone history → [docs/PROJECT_STATUS.md](docs/PROJECT_STATUS.md). Changelog → [CHANGELOG.md](CHANGELOG.md). Where the project is heading → [ROADMAP.md](ROADMAP.md).
162
162
 
163
163
  ## License & legal
164
164