gflow-cli 0.6.0a4__tar.gz → 0.6.0a6__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 (188) hide show
  1. gflow_cli-0.6.0a6/.github/CODEOWNERS +22 -0
  2. gflow_cli-0.6.0a6/.github/dependabot.yml +34 -0
  3. gflow_cli-0.6.0a6/.github/workflows/ci.yml +96 -0
  4. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/.gitignore +13 -0
  5. gflow_cli-0.6.0a6/.gitleaks.toml +33 -0
  6. gflow_cli-0.6.0a6/.pre-commit-config.yaml +38 -0
  7. gflow_cli-0.6.0a6/.secrets.baseline +152 -0
  8. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/CHANGELOG.md +98 -1
  9. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/CLAUDE.md +10 -2
  10. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/CONTRIBUTING.md +14 -9
  11. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/KNOWN_ISSUES.md +14 -0
  12. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/PKG-INFO +4 -3
  13. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/PLAN.md +175 -1
  14. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/README.md +3 -2
  15. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/ARCHITECTURE.md +4 -0
  16. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/SECURITY.md +37 -1
  17. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/USER_GUIDE.md +161 -0
  18. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/pyproject.toml +2 -1
  19. gflow_cli-0.6.0a6/scripts/ci/check_repo_hygiene.py +141 -0
  20. gflow_cli-0.6.0a6/scripts/debug_editor.py +69 -0
  21. gflow_cli-0.6.0a6/scripts/debug_gen_settings.py +83 -0
  22. gflow_cli-0.6.0a6/scripts/debug_settings.py +69 -0
  23. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/diag_capture_flow_traffic.py +1 -1
  24. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/smoke_worker_style.py +188 -38
  25. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/verify_chrome_auth_viability.py +9 -9
  26. gflow_cli-0.6.0a6/sonar-project.properties +35 -0
  27. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/__init__.py +1 -1
  28. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/_retry.py +2 -1
  29. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/client.py +28 -9
  30. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/image.py +4 -0
  31. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/experimental/bearer.py +4 -2
  32. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/experimental/sapisidhash.py +3 -0
  33. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/ui_automation.py +313 -55
  34. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/auth/__init__.py +2 -2
  35. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/auth/internal_chromium.py +0 -4
  36. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/auth/real_chrome.py +11 -10
  37. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/browser_manager.py +93 -111
  38. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/cli_image.py +46 -30
  39. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/config.py +7 -6
  40. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/image_batch.py +0 -1
  41. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/manifest.py +18 -17
  42. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_client.py +4 -2
  43. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_concurrency.py +1 -0
  44. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_evaluate_fetch.py +2 -2
  45. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_ui_automation.py +49 -36
  46. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/auth/strategies/test_strategies.py +24 -7
  47. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/e2e/test_transports_e2e.py +1 -1
  48. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_browser_manager.py +9 -0
  49. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_config.py +6 -5
  50. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_smoke.py +2 -1
  51. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/uv.lock +184 -1
  52. gflow_cli-0.6.0a4/.github/workflows/ci.yml +0 -42
  53. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/.claude/README.md +0 -0
  54. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/.claude/commands/release.md +0 -0
  55. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/.env.template +0 -0
  56. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/.gitattributes +0 -0
  57. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/.github/workflows/release.yml +0 -0
  58. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/.planning/todos/pending/2026-05-11-add-project-logo-and-docs-site-promotion-plan.md +0 -0
  59. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/CONFIGURATION.md +0 -0
  60. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/DISCLAIMER.md +0 -0
  61. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/LICENSE +0 -0
  62. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/RELEASE.md +0 -0
  63. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/AUTHENTICATION.md +0 -0
  64. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/CONFIGURATION.md +0 -0
  65. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/INDEX.md +0 -0
  66. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/USAGE.md +0 -0
  67. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/assets/example-run.gif +0 -0
  68. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-09-image-mvp-orchestration.md +0 -0
  69. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-09-image-mvp.md +0 -0
  70. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +0 -0
  71. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-09-video-mvp.md +0 -0
  72. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-10-phase-4-hardening-orchestration.md +0 -0
  73. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-10-phase-4-hardening.md +0 -0
  74. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/2026-05-14-shell-multi-prompt-orchestration.md +0 -0
  75. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_ARCH.md +0 -0
  76. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_SEC_UX.md +0 -0
  77. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_CODE.md +0 -0
  78. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_GEMINI.md +0 -0
  79. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_SECURITY.md +0 -0
  80. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_PYTHON.md +0 -0
  81. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_SECURITY.md +0 -0
  82. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN.md +0 -0
  83. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_CODE.md +0 -0
  84. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_FOLLOWUP.md +0 -0
  85. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_PLANNER.md +0 -0
  86. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY.md +0 -0
  87. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY_FOLLOWUP.md +0 -0
  88. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_FINAL_SEC_UX_VERIFIED.md +0 -0
  89. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_PLAN_SECURITY.md +0 -0
  90. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_SPEC_SECURITY.md +0 -0
  91. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/PLAN.md +0 -0
  92. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/orchestration.md +0 -0
  93. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/specs/2026-05-10-phase-4-hardening-design.md +0 -0
  94. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/specs/2026-05-14-shell-multi-prompt-design.md +0 -0
  95. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/specs/2026-05-15-auth-login-real-chrome-design.md +0 -0
  96. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +0 -0
  97. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/examples/README.md +0 -0
  98. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/examples/batch_from_config.py +0 -0
  99. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/examples/multi_prompt_t2i.py +0 -0
  100. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/examples/sample_config.json +0 -0
  101. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/examples/sample_prompts.txt +0 -0
  102. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/examples/single_image_t2i.py +0 -0
  103. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/README.md +0 -0
  104. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/01_upload_image.json +0 -0
  105. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
  106. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
  107. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/04_archive_workflow.json +0 -0
  108. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/05_createProject.json +0 -0
  109. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/06_batchGenerateImages.json +0 -0
  110. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
  111. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/diag_recaptcha_mint.py +0 -0
  112. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/record_demo.ps1 +0 -0
  113. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/smoke_e2e.py +0 -0
  114. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/smoke_image.py +0 -0
  115. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/smoke_real_chrome_image.py +0 -0
  116. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/skills/README.md +0 -0
  117. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/skills/gflow-cli/SKILL.md +0 -0
  118. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/__main__.py +0 -0
  119. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/_cli_helpers.py +0 -0
  120. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/__init__.py +0 -0
  121. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/dto.py +0 -0
  122. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/recaptcha.py +0 -0
  123. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/routes.py +0 -0
  124. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/__init__.py +0 -0
  125. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/_common.py +0 -0
  126. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/_fingerprint.py +0 -0
  127. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/base.py +0 -0
  128. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/experimental/__init__.py +0 -0
  129. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +0 -0
  130. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/video.py +0 -0
  131. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/auth/base.py +0 -0
  132. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/auth/factory.py +0 -0
  133. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/auth/strategies.py +0 -0
  134. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/cli.py +0 -0
  135. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/cli_run.py +0 -0
  136. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/cli_video.py +0 -0
  137. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/errors.py +0 -0
  138. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/observability.py +0 -0
  139. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/paths.py +0 -0
  140. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/profile_store.py +0 -0
  141. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tasks/lessons.md +0 -0
  142. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/__init__.py +0 -0
  143. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/__init__.py +0 -0
  144. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_client_generate_video.py +0 -0
  145. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_client_image.py +0 -0
  146. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_dto.py +0 -0
  147. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_image.py +0 -0
  148. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_image_dto.py +0 -0
  149. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_recaptcha.py +0 -0
  150. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_retry.py +0 -0
  151. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_routes.py +0 -0
  152. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_video.py +0 -0
  153. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/__init__.py +0 -0
  154. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_base.py +0 -0
  155. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_bearer.py +0 -0
  156. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_common.py +0 -0
  157. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_factory.py +0 -0
  158. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_fingerprint.py +0 -0
  159. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_sapisidhash.py +0 -0
  160. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/auth/strategies/test_factory.py +0 -0
  161. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/cli/__init__.py +0 -0
  162. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/cli/test_cli_image.py +0 -0
  163. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/cli/test_cli_run.py +1 -1
  164. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/cli/test_error_handling.py +0 -0
  165. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/cli/test_helpers.py +0 -0
  166. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/cli/test_t2i_multi_prompt.py +0 -0
  167. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/conftest.py +0 -0
  168. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/e2e/__init__.py +0 -0
  169. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/__init__.py +0 -0
  170. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/auth.feature +0 -0
  171. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/auth_login.feature +0 -0
  172. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/conftest.py +0 -0
  173. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/image.feature +0 -0
  174. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/test_auth_login_steps.py +0 -0
  175. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/test_auth_steps.py +0 -0
  176. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/test_image_steps.py +0 -0
  177. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/test_step_collision_guard.py +0 -0
  178. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/test_video_steps.py +0 -0
  179. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/video.feature +0 -0
  180. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/smoke/__init__.py +0 -0
  181. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/smoke/test_real_flow.py +0 -0
  182. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_auth.py +0 -0
  183. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_cli_video.py +0 -0
  184. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_errors.py +0 -0
  185. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_manifest.py +0 -0
  186. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_observability.py +0 -0
  187. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_paths.py +0 -0
  188. {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_profile_store.py +0 -0
@@ -0,0 +1,22 @@
1
+ # CODEOWNERS — https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
2
+ #
3
+ # These owners are automatically requested for review on every PR that touches
4
+ # the matched paths. Ownership does not prevent external contributors from
5
+ # opening PRs — it ensures a maintainer is always in the review loop.
6
+
7
+ # Global fallback — everything not matched below
8
+ * @ffroliva
9
+
10
+ # Core source
11
+ /src/ @ffroliva
12
+
13
+ # CI and security gates — changes here require extra care
14
+ /.github/ @ffroliva
15
+ /scripts/ci/ @ffroliva
16
+ /.pre-commit-config.yaml @ffroliva
17
+ /.gitleaks.toml @ffroliva
18
+ /.secrets.baseline @ffroliva
19
+ /.gitignore @ffroliva
20
+
21
+ # Auth handling — sensitive, never bypass review
22
+ /src/gflow_cli/auth.py @ffroliva
@@ -0,0 +1,34 @@
1
+ # Dependabot configuration
2
+ # Docs: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
3
+
4
+ version: 2
5
+ updates:
6
+ # Python dependencies (pip/uv — Dependabot reads pyproject.toml)
7
+ - package-ecosystem: "pip"
8
+ directory: "/"
9
+ schedule:
10
+ interval: "weekly"
11
+ day: "monday"
12
+ time: "08:00"
13
+ timezone: "Europe/Lisbon"
14
+ open-pull-requests-limit: 5
15
+ labels:
16
+ - "dependencies"
17
+ - "python"
18
+ ignore:
19
+ # Playwright has its own browser download step; pin manually.
20
+ - dependency-name: "playwright"
21
+ update-types: ["version-update:semver-major"]
22
+
23
+ # GitHub Actions
24
+ - package-ecosystem: "github-actions"
25
+ directory: "/"
26
+ schedule:
27
+ interval: "weekly"
28
+ day: "monday"
29
+ time: "08:00"
30
+ timezone: "Europe/Lisbon"
31
+ open-pull-requests-limit: 5
32
+ labels:
33
+ - "dependencies"
34
+ - "github-actions"
@@ -0,0 +1,96 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ env:
9
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
10
+
11
+ jobs:
12
+ # ── Security gate: runs first, on every push/PR, never skippable ──────────
13
+ secrets-scan:
14
+ name: Secret scan (gitleaks)
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ with:
19
+ fetch-depth: 0 # full history so gitleaks can diff against base
20
+
21
+ - name: Run gitleaks
22
+ uses: gitleaks/gitleaks-action@v2
23
+ env:
24
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25
+
26
+ # ── Main test matrix ──────────────────────────────────────────────────────
27
+ test:
28
+ runs-on: ubuntu-latest
29
+ strategy:
30
+ matrix:
31
+ python-version: ["3.11", "3.12", "3.13"]
32
+ steps:
33
+ - uses: actions/checkout@v4
34
+
35
+ - name: Install uv
36
+ uses: astral-sh/setup-uv@v3
37
+
38
+ - name: Set up Python
39
+ run: uv python install ${{ matrix.python-version }}
40
+
41
+ - name: Install deps
42
+ run: uv sync --extra dev
43
+
44
+ - name: Repo hygiene (no artefacts, no hardcoded paths)
45
+ run: uv run python scripts/ci/check_repo_hygiene.py
46
+
47
+ - name: Lint
48
+ run: uv run ruff check src tests
49
+
50
+ - name: Format check
51
+ run: uv run ruff format --check src tests
52
+
53
+ - name: Type check
54
+ run: uv run pyright src
55
+
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
65
+
66
+ # Upload coverage XML so the sonar job can consume it
67
+ - name: Upload coverage report
68
+ if: matrix.python-version == '3.11'
69
+ uses: actions/upload-artifact@v4
70
+ with:
71
+ name: coverage-xml
72
+ path: coverage.xml
73
+ retention-days: 1
74
+
75
+ # ── SonarCloud analysis ───────────────────────────────────────────────────
76
+ sonar:
77
+ name: SonarCloud analysis
78
+ runs-on: ubuntu-latest
79
+ needs: test # wait for tests + coverage report
80
+ if: always() # run even if test matrix has failures — Sonar should see the state
81
+ steps:
82
+ - uses: actions/checkout@v4
83
+ with:
84
+ fetch-depth: 0 # shallow clones break blame / new-code detection
85
+
86
+ - name: Download coverage report
87
+ uses: actions/download-artifact@v4
88
+ with:
89
+ name: coverage-xml
90
+ continue-on-error: true # graceful if coverage upload was skipped
91
+
92
+ - name: SonarCloud scan
93
+ uses: SonarSource/sonarcloud-github-action@master
94
+ env:
95
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # PR decoration
96
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} # set in repo → Settings → Secrets
@@ -43,12 +43,25 @@ secrets.json # generic secrets file
43
43
  # Generated outputs
44
44
  out/
45
45
  tmp/
46
+ gflow-output/
46
47
  *.mp4
47
48
  *.png
49
+ *.jpg
50
+ *.jpeg
48
51
  !docs/**/*.png # docs images are OK
49
52
  !tests/fixtures/**/*.png
53
+ !test_assets/fixtures/**/*.jpg
54
+ !test_assets/fixtures/**/*.jpeg
50
55
  samples/*.captured.json # sandbox-recorded API exchanges may contain PII
51
56
 
57
+ # CDP browser session lock files (contain PID, port, profile name)
58
+ .gflow-cdp.lock
59
+ **/.gflow-cdp.lock
60
+
61
+ # Runtime artefact dirs written by smoke/debug scripts — belong under tmp/ only
62
+ test_assets/smoke_*/
63
+ test_assets/debug_*/
64
+
52
65
  # Live Flow traffic captures — NEVER commit (contain real Bearer tokens / API keys).
53
66
  # Diagnostic scripts MUST default-write here, NOT to samples/captured/.
54
67
  # Sanitised reference samples (no secrets) can still live under samples/captured/.
@@ -0,0 +1,33 @@
1
+ # gitleaks configuration for gflow-cli
2
+ # Docs: https://github.com/gitleaks/gitleaks#configuration
3
+ #
4
+ # This file tells gitleaks which patterns to IGNORE (allowlist) so that
5
+ # legitimate test fixtures and documentation snippets don't trigger false
6
+ # positives. The default ruleset catches: Google API keys, OAuth tokens,
7
+ # GitHub tokens, generic secrets, private keys, and more.
8
+
9
+ title = "gflow-cli gitleaks config"
10
+
11
+ [allowlist]
12
+ description = "Known-safe patterns in this repo"
13
+
14
+ # Sample/fixture files contain placeholder UUIDs and sanitised JSON — not real tokens.
15
+ paths = [
16
+ "samples/",
17
+ "tests/fixtures/",
18
+ "docs/",
19
+ "CHANGELOG.md",
20
+ "README.md",
21
+ ]
22
+
23
+ # Regex patterns that are safe to ignore across the whole repo.
24
+ # Format: list of Go regex strings matched against the secret value.
25
+ regexes = [
26
+ # Placeholder project/asset UUIDs in test fixtures (all-hex, fixed length,
27
+ # committed deliberately as sample data with no auth value).
28
+ "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
29
+ ]
30
+
31
+ # Specific commit SHAs that were already reviewed and cleared.
32
+ # Add a SHA here only after manually verifying no live credentials exist.
33
+ commits = []
@@ -0,0 +1,38 @@
1
+ # Pre-commit hooks for gflow-cli
2
+ # Install: pip install pre-commit && pre-commit install
3
+ # Run manually: pre-commit run --all-files
4
+ #
5
+ # Gates enforced:
6
+ # 1. ruff lint + format (fast, catches import order / style / unused imports)
7
+ # 2. repo-hygiene (blocks tracked images, CDP lock files, hardcoded Windows paths)
8
+ #
9
+ # The hygiene hook is the primary defence against accidental leakage of:
10
+ # - generated output artefacts (*.jpg, *.jpeg, test_assets/smoke_*/, test_assets/debug_*/)
11
+ # - CDP lock files (.gflow-cdp.lock) that contain browser session metadata
12
+ # - hardcoded machine-specific paths in scripts/ (C:\Users\<name>\...)
13
+
14
+ repos:
15
+ - repo: https://github.com/astral-sh/ruff-pre-commit
16
+ rev: v0.11.10
17
+ hooks:
18
+ - id: ruff
19
+ args: [--fix]
20
+ - id: ruff-format
21
+
22
+ - repo: local
23
+ hooks:
24
+ - id: repo-hygiene
25
+ name: Repo hygiene (no artefacts, no hardcoded paths)
26
+ language: python
27
+ entry: python scripts/ci/check_repo_hygiene.py
28
+ pass_filenames: false
29
+ always_run: true
30
+ additional_dependencies: []
31
+
32
+ - repo: https://github.com/Yelp/detect-secrets
33
+ rev: v1.5.0
34
+ hooks:
35
+ - id: detect-secrets
36
+ name: Detect secrets
37
+ args: ["--baseline", ".secrets.baseline"]
38
+ exclude: "\.secrets\.baseline$"
@@ -0,0 +1,152 @@
1
+ {
2
+ "version": "1.5.0",
3
+ "plugins_used": [
4
+ {
5
+ "name": "ArtifactoryDetector"
6
+ },
7
+ {
8
+ "name": "AWSKeyDetector"
9
+ },
10
+ {
11
+ "name": "AzureStorageKeyDetector"
12
+ },
13
+ {
14
+ "name": "Base64HighEntropyString",
15
+ "limit": 4.5
16
+ },
17
+ {
18
+ "name": "BasicAuthDetector"
19
+ },
20
+ {
21
+ "name": "CloudantDetector"
22
+ },
23
+ {
24
+ "name": "DiscordBotTokenDetector"
25
+ },
26
+ {
27
+ "name": "GitHubTokenDetector"
28
+ },
29
+ {
30
+ "name": "GitLabTokenDetector"
31
+ },
32
+ {
33
+ "name": "HexHighEntropyString",
34
+ "limit": 3.0
35
+ },
36
+ {
37
+ "name": "IbmCloudIamDetector"
38
+ },
39
+ {
40
+ "name": "IbmCosHmacDetector"
41
+ },
42
+ {
43
+ "name": "IPPublicDetector"
44
+ },
45
+ {
46
+ "name": "JwtTokenDetector"
47
+ },
48
+ {
49
+ "name": "KeywordDetector",
50
+ "keyword_exclude": ""
51
+ },
52
+ {
53
+ "name": "MailchimpDetector"
54
+ },
55
+ {
56
+ "name": "NpmDetector"
57
+ },
58
+ {
59
+ "name": "OpenAIDetector"
60
+ },
61
+ {
62
+ "name": "PrivateKeyDetector"
63
+ },
64
+ {
65
+ "name": "PypiTokenDetector"
66
+ },
67
+ {
68
+ "name": "SendGridDetector"
69
+ },
70
+ {
71
+ "name": "SlackDetector"
72
+ },
73
+ {
74
+ "name": "SoftlayerDetector"
75
+ },
76
+ {
77
+ "name": "SquareOAuthDetector"
78
+ },
79
+ {
80
+ "name": "StripeDetector"
81
+ },
82
+ {
83
+ "name": "TelegramBotTokenDetector"
84
+ },
85
+ {
86
+ "name": "TwilioKeyDetector"
87
+ }
88
+ ],
89
+ "filters_used": [
90
+ {
91
+ "path": "detect_secrets.filters.allowlist.is_line_allowlisted"
92
+ },
93
+ {
94
+ "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
95
+ "min_level": 2
96
+ },
97
+ {
98
+ "path": "detect_secrets.filters.heuristic.is_indirect_reference"
99
+ },
100
+ {
101
+ "path": "detect_secrets.filters.heuristic.is_likely_id_string"
102
+ },
103
+ {
104
+ "path": "detect_secrets.filters.heuristic.is_lock_file"
105
+ },
106
+ {
107
+ "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
108
+ },
109
+ {
110
+ "path": "detect_secrets.filters.heuristic.is_potential_uuid"
111
+ },
112
+ {
113
+ "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
114
+ },
115
+ {
116
+ "path": "detect_secrets.filters.heuristic.is_sequential_string"
117
+ },
118
+ {
119
+ "path": "detect_secrets.filters.heuristic.is_swagger_file"
120
+ },
121
+ {
122
+ "path": "detect_secrets.filters.heuristic.is_templated_secret"
123
+ },
124
+ {
125
+ "path": "detect_secrets.filters.regex.should_exclude_file",
126
+ "pattern": [
127
+ "\\.venv|tmp|samples/captured"
128
+ ]
129
+ }
130
+ ],
131
+ "results": {
132
+ "tests\\api\\transports\\test_sapisidhash.py": [
133
+ {
134
+ "type": "Hex High Entropy String",
135
+ "filename": "tests\\api\\transports\\test_sapisidhash.py",
136
+ "hashed_secret": "53506367ae14180a65ad639f12ef857370f1ab06",
137
+ "is_verified": false,
138
+ "line_number": 385
139
+ }
140
+ ],
141
+ "tests\\test_observability.py": [
142
+ {
143
+ "type": "Secret Keyword",
144
+ "filename": "tests\\test_observability.py",
145
+ "hashed_secret": "ae08c5886eb2b1feb7c53d7774dc1eef39281da6",
146
+ "is_verified": false,
147
+ "line_number": 69
148
+ }
149
+ ]
150
+ },
151
+ "generated_at": "2026-05-16T17:49:16Z"
152
+ }
@@ -7,6 +7,101 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.6.0a6] — 2026-05-17
11
+
12
+ > **Stability & code-quality release.** Fixes a concurrency bug in image
13
+ > generation, restores a green CI pipeline (the test job had been hanging
14
+ > indefinitely), and clears every open SonarCloud issue so the project's
15
+ > Quality Gate passes.
16
+
17
+ ### Fixed
18
+
19
+ - **Concurrent `generate_images` calls are now serialized**, and every batch
20
+ creates a fresh Flow project — prevents project-reuse races when multiple
21
+ image generations overlap.
22
+ - **CI test job no longer hangs.** `RealChromeStrategy` launches Chrome with
23
+ `asyncio.create_subprocess_exec`, but its tests patched `subprocess.Popen`;
24
+ asyncio's POSIX subprocess transport uses `Popen` internally, so the mock
25
+ left the event loop's child watcher unresolved forever — the test job ran
26
+ until cancelled and never wrote a coverage report. Tests now patch
27
+ `asyncio.create_subprocess_exec` directly.
28
+ - **structlog log-capture test isolation** — a `browser_manager` test asserted
29
+ on a log event that an earlier test had already cached onto the production
30
+ logger chain (`cache_logger_on_first_use=True`). It now patches in a fresh
31
+ logger proxy and passes regardless of suite order.
32
+
33
+ ### Changed
34
+
35
+ - **All open SonarCloud issues resolved** and the Quality Gate now passes:
36
+ the S6418 BLOCKER and 10× S5443 CRITICAL test findings, 16 mechanical
37
+ issues, async-hygiene rules (S7503 / S7487 / S7493), and 5
38
+ cognitive-complexity (S3776) extractions. The two remaining Security
39
+ Hotspots — `random`-based retry jitter and protocol-mandated SHA-1 in
40
+ `sapisidhash` — were reviewed and marked Safe.
41
+
42
+ ### Security / Compliance
43
+
44
+ - **Removed accidentally tracked artefacts** — 7 files were untracked from git:
45
+ `denon82/.gflow-cdp.lock`, `test_assets/debug_editor/buttons.json`,
46
+ `test_assets/debug_settings/settings_panel.json`, and 4 AI-generated JPGs
47
+ in `test_assets/smoke_e2e_*/`. None contained credentials or API tokens, but
48
+ the CDP lock file exposed a profile name and browser PID and the debug JSON
49
+ files contained Flow UI text. Files were removed from HEAD forward (no history
50
+ rewrite — see decision rationale in `PLAN.md` ADR #3).
51
+
52
+ - **`.gitignore` hardened** — added `*.jpg`, `*.jpeg`, `**/.gflow-cdp.lock`,
53
+ `test_assets/smoke_*/`, `test_assets/debug_*/`, and `gflow-output/` to
54
+ prevent recurrence. Fixture allowlist added (`!test_assets/fixtures/**/*.jpg`).
55
+
56
+ - **Hygiene gate added to CI** — `scripts/ci/check_repo_hygiene.py` runs on
57
+ every push and PR before lint. Fails if tracked files match the denylist or
58
+ if any `scripts/**/*.py` contains a hardcoded Windows absolute path or writes
59
+ output to `test_assets/`.
60
+
61
+ - **`.pre-commit-config.yaml` added** — ships ruff (lint + format) and the
62
+ hygiene gate as pre-commit hooks. Install with:
63
+ `pip install pre-commit && pre-commit install`.
64
+
65
+ - **Debug scripts de-hardcoded** — `scripts/debug_editor.py`,
66
+ `scripts/debug_gen_settings.py`, `scripts/debug_settings.py` previously
67
+ contained `PROFILE = r"C:\Users\ffrol\..."` (Windows username + Google
68
+ profile name) and wrote output to `test_assets/`. Replaced with argparse
69
+ `--profile` flag + `auth.profile_dir(args.profile)` and output redirected to
70
+ `tmp/debug/<name>/`.
71
+
72
+ - **CI workflow scrubbed** — removed a hardcoded profile name (`denon82`) from
73
+ a comment in `.github/workflows/ci.yml`.
74
+
75
+ ### CI / Tooling
76
+
77
+ - **GitHub Actions migrated to Node.js 24** ahead of the June 2026 forced
78
+ migration (`FORCE_JAVASCRIPT_ACTIONS_TO_NODE24`).
79
+ - **SonarCloud Quality Gate badge** added to the README.
80
+
81
+ ## [0.6.0a5] — 2026-05-16
82
+
83
+ > **CLI transport proven end-to-end.** The `ui_automation` transport now
84
+ > generates images correctly from the `gflow image t2i` command — count,
85
+ > aspect ratio, and file download all work. Root cause of the persistent 403
86
+ > was `headless=True`; reCAPTCHA Enterprise immediately rejects headless
87
+ > Chromium.
88
+
89
+ ### Fixed
90
+
91
+ - **`headless` default changed `True` → `False`** in `config.py` and
92
+ `FlowApiClient.__init__` — the `ui_automation` transport requires a headed
93
+ (visible) Chrome window; reCAPTCHA Enterprise scores headless browsers as
94
+ bots and returns an immediate 403 on `batchGenerateImages`.
95
+ - **13 unit test mock regressions** fixed after the v0.6.0a4 transport rewrite:
96
+ - `add_init_script = AsyncMock()` added to `_patch_playwright` and
97
+ `fake_context` fixtures (`test_client.py`, `test_concurrency.py`).
98
+ - `keyboard.insert_text = AsyncMock()` added to `_make_prompt_page`
99
+ (transport now uses `insert_text` instead of `type`).
100
+ - `_FakeHttpxResponse.headers` added (download auto-detects `.jpg`/`.png`
101
+ from `Content-Type`).
102
+ - `_capture_batch_response` / `_await_captured` return `list[dict]` —
103
+ test assertions updated throughout `test_ui_automation.py`.
104
+
10
105
  ## [0.6.0a4] — 2026-05-17
11
106
 
12
107
  > **Unified output resolution + batch orchestration refactor.** This release
@@ -538,7 +633,9 @@ shell-script template that branches on these codes.
538
633
 
539
634
  First skeleton. Not functional end-to-end yet.
540
635
 
541
- [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.6.0a1...HEAD
636
+ [Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.6.0a6...HEAD
637
+ [0.6.0a6]: https://github.com/ffroliva/gflow-cli/compare/v0.6.0a5...v0.6.0a6
638
+ [0.6.0a5]: https://github.com/ffroliva/gflow-cli/compare/v0.6.0a4...v0.6.0a5
542
639
  [0.6.0a1]: https://github.com/ffroliva/gflow-cli/compare/v0.5.0a1...v0.6.0a1
543
640
  [0.5.0a1]: https://github.com/ffroliva/gflow-cli/compare/v0.4.0a2...v0.5.0a1
544
641
  [0.3.0a1]: https://github.com/ffroliva/gflow-cli/releases/tag/v0.3.0a1
@@ -67,16 +67,24 @@ Dependency rule: **`domain/` depends on nothing**. `application/` depends on `do
67
67
 
68
68
  ## How to verify your work
69
69
 
70
- Run all four BEFORE asking to commit:
70
+ Run all five BEFORE asking to commit:
71
71
 
72
72
  ```bash
73
+ uv run python scripts/ci/check_repo_hygiene.py # hygiene gate (run first)
73
74
  uv run ruff check src tests # lint
74
75
  uv run ruff format --check src tests # formatting
75
76
  uv run pyright src # types
76
77
  uv run pytest -q --cov=gflow_cli # tests + coverage
77
78
  ```
78
79
 
79
- CI runs the same four on every push (see `.github/workflows/ci.yml`).
80
+ CI runs the same five on every push (see `.github/workflows/ci.yml`).
81
+
82
+ ## Output path rule — MANDATORY
83
+
84
+ **All script and test runtime output goes to `tmp/`.** Never to `test_assets/`
85
+ or the repo root. `test_assets/` is for committed test *fixtures* (static
86
+ input files checked into git). The CI hygiene gate (`check_repo_hygiene.py`)
87
+ actively blocks commits that violate this rule.
80
88
 
81
89
  ## Where to look
82
90
 
@@ -59,24 +59,29 @@ CI runs `unit` + `integration` on every push. `live` tests run only on the maint
59
59
  ## Quality gates (run before commit)
60
60
 
61
61
  ```bash
62
+ uv run python scripts/ci/check_repo_hygiene.py # artefact + path hygiene
62
63
  uv run ruff check src tests # lint
63
64
  uv run ruff format src tests # auto-format
64
65
  uv run pyright src # type-check (strict on src/gflow_cli/)
65
66
  uv run pytest -q --cov=gflow_cli # tests + coverage
66
67
  ```
67
68
 
68
- CI runs all four on every push. Local pre-commit hook recommended:
69
+ CI runs all five on every push. Install local pre-commit hooks (recommended):
69
70
 
70
- ```yaml
71
- # .pre-commit-config.yaml — install with `pip install pre-commit && pre-commit install`
72
- repos:
73
- - repo: https://github.com/astral-sh/ruff-pre-commit
74
- rev: v0.6.9
75
- hooks:
76
- - id: ruff
77
- - id: ruff-format
71
+ ```bash
72
+ pip install pre-commit && pre-commit install
78
73
  ```
79
74
 
75
+ The `.pre-commit-config.yaml` already ships ruff and the hygiene gate.
76
+
77
+ ### Script output convention
78
+
79
+ All runtime output — smoke runs, debug dumps, generated images — **must** go
80
+ to `tmp/` (already gitignored). `test_assets/` is for committed test
81
+ *fixtures* only (static input files for unit tests). Never write to
82
+ `test_assets/smoke_*/` or `test_assets/debug_*/` from scripts; the hygiene
83
+ gate blocks this.
84
+
80
85
  ## Adding a new API route
81
86
 
82
87
  1. **Capture the live request** — add a sanitised JSON sample under `samples/captured/` (numbered, e.g. `08_<route>.json`; scrub project IDs, asset UUIDs, bearer tokens, and reCAPTCHA tokens).
@@ -111,6 +111,20 @@ gflow video batch manifest.remaining.tsv
111
111
 
112
112
  ---
113
113
 
114
+ ### REST API 401 unauthorized on project creation
115
+
116
+ - **Status:** Open (Mitigated) · **Severity:** High · **Affects:** v0.2.0a1+ · **Fixed in:** v0.6.0a5 (planned)
117
+
118
+ Even with a valid browser session (cookies present), calling Flow's REST API directly via `fetch` or `page.request` (e.g., `project.createProject`) may return HTTP 401. This blocks the CLI's standard "pre-flight" sequence for generations.
119
+
120
+ **Root cause:** Google's backend has tightened security on its private trpc/REST endpoints, likely requiring specific headers (`Origin`, `Referer`) or a more complete browser fingerprint that raw script-driven requests lack.
121
+
122
+ **Workaround:** Use the **UI Mimicry** approach (used by the `scripts/smoke_worker_style.py` diagnostic). This strategy performs actions by clicking real buttons in the Flow editor instead of making raw REST calls.
123
+
124
+ **Roadmap:** v0.6.0a5 will refactor the `ui_automation` transport to handle its own project creation via the UI, bypassing the REST-based `create_project` blocker entirely for image generation.
125
+
126
+ ---
127
+
114
128
  ### Output dir is not tidied automatically
115
129
 
116
130
  - **Status:** Open · **Severity:** Low · **By design**
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gflow-cli
3
- Version: 0.6.0a4
3
+ Version: 0.6.0a6
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
@@ -66,6 +66,7 @@ Description-Content-Type: text/markdown
66
66
  [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
67
67
  [![Type checked: pyright](https://img.shields.io/badge/type%20checked-pyright-blue.svg)](https://github.com/microsoft/pyright)
68
68
  [![Tests: TDD](https://img.shields.io/badge/tests-TDD-brightgreen.svg)](#development--tdd-workflow)
69
+ [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=ffroliva_gflow-cli&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=ffroliva_gflow-cli)
69
70
 
70
71
  > ⚠️ **Not affiliated with Google.** Reverse-engineered from public Flow web traffic. Endpoints can change at any time. See full [DISCLAIMER](DISCLAIMER.md) before use.
71
72
 
@@ -108,7 +109,7 @@ Read the full [DISCLAIMER](DISCLAIMER.md) before deploying this in any productio
108
109
 
109
110
  ## Project status
110
111
 
111
- **v0.5.0a1 — alpha.** Video (T2V/I2V/batch), image (T2I/I2I/upload), the new **`gflow run` JSON-batch command**, and the **`ui_automation` default transport** are functional end-to-end against a live Google AI Pro/Ultra Flow account. Three earlier HTTP transport strategies (`evaluate_fetch` / `bearer` / `sapisidhash`) move to an `experimental/` subpackage in this release; the production path is `ui_automation`.
112
+ **v0.6.0a5 — alpha.** Video (T2V/I2V/batch), image (T2I/I2I/upload), the new **`gflow run` JSON-batch command**, and the **`ui_automation` default transport** are functional end-to-end against a live Google AI Pro/Ultra Flow account. Three earlier HTTP transport strategies (`evaluate_fetch` / `bearer` / `sapisidhash`) move to an `experimental/` subpackage in this release; the production path is `ui_automation`.
112
113
 
113
114
  | Milestone | Status |
114
115
  |---|---|
@@ -128,7 +129,7 @@ Read the full [DISCLAIMER](DISCLAIMER.md) before deploying this in any productio
128
129
  | Shell multi-prompt `gflow image t2i` (`PROMPT...`, `--prompts-file`, `--stdin`) | ✅ done (v0.6.0a1) |
129
130
  | Provider abstraction for official Veo 3.1 API | ⏳ planned (v0.6+) |
130
131
 
131
- ### What's new in v0.5.0a1
132
+ ### What's new in v0.6.0a5
132
133
 
133
134
  - `UiAutomationTransport` is now the default image-generation strategy — Playwright-driven UI mimicry against the Flow editor on a logged-in Pro/Ultra profile (no externally-exposed CDP debug port).
134
135
  - New top-level `gflow run --config <file>` command for JSON-described sequential batches (1–50 prompts per file, `--continue-on-error` / `--fail-fast` modes). See [`docs/USAGE.md`](docs/USAGE.md#gflow-run) for the schema.