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.
- gflow_cli-0.6.0a6/.github/CODEOWNERS +22 -0
- gflow_cli-0.6.0a6/.github/dependabot.yml +34 -0
- gflow_cli-0.6.0a6/.github/workflows/ci.yml +96 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/.gitignore +13 -0
- gflow_cli-0.6.0a6/.gitleaks.toml +33 -0
- gflow_cli-0.6.0a6/.pre-commit-config.yaml +38 -0
- gflow_cli-0.6.0a6/.secrets.baseline +152 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/CHANGELOG.md +98 -1
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/CLAUDE.md +10 -2
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/CONTRIBUTING.md +14 -9
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/KNOWN_ISSUES.md +14 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/PKG-INFO +4 -3
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/PLAN.md +175 -1
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/README.md +3 -2
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/ARCHITECTURE.md +4 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/SECURITY.md +37 -1
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/USER_GUIDE.md +161 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/pyproject.toml +2 -1
- gflow_cli-0.6.0a6/scripts/ci/check_repo_hygiene.py +141 -0
- gflow_cli-0.6.0a6/scripts/debug_editor.py +69 -0
- gflow_cli-0.6.0a6/scripts/debug_gen_settings.py +83 -0
- gflow_cli-0.6.0a6/scripts/debug_settings.py +69 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/diag_capture_flow_traffic.py +1 -1
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/smoke_worker_style.py +188 -38
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/verify_chrome_auth_viability.py +9 -9
- gflow_cli-0.6.0a6/sonar-project.properties +35 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/__init__.py +1 -1
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/_retry.py +2 -1
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/client.py +28 -9
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/image.py +4 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/experimental/bearer.py +4 -2
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/experimental/sapisidhash.py +3 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/ui_automation.py +313 -55
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/auth/__init__.py +2 -2
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/auth/internal_chromium.py +0 -4
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/auth/real_chrome.py +11 -10
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/browser_manager.py +93 -111
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/cli_image.py +46 -30
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/config.py +7 -6
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/image_batch.py +0 -1
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/manifest.py +18 -17
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_client.py +4 -2
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_concurrency.py +1 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_evaluate_fetch.py +2 -2
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_ui_automation.py +49 -36
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/auth/strategies/test_strategies.py +24 -7
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/e2e/test_transports_e2e.py +1 -1
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_browser_manager.py +9 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_config.py +6 -5
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_smoke.py +2 -1
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/uv.lock +184 -1
- gflow_cli-0.6.0a4/.github/workflows/ci.yml +0 -42
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/.claude/README.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/.claude/commands/release.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/.env.template +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/.gitattributes +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/.github/workflows/release.yml +0 -0
- {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
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/CONFIGURATION.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/DISCLAIMER.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/LICENSE +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/RELEASE.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/AUTHENTICATION.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/CONFIGURATION.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/INDEX.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/USAGE.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/assets/example-run.gif +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-09-image-mvp-orchestration.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-09-image-mvp.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-09-video-mvp.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-10-phase-4-hardening-orchestration.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-10-phase-4-hardening.md +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN.md +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/PLAN.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/orchestration.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/specs/2026-05-10-phase-4-hardening-design.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/specs/2026-05-14-shell-multi-prompt-design.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/specs/2026-05-15-auth-login-real-chrome-design.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/examples/README.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/examples/batch_from_config.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/examples/multi_prompt_t2i.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/examples/sample_config.json +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/examples/sample_prompts.txt +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/examples/single_image_t2i.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/README.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/01_upload_image.json +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/04_archive_workflow.json +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/05_createProject.json +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/06_batchGenerateImages.json +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/diag_recaptcha_mint.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/record_demo.ps1 +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/smoke_e2e.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/smoke_image.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/scripts/smoke_real_chrome_image.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/skills/README.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/skills/gflow-cli/SKILL.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/__main__.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/_cli_helpers.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/__init__.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/dto.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/recaptcha.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/routes.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/__init__.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/_common.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/_fingerprint.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/base.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/experimental/__init__.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/api/video.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/auth/base.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/auth/factory.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/auth/strategies.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/cli.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/cli_run.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/cli_video.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/errors.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/observability.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/paths.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/src/gflow_cli/profile_store.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tasks/lessons.md +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/__init__.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/__init__.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_client_generate_video.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_client_image.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_dto.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_image.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_image_dto.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_recaptcha.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_retry.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_routes.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/test_video.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/__init__.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_base.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_bearer.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_common.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_factory.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_fingerprint.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/api/transports/test_sapisidhash.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/auth/strategies/test_factory.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/cli/__init__.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/cli/test_cli_image.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/cli/test_cli_run.py +1 -1
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/cli/test_error_handling.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/cli/test_helpers.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/cli/test_t2i_multi_prompt.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/conftest.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/e2e/__init__.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/__init__.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/auth.feature +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/auth_login.feature +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/conftest.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/image.feature +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/test_auth_login_steps.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/test_auth_steps.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/test_image_steps.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/test_step_collision_guard.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/test_video_steps.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/features/video.feature +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/smoke/__init__.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/smoke/test_real_flow.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_auth.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_cli_video.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_errors.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_manifest.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_observability.py +0 -0
- {gflow_cli-0.6.0a4 → gflow_cli-0.6.0a6}/tests/test_paths.py +0 -0
- {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.
|
|
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
|
|
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
|
|
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
|
|
69
|
+
CI runs all five on every push. Install local pre-commit hooks (recommended):
|
|
69
70
|
|
|
70
|
-
```
|
|
71
|
-
|
|
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.
|
|
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
|
[](https://github.com/astral-sh/ruff)
|
|
67
67
|
[](https://github.com/microsoft/pyright)
|
|
68
68
|
[](#development--tdd-workflow)
|
|
69
|
+
[](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.
|
|
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.
|
|
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.
|