gflow-cli 0.6.0a6__tar.gz → 0.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/.claude/README.md +8 -3
- gflow_cli-0.7.0/.claude/commands/gflow/changelog.md +21 -0
- gflow_cli-0.7.0/.claude/commands/gflow/check.md +48 -0
- gflow_cli-0.7.0/.claude/commands/gflow/known-issues.md +20 -0
- gflow_cli-0.7.0/.claude/commands/gflow/plan.md +39 -0
- gflow_cli-0.7.0/.claude/commands/gflow/release.md +118 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/.github/CODEOWNERS +1 -0
- gflow_cli-0.7.0/.github/PULL_REQUEST_TEMPLATE.md +20 -0
- gflow_cli-0.7.0/.github/copilot-instructions.md +24 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/.github/workflows/ci.yml +16 -8
- gflow_cli-0.7.0/.github/workflows/external-pr-triage.yml +126 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/.github/workflows/release.yml +18 -3
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/CHANGELOG.md +54 -1
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/CLAUDE.md +22 -18
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/CONTRIBUTING.md +33 -5
- gflow_cli-0.7.0/KNOWN_ISSUES.md +326 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/PKG-INFO +24 -44
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/PLAN.md +40 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/README.md +23 -43
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/RELEASE.md +2 -2
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/ARCHITECTURE.md +1 -0
- gflow_cli-0.7.0/docs/DEBUGGING.md +183 -0
- gflow_cli-0.7.0/docs/DEVELOPMENT.md +125 -0
- gflow_cli-0.7.0/docs/GITHUB.md +139 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/INDEX.md +29 -0
- gflow_cli-0.7.0/docs/LIVE_VERIFICATION_v0.7.0.md +110 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/USAGE.md +64 -10
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/USER_GUIDE.md +87 -0
- gflow_cli-0.7.0/docs/superpowers/2026-05-17-issue-15-handover.md +59 -0
- gflow_cli-0.7.0/docs/superpowers/plans/2026-05-17-e2e-test-coverage.md +463 -0
- gflow_cli-0.7.0/docs/superpowers/plans/2026-05-17-issue-15-auth-verification-fix.md +1449 -0
- gflow_cli-0.7.0/docs/superpowers/plans/2026-05-17-issue-15-i2v-bearer-auth.md +811 -0
- gflow_cli-0.7.0/docs/superpowers/plans/2026-05-17-issue-15-orchestration.md +118 -0
- gflow_cli-0.7.0/docs/superpowers/plans/2026-05-18-video-phase0-submit-spike.md +697 -0
- gflow_cli-0.7.0/docs/superpowers/plans/2026-05-19-video-phase-a-execution-state.md +64 -0
- gflow_cli-0.7.0/docs/superpowers/plans/2026-05-19-video-phase-a-orchestration.md +164 -0
- gflow_cli-0.7.0/docs/superpowers/plans/2026-05-19-video-phase-a-t2v.md +2083 -0
- gflow_cli-0.7.0/docs/superpowers/specs/2026-05-17-e2e-test-coverage-design.md +190 -0
- gflow_cli-0.7.0/docs/superpowers/specs/2026-05-17-i2v-uploadimage-401-bearer-auth-design.md +330 -0
- gflow_cli-0.7.0/docs/superpowers/specs/2026-05-17-issue-15-auth-verification-fix-design.md +485 -0
- gflow_cli-0.7.0/docs/superpowers/specs/2026-05-17-issue-15-root-cause-findings.md +87 -0
- gflow_cli-0.7.0/docs/superpowers/specs/2026-05-18-ui-automation-video-generation-design.md +739 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/pyproject.toml +1 -1
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/samples/captured/02_batchAsyncGenerateVideoText.json +3 -3
- gflow_cli-0.7.0/samples/captured/08_batchAsyncGenerateVideoStartAndEndImage.json +144 -0
- gflow_cli-0.7.0/samples/captured/09_batchAsyncGenerateVideoReferenceImages.json +136 -0
- gflow_cli-0.7.0/samples/captured/10_batchCheckAsyncVideoGenerationStatus_successful.json +90 -0
- gflow_cli-0.7.0/samples/captured/11_batchCheckAsyncVideoGenerationStatus_failed.json +97 -0
- gflow_cli-0.7.0/scripts/dev/active_plan.py +188 -0
- gflow_cli-0.7.0/scripts/smoke_video_editor.py +874 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/__init__.py +1 -1
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/__init__.py +1 -3
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/client.py +151 -111
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/dto.py +0 -67
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/recaptcha.py +1 -1
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/transports/base.py +2 -2
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/transports/experimental/bearer.py +3 -1
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +7 -1
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/transports/experimental/sapisidhash.py +3 -1
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/transports/ui_automation.py +200 -19
- gflow_cli-0.7.0/src/gflow_cli/api/transports/ui_automation_video.py +498 -0
- gflow_cli-0.7.0/src/gflow_cli/api/video.py +156 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/auth/internal_chromium.py +56 -23
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/auth/real_chrome.py +61 -34
- gflow_cli-0.7.0/src/gflow_cli/auth/verification.py +228 -0
- gflow_cli-0.7.0/src/gflow_cli/cli_video.py +95 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/errors.py +58 -4
- gflow_cli-0.7.0/src/gflow_cli/exceptions.py +25 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tasks/lessons.md +34 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/test_client.py +86 -2
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/test_client_image.py +116 -65
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/test_dto.py +1 -38
- gflow_cli-0.7.0/tests/api/test_video.py +213 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/transports/test_ui_automation.py +242 -4
- gflow_cli-0.7.0/tests/api/transports/test_ui_automation_video.py +392 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/auth/strategies/test_strategies.py +127 -50
- gflow_cli-0.7.0/tests/auth/test_verification.py +301 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/cli/test_error_handling.py +17 -1
- gflow_cli-0.7.0/tests/e2e/conftest.py +67 -0
- gflow_cli-0.7.0/tests/e2e/test_auth_verification_e2e.py +65 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/e2e/test_transports_e2e.py +72 -0
- gflow_cli-0.7.0/tests/e2e/test_video_t2v_e2e.py +139 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/features/conftest.py +0 -2
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/features/test_step_collision_guard.py +2 -4
- gflow_cli-0.7.0/tests/test_cli_video.py +44 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/test_errors.py +28 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/uv.lock +1 -1
- gflow_cli-0.6.0a6/.claude/commands/release.md +0 -97
- gflow_cli-0.6.0a6/KNOWN_ISSUES.md +0 -198
- gflow_cli-0.6.0a6/scripts/smoke_e2e.py +0 -78
- gflow_cli-0.6.0a6/src/gflow_cli/api/video.py +0 -112
- gflow_cli-0.6.0a6/src/gflow_cli/cli_video.py +0 -341
- gflow_cli-0.6.0a6/tests/api/test_client_generate_video.py +0 -93
- gflow_cli-0.6.0a6/tests/api/test_video.py +0 -83
- gflow_cli-0.6.0a6/tests/features/test_video_steps.py +0 -253
- gflow_cli-0.6.0a6/tests/features/video.feature +0 -27
- gflow_cli-0.6.0a6/tests/test_cli_video.py +0 -220
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/.env.template +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/.gitattributes +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/.github/dependabot.yml +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/.gitignore +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/.gitleaks.toml +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/.planning/todos/pending/2026-05-11-add-project-logo-and-docs-site-promotion-plan.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/.pre-commit-config.yaml +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/.secrets.baseline +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/CONFIGURATION.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/DISCLAIMER.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/LICENSE +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/AUTHENTICATION.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/CONFIGURATION.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/SECURITY.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/assets/example-run.gif +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-09-image-mvp-orchestration.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-09-image-mvp.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-09-video-mvp.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-10-phase-4-hardening-orchestration.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-10-phase-4-hardening.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/2026-05-14-shell-multi-prompt-orchestration.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_ARCH.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_SEC_UX.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_CODE.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_GEMINI.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_SECURITY.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_PYTHON.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_SECURITY.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_CODE.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_FOLLOWUP.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_PLANNER.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY_FOLLOWUP.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_FINAL_SEC_UX_VERIFIED.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_PLAN_SECURITY.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_SPEC_SECURITY.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/PLAN.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/orchestration.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/specs/2026-05-10-phase-4-hardening-design.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/specs/2026-05-14-shell-multi-prompt-design.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/specs/2026-05-15-auth-login-real-chrome-design.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/examples/README.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/examples/batch_from_config.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/examples/multi_prompt_t2i.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/examples/sample_config.json +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/examples/sample_prompts.txt +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/examples/single_image_t2i.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/samples/README.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/samples/captured/01_upload_image.json +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/samples/captured/04_archive_workflow.json +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/samples/captured/05_createProject.json +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/samples/captured/06_batchGenerateImages.json +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/scripts/ci/check_repo_hygiene.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/scripts/debug_editor.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/scripts/debug_gen_settings.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/scripts/debug_settings.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/scripts/diag_capture_flow_traffic.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/scripts/diag_recaptcha_mint.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/scripts/record_demo.ps1 +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/scripts/smoke_image.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/scripts/smoke_real_chrome_image.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/scripts/smoke_worker_style.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/scripts/verify_chrome_auth_viability.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/skills/README.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/skills/gflow-cli/SKILL.md +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/sonar-project.properties +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/__main__.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/_cli_helpers.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/_retry.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/image.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/routes.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/transports/__init__.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/transports/_common.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/transports/_fingerprint.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/api/transports/experimental/__init__.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/auth/__init__.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/auth/base.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/auth/factory.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/auth/strategies.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/browser_manager.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/cli.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/cli_image.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/cli_run.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/config.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/image_batch.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/manifest.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/observability.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/paths.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/src/gflow_cli/profile_store.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/__init__.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/__init__.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/test_concurrency.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/test_image.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/test_image_dto.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/test_recaptcha.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/test_retry.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/test_routes.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/transports/__init__.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/transports/test_base.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/transports/test_bearer.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/transports/test_common.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/transports/test_evaluate_fetch.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/transports/test_factory.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/transports/test_fingerprint.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/api/transports/test_sapisidhash.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/auth/strategies/test_factory.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/cli/__init__.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/cli/test_cli_image.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/cli/test_cli_run.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/cli/test_helpers.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/cli/test_t2i_multi_prompt.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/conftest.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/e2e/__init__.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/features/__init__.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/features/auth.feature +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/features/auth_login.feature +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/features/image.feature +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/features/test_auth_login_steps.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/features/test_auth_steps.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/features/test_image_steps.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/smoke/__init__.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/smoke/test_real_flow.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/test_auth.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/test_browser_manager.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/test_config.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/test_manifest.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/test_observability.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/test_paths.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/test_profile_store.py +0 -0
- {gflow_cli-0.6.0a6 → gflow_cli-0.7.0}/tests/test_smoke.py +0 -0
|
@@ -10,7 +10,12 @@ This directory holds **internal maintainer workflows** that are bundled with the
|
|
|
10
10
|
.claude/
|
|
11
11
|
├── README.md ← this file
|
|
12
12
|
└── commands/ ← repo-local slash commands
|
|
13
|
-
└──
|
|
13
|
+
└── gflow/ ← `/gflow:*` namespace (avoids collision with built-ins)
|
|
14
|
+
├── check.md ← `/gflow:check` — hygiene + ruff + pyright + pytest
|
|
15
|
+
├── plan.md ← `/gflow:plan` — show active phase / superpowers plan
|
|
16
|
+
├── known-issues.md← `/gflow:known-issues` — open/mitigated items
|
|
17
|
+
├── changelog.md ← `/gflow:changelog` — [Unreleased] + last tagged
|
|
18
|
+
└── release.md ← `/gflow:release` — full release flow (signed tags)
|
|
14
19
|
```
|
|
15
20
|
|
|
16
21
|
Optional additions when needed:
|
|
@@ -25,9 +30,9 @@ Optional additions when needed:
|
|
|
25
30
|
|
|
26
31
|
## Adding a slash command
|
|
27
32
|
|
|
28
|
-
Drop a Markdown file into `commands
|
|
33
|
+
Drop a Markdown file into `commands/gflow/` to add a `/gflow:<name>` command. Filename (without `.md`) becomes the command name. The first paragraph is the description Claude shows in `/help`. The rest is the prompt the agent executes. **Use the `gflow/` subdirectory** so commands stay namespaced and don't collide with Claude Code built-ins or user-global commands.
|
|
29
34
|
|
|
30
|
-
Example: `commands/foo.md` → invoked as `/foo`.
|
|
35
|
+
Example: `commands/gflow/foo.md` → invoked as `/gflow:foo`.
|
|
31
36
|
|
|
32
37
|
## Adding an internal skill
|
|
33
38
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Show unreleased changes and last tagged version — insight into recent work.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# `/gflow:changelog` — Recent changes
|
|
6
|
+
|
|
7
|
+
Read CHANGELOG.md and surface what's queued and what recently shipped.
|
|
8
|
+
|
|
9
|
+
## Steps
|
|
10
|
+
|
|
11
|
+
1. Read [CHANGELOG.md](../../../CHANGELOG.md)
|
|
12
|
+
2. Return:
|
|
13
|
+
- All entries under `## [Unreleased]` (empty = nothing queued yet)
|
|
14
|
+
- The most recent versioned section (last tagged release) for comparison
|
|
15
|
+
3. One-line summary: "X features, Y fixes queued since vZ."
|
|
16
|
+
|
|
17
|
+
## When to call
|
|
18
|
+
|
|
19
|
+
- Before cutting a release (called automatically by `/gflow:release` as its first step)
|
|
20
|
+
- When you need a quick picture of recent work without opening the file
|
|
21
|
+
- When writing a commit message and unsure if a change is user-visible enough to log
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Auto-fix lint and formatting, then report types and tests. Run before every commit.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# `/gflow:check` — Quality gates
|
|
6
|
+
|
|
7
|
+
Run in order. Stop and report if a step fails after the fix pass.
|
|
8
|
+
|
|
9
|
+
## Steps
|
|
10
|
+
|
|
11
|
+
**1. Repo hygiene** (read-only — checks tmp/ output rule, secret files, etc.)
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
PYTHONUTF8=1 uv run python scripts/ci/check_repo_hygiene.py
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**2. Auto-fix lint and formatting** (rewrites files in place)
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
uv run ruff check --fix src tests
|
|
21
|
+
uv run ruff format src tests
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Report which files were modified. Do NOT stage or commit — leave the diff for review.
|
|
25
|
+
|
|
26
|
+
**3. Type check** (report only — cannot auto-fix)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
uv run pyright src
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**4. Tests + coverage** (report only)
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
uv run pytest -q --cov=gflow_cli --cov-fail-under=80
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Output
|
|
39
|
+
|
|
40
|
+
- List files changed by the fix pass (empty = nothing needed fixing)
|
|
41
|
+
- All pyright errors with `file:line` references
|
|
42
|
+
- Pytest summary line and coverage percentage
|
|
43
|
+
- Final verdict: all gates pass / which gates failed
|
|
44
|
+
|
|
45
|
+
## Notes
|
|
46
|
+
|
|
47
|
+
Ruff fix and format may rewrite multiple files. Always `git diff` before staging.
|
|
48
|
+
Pyright errors and test failures require manual intervention — do not attempt silent workarounds.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Surface open known issues. Call before touching auth, reCAPTCHA, or anything previously flagged.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# `/gflow:known-issues` — Open issues
|
|
6
|
+
|
|
7
|
+
Read KNOWN_ISSUES.md and return items that are still open or mitigated (not resolved).
|
|
8
|
+
|
|
9
|
+
## Steps
|
|
10
|
+
|
|
11
|
+
1. Read [KNOWN_ISSUES.md](../../../KNOWN_ISSUES.md)
|
|
12
|
+
2. Return only items with status **open** or **mitigated**
|
|
13
|
+
3. Flag any that are relevant to the current task context
|
|
14
|
+
|
|
15
|
+
## When to call
|
|
16
|
+
|
|
17
|
+
- Before touching `src/gflow_cli/auth.py`
|
|
18
|
+
- Before touching `src/gflow_cli/api/recaptcha.py`
|
|
19
|
+
- Before any work the user flags as "this felt flaky before"
|
|
20
|
+
- When a test or behaviour feels unexpectedly broken
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Show the active plan — next task if a superpowers plan is running, current phase otherwise.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# `/gflow:plan` — Active plan
|
|
6
|
+
|
|
7
|
+
## Steps
|
|
8
|
+
|
|
9
|
+
**1. Check conversation context.**
|
|
10
|
+
|
|
11
|
+
Has the user mentioned a specific feature or invoked the write-plan skill in this session?
|
|
12
|
+
If yes, note the feature name (e.g. `shell-multi-prompt`, `image-mvp`, `phase-4-hardening`).
|
|
13
|
+
|
|
14
|
+
**2. Run the discovery script.**
|
|
15
|
+
|
|
16
|
+
With a feature name identified in step 1:
|
|
17
|
+
```bash
|
|
18
|
+
uv run python scripts/dev/active_plan.py --feature <feature-name>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Without a feature name (uses most-recent superpowers plan, falls back to PLAN.md):
|
|
22
|
+
```bash
|
|
23
|
+
uv run python scripts/dev/active_plan.py
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**3. Return the output verbatim.**
|
|
27
|
+
|
|
28
|
+
The script already filters to the relevant block. Do not read additional files.
|
|
29
|
+
|
|
30
|
+
## What the script returns
|
|
31
|
+
|
|
32
|
+
- **Superpowers plan active:** file path, title, goal, progress (X/N steps), and the next unchecked task block
|
|
33
|
+
- **No superpowers plan:** the first incomplete phase from `PLAN.md` (scope, sequence, definition of done)
|
|
34
|
+
|
|
35
|
+
## When to call
|
|
36
|
+
|
|
37
|
+
- When starting a task and unsure what's in scope
|
|
38
|
+
- When the user asks "what are we working on?" or "what's next?"
|
|
39
|
+
- Before adding a feature, to check it belongs to the current scope
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Cut a new gflow-cli release — bump version, update CHANGELOG, tag, push.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# `/gflow:release` — Cut a new release
|
|
6
|
+
|
|
7
|
+
Follow this sequence verbatim. Every step matters.
|
|
8
|
+
|
|
9
|
+
## Inputs
|
|
10
|
+
|
|
11
|
+
Ask the user (if not already provided):
|
|
12
|
+
1. **Version** — the new version (e.g. `0.4.0`, `0.4.0a3`, `1.0.0rc1`). Use PEP 440 prerelease suffixes (`aN`, `bN`, `rcN`). If they don't know, run `/gflow:changelog` first and propose the next bump (PATCH for fixes only, MINOR for new features, MAJOR for breaks).
|
|
13
|
+
2. **Pre-release?** — prerelease versions should stay marked as GitHub prereleases. Only the user can say when a release line is ready for the stable tag.
|
|
14
|
+
|
|
15
|
+
## Sequence
|
|
16
|
+
|
|
17
|
+
**1. Review what's queued.**
|
|
18
|
+
|
|
19
|
+
Run `/gflow:changelog` — confirm the `[Unreleased]` block is non-empty and accurate before proceeding.
|
|
20
|
+
|
|
21
|
+
**2. Verify clean working tree.**
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
git status --short
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Must be empty. If not, abort and tell the user to commit or stash first.
|
|
28
|
+
|
|
29
|
+
**3. Verify on `main`, up-to-date with `origin/main`.**
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
git rev-parse --abbrev-ref HEAD # must be "main"
|
|
33
|
+
git fetch origin
|
|
34
|
+
git rev-list HEAD..origin/main # must be empty
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**4. Run quality gates.**
|
|
38
|
+
|
|
39
|
+
Run `/gflow:check` — all gates must pass. Abort if any fail.
|
|
40
|
+
|
|
41
|
+
**5. Bump version** in `pyproject.toml`:
|
|
42
|
+
|
|
43
|
+
```toml
|
|
44
|
+
[project]
|
|
45
|
+
version = "<NEW_VERSION>"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**6. Bump package version** in `src/gflow_cli/__init__.py`:
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
__version__ = "<NEW_VERSION>"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**7. Update version assertion tests** if present:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
rg -n "__version__|<OLD_VERSION>|version assertion" tests src pyproject.toml
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**8. Migrate CHANGELOG.**
|
|
61
|
+
|
|
62
|
+
- Move all entries under `## [Unreleased]` to a new `## [<NEW_VERSION>] — YYYY-MM-DD` section.
|
|
63
|
+
- Leave `## [Unreleased]` empty.
|
|
64
|
+
- Update the link footer:
|
|
65
|
+
```
|
|
66
|
+
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v<NEW_VERSION>...HEAD
|
|
67
|
+
[<NEW_VERSION>]: https://github.com/ffroliva/gflow-cli/releases/tag/v<NEW_VERSION>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**9. Review commands for staleness.**
|
|
71
|
+
|
|
72
|
+
Scan `.claude/commands/gflow/` — check if any command references a phase, file path, or behaviour that the release changes. Update in the same commit if so.
|
|
73
|
+
|
|
74
|
+
**10. Commit the release prep.**
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
git add pyproject.toml src/gflow_cli/__init__.py CHANGELOG.md tests
|
|
78
|
+
git commit -m "chore(release): v<NEW_VERSION>"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**11. Tag.** Use `-s` for a signed annotated tag so GitHub shows the **"Verified"** badge AND `.github/workflows/release.yml` passes the signed-tag gate (lightweight or unsigned tags are rejected).
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
git tag -s v<NEW_VERSION> -m "v<NEW_VERSION>"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Requires a GPG or SSH signing key registered in your GitHub account settings.
|
|
88
|
+
Run `git config --global user.signingkey` to confirm a key is set.
|
|
89
|
+
If signing is not available in the current environment, create the tag on
|
|
90
|
+
your local machine and push it: `git push origin v<NEW_VERSION>`.
|
|
91
|
+
|
|
92
|
+
**12. Push commit + tag.**
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
git push origin main
|
|
96
|
+
git push origin v<NEW_VERSION>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**13. Report.**
|
|
100
|
+
|
|
101
|
+
Tell the user:
|
|
102
|
+
- The pushed tag triggers `.github/workflows/release.yml`.
|
|
103
|
+
- Watch <https://github.com/ffroliva/gflow-cli/actions> for the release workflow.
|
|
104
|
+
- On success: PyPI publish + GitHub Release with auto-generated notes.
|
|
105
|
+
- On failure (most common: PyPI Trusted Publishing not yet configured): point to <https://pypi.org/manage/account/publishing/>.
|
|
106
|
+
|
|
107
|
+
## Critical reminders
|
|
108
|
+
|
|
109
|
+
- **NEVER** add `Co-Authored-By: Claude` (or any AI co-author) to the release commit.
|
|
110
|
+
- **NEVER** force-push a release tag once it's on GitHub. Ship a PATCH fix instead.
|
|
111
|
+
- **NEVER** `--no-verify` past hooks. Fix the underlying issue.
|
|
112
|
+
- If quality gates fail at step 4, **STOP**. Surface the failures to the user.
|
|
113
|
+
|
|
114
|
+
## See also
|
|
115
|
+
|
|
116
|
+
- [RELEASE.md](../../../RELEASE.md) — full release protocol, prerelease policy, and checklist
|
|
117
|
+
- [README § Releases](../../../README.md#releases) — release policy and cadence
|
|
118
|
+
- [PLAN § Phase 5](../../../PLAN.md#phase-5--public-alpha-release-on-pypi) — first-release exit criteria
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What changed and why? Link issues with "Fixes #123" when applicable. -->
|
|
4
|
+
|
|
5
|
+
## Validation
|
|
6
|
+
|
|
7
|
+
<!-- List the focused commands you ran, plus any checks you could not run. -->
|
|
8
|
+
|
|
9
|
+
- [ ] Focused tests added or updated for behavior changes
|
|
10
|
+
- [ ] `uv run ruff check src tests`
|
|
11
|
+
- [ ] `uv run pyright src`
|
|
12
|
+
- [ ] Relevant pytest command:
|
|
13
|
+
|
|
14
|
+
## Contribution Checklist
|
|
15
|
+
|
|
16
|
+
- [ ] This PR targets `develop`, unless it is a release or emergency fix
|
|
17
|
+
- [ ] My commits use my real Git identity or GitHub noreply email
|
|
18
|
+
- [ ] External contribution commits include `Signed-off-by:` (`git commit -s`)
|
|
19
|
+
- [ ] I did not include secrets, cookies, account tokens, signed URLs, or private captured data
|
|
20
|
+
- [ ] I reviewed any AI-assisted changes before submitting
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Copilot Code Review Instructions
|
|
2
|
+
|
|
3
|
+
Review this repository as a Python CLI that automates browser-authenticated
|
|
4
|
+
Google Flow workflows. Treat auth, browser automation, CI, release, and secret
|
|
5
|
+
handling changes as high-risk even when the diff is small.
|
|
6
|
+
|
|
7
|
+
For pull request reviews:
|
|
8
|
+
|
|
9
|
+
- Check that PRs target `develop`, unless they are release PRs.
|
|
10
|
+
- Flag unclear contributor provenance, missing DCO sign-off, placeholder author
|
|
11
|
+
emails, and any copied private data.
|
|
12
|
+
- Look for leaked tokens, cookies, signed URLs, local profile paths, and captured
|
|
13
|
+
Google/Flow request data.
|
|
14
|
+
- For auth/browser changes, check that the implementation preserves profile
|
|
15
|
+
isolation, does not weaken local path boundaries, and avoids remote debugging
|
|
16
|
+
unless explicitly documented.
|
|
17
|
+
- For CI changes, check forked-PR secret behavior and avoid recommending
|
|
18
|
+
`pull_request_target` for jobs that checkout or execute contributor code.
|
|
19
|
+
- For behavior changes, expect focused tests and docs/changelog updates.
|
|
20
|
+
- Keep findings concrete: reference files/lines, explain the user-visible risk,
|
|
21
|
+
and separate blocking issues from cosmetic suggestions.
|
|
22
|
+
|
|
23
|
+
Do not approve pull requests. Copilot review is advisory; maintainer approval is
|
|
24
|
+
still required.
|
|
@@ -2,7 +2,7 @@ name: CI
|
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
|
-
branches: [main]
|
|
5
|
+
branches: [develop, main]
|
|
6
6
|
pull_request:
|
|
7
7
|
|
|
8
8
|
env:
|
|
@@ -14,7 +14,7 @@ jobs:
|
|
|
14
14
|
name: Secret scan (gitleaks)
|
|
15
15
|
runs-on: ubuntu-latest
|
|
16
16
|
steps:
|
|
17
|
-
- uses: actions/checkout@
|
|
17
|
+
- uses: actions/checkout@v6
|
|
18
18
|
with:
|
|
19
19
|
fetch-depth: 0 # full history so gitleaks can diff against base
|
|
20
20
|
|
|
@@ -30,10 +30,10 @@ jobs:
|
|
|
30
30
|
matrix:
|
|
31
31
|
python-version: ["3.11", "3.12", "3.13"]
|
|
32
32
|
steps:
|
|
33
|
-
- uses: actions/checkout@
|
|
33
|
+
- uses: actions/checkout@v6
|
|
34
34
|
|
|
35
35
|
- name: Install uv
|
|
36
|
-
uses: astral-sh/setup-uv@
|
|
36
|
+
uses: astral-sh/setup-uv@v7
|
|
37
37
|
|
|
38
38
|
- name: Set up Python
|
|
39
39
|
run: uv python install ${{ matrix.python-version }}
|
|
@@ -66,7 +66,7 @@ jobs:
|
|
|
66
66
|
# Upload coverage XML so the sonar job can consume it
|
|
67
67
|
- name: Upload coverage report
|
|
68
68
|
if: matrix.python-version == '3.11'
|
|
69
|
-
uses: actions/upload-artifact@
|
|
69
|
+
uses: actions/upload-artifact@v7
|
|
70
70
|
with:
|
|
71
71
|
name: coverage-xml
|
|
72
72
|
path: coverage.xml
|
|
@@ -77,14 +77,22 @@ jobs:
|
|
|
77
77
|
name: SonarCloud analysis
|
|
78
78
|
runs-on: ubuntu-latest
|
|
79
79
|
needs: test # wait for tests + coverage report
|
|
80
|
-
|
|
80
|
+
# Forked pull_request runs do not receive repository secrets, so SONAR_TOKEN
|
|
81
|
+
# is empty there and the scanner fails before analysis. Keep SonarCloud on
|
|
82
|
+
# trusted pushes/internal PRs where the token is available.
|
|
83
|
+
if: >
|
|
84
|
+
always() &&
|
|
85
|
+
(
|
|
86
|
+
github.event_name != 'pull_request' ||
|
|
87
|
+
github.event.pull_request.head.repo.full_name == github.repository
|
|
88
|
+
)
|
|
81
89
|
steps:
|
|
82
|
-
- uses: actions/checkout@
|
|
90
|
+
- uses: actions/checkout@v6
|
|
83
91
|
with:
|
|
84
92
|
fetch-depth: 0 # shallow clones break blame / new-code detection
|
|
85
93
|
|
|
86
94
|
- name: Download coverage report
|
|
87
|
-
uses: actions/download-artifact@
|
|
95
|
+
uses: actions/download-artifact@v8
|
|
88
96
|
with:
|
|
89
97
|
name: coverage-xml
|
|
90
98
|
continue-on-error: true # graceful if coverage upload was skipped
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
name: External PR Triage
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request_target:
|
|
5
|
+
types: [opened, reopened, synchronize, ready_for_review, edited]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
issues: write
|
|
10
|
+
pull-requests: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
triage:
|
|
14
|
+
name: Label and route external PRs
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- name: Triage external pull request
|
|
18
|
+
uses: actions/github-script@v7
|
|
19
|
+
with:
|
|
20
|
+
script: |
|
|
21
|
+
const pr = context.payload.pull_request;
|
|
22
|
+
if (!pr) {
|
|
23
|
+
core.info("No pull request payload; nothing to do.");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const owner = context.repo.owner;
|
|
28
|
+
const repo = context.repo.repo;
|
|
29
|
+
const issue_number = pr.number;
|
|
30
|
+
const isBot = pr.user?.type === "Bot";
|
|
31
|
+
const trustedAssociations = new Set(["OWNER", "MEMBER", "COLLABORATOR"]);
|
|
32
|
+
const isFork = pr.head.repo.full_name !== pr.base.repo.full_name;
|
|
33
|
+
const isExternal = isFork || !trustedAssociations.has(pr.author_association);
|
|
34
|
+
|
|
35
|
+
if (isBot) {
|
|
36
|
+
core.info("Bot PR; skipping human external-contribution triage.");
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!isExternal) {
|
|
41
|
+
core.info("PR is not external; skipping external triage.");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const labels = [
|
|
46
|
+
{
|
|
47
|
+
name: "external-contribution",
|
|
48
|
+
color: "0e8a16",
|
|
49
|
+
description: "Pull request from a non-maintainer or fork",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "needs-maintainer-review",
|
|
53
|
+
color: "fbca04",
|
|
54
|
+
description: "Requires maintainer review before merge",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: "needs-copilot-review",
|
|
58
|
+
color: "5319e7",
|
|
59
|
+
description: "Ask GitHub Copilot for advisory code review",
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
for (const label of labels) {
|
|
64
|
+
try {
|
|
65
|
+
await github.rest.issues.createLabel({ owner, repo, ...label });
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (error.status !== 422) {
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
await github.rest.issues.addLabels({
|
|
74
|
+
owner,
|
|
75
|
+
repo,
|
|
76
|
+
issue_number,
|
|
77
|
+
labels: labels.map((label) => label.name),
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
await github.rest.pulls.requestReviewers({
|
|
82
|
+
owner,
|
|
83
|
+
repo,
|
|
84
|
+
pull_number: issue_number,
|
|
85
|
+
reviewers: ["ffroliva"],
|
|
86
|
+
});
|
|
87
|
+
} catch (error) {
|
|
88
|
+
core.warning(`Could not request maintainer review: ${error.message}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const marker = "<!-- gflow-cli-external-pr-triage -->";
|
|
92
|
+
const body = `${marker}
|
|
93
|
+
Thanks for the contribution. This PR has been marked as an external contribution and routed for maintainer review.
|
|
94
|
+
|
|
95
|
+
Before merge, please make sure:
|
|
96
|
+
|
|
97
|
+
- The PR targets \`develop\`.
|
|
98
|
+
- Commits use a real Git identity or GitHub noreply email.
|
|
99
|
+
- External commits include a DCO sign-off: \`git commit -s\`.
|
|
100
|
+
- The PR does not include secrets, cookies, account tokens, signed URLs, or private captured data.
|
|
101
|
+
- Focused tests/docs are included for behavior changes.
|
|
102
|
+
|
|
103
|
+
GitHub Copilot code review may be requested as an advisory first pass, but maintainer approval is still required.`;
|
|
104
|
+
|
|
105
|
+
const comments = await github.paginate(github.rest.issues.listComments, {
|
|
106
|
+
owner,
|
|
107
|
+
repo,
|
|
108
|
+
issue_number,
|
|
109
|
+
per_page: 100,
|
|
110
|
+
});
|
|
111
|
+
const existing = comments.find((comment) => comment.body?.includes(marker));
|
|
112
|
+
if (existing) {
|
|
113
|
+
await github.rest.issues.updateComment({
|
|
114
|
+
owner,
|
|
115
|
+
repo,
|
|
116
|
+
comment_id: existing.id,
|
|
117
|
+
body,
|
|
118
|
+
});
|
|
119
|
+
} else {
|
|
120
|
+
await github.rest.issues.createComment({
|
|
121
|
+
owner,
|
|
122
|
+
repo,
|
|
123
|
+
issue_number,
|
|
124
|
+
body,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
@@ -18,16 +18,31 @@ jobs:
|
|
|
18
18
|
env:
|
|
19
19
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
|
20
20
|
steps:
|
|
21
|
-
- uses: actions/checkout@
|
|
21
|
+
- uses: actions/checkout@v6
|
|
22
22
|
with:
|
|
23
23
|
fetch-depth: 0
|
|
24
24
|
|
|
25
25
|
- name: Install uv
|
|
26
|
-
uses: astral-sh/setup-uv@
|
|
26
|
+
uses: astral-sh/setup-uv@v7
|
|
27
27
|
|
|
28
28
|
- name: Set up Python
|
|
29
29
|
run: uv python install 3.12
|
|
30
30
|
|
|
31
|
+
- name: Verify tag is signed
|
|
32
|
+
run: |
|
|
33
|
+
TAG=${GITHUB_REF_NAME}
|
|
34
|
+
# Lightweight tags resolve directly to a commit, not a tag object.
|
|
35
|
+
TYPE=$(git cat-file -t "$TAG")
|
|
36
|
+
if [ "$TYPE" != "tag" ]; then
|
|
37
|
+
echo "::error::$TAG is a lightweight tag. Use 'git tag -s' to create a signed annotated tag."
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
# Annotated but unsigned tags have no signature header in the object.
|
|
41
|
+
if ! git cat-file -p "$TAG" | grep -qE "BEGIN (PGP|SSH) SIGNATURE"; then
|
|
42
|
+
echo "::error::$TAG is not signed. Use 'git tag -s' when cutting releases."
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
|
45
|
+
|
|
31
46
|
- name: Verify tag matches pyproject version
|
|
32
47
|
run: |
|
|
33
48
|
TAG=${GITHUB_REF_NAME#v}
|
|
@@ -46,7 +61,7 @@ jobs:
|
|
|
46
61
|
# Configure once at https://pypi.org/manage/account/publishing/
|
|
47
62
|
|
|
48
63
|
- name: Create GitHub Release
|
|
49
|
-
uses: softprops/action-gh-release@
|
|
64
|
+
uses: softprops/action-gh-release@v3
|
|
50
65
|
with:
|
|
51
66
|
generate_release_notes: true
|
|
52
67
|
files: dist/*
|
|
@@ -7,6 +7,58 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.7.0] — 2026-05-20
|
|
11
|
+
|
|
12
|
+
> **Downstream-worker ergonomics release.** Hardens `FlowApiClient` for
|
|
13
|
+
> long-lived integrations: standard exception module name, optional
|
|
14
|
+
> `project_id`, `health_check()` for liveness probes, `out_dir` for
|
|
15
|
+
> debug-screenshot plumbing, and a stable library-owned error when the
|
|
16
|
+
> underlying browser session dies. Plus auth-flow fixes from issues #15 and
|
|
17
|
+
> #17 and overlay-dismiss for first-run profiles (#26).
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- `gflow_cli.exceptions` module as a standard alias for `gflow_cli.errors` — both module names resolve identically. Closes [#16](https://github.com/ffroliva/gflow-cli/issues/16).
|
|
22
|
+
- `FlowApiClient.health_check()` async method — returns `True` if browser context is alive and on a Google domain; safe to call from long-lived workers without try/except. Closes [#16](https://github.com/ffroliva/gflow-cli/issues/16).
|
|
23
|
+
- `FlowApiClient(out_dir=...)` constructor argument — when set, the resolved transport stores it as `_out_dir` so internal `_capture_debug_screenshot` calls inside `UiAutomationTransport._generate_images_locked` (entering the editor, dismissing overlays, sending prompts) save artifacts to that directory. Long-lived workers can now diagnose selector failures without restructuring their call sites. Closes [#18](https://github.com/ffroliva/gflow-cli/issues/18).
|
|
24
|
+
- `BrowserSessionClosedError` (`gflow_cli.errors`, exit code 15) — raised from `FlowApiClient.generate_image()` / `generate_images_batch()` when the underlying Playwright page/context is closed mid-call (Playwright `TargetClosedError`). Callers can now catch a stable library-owned class and recreate the client via `async with FlowApiClient(...)` instead of importing from `playwright._impl._errors`. Closes [#18](https://github.com/ffroliva/gflow-cli/issues/18).
|
|
25
|
+
- `UiAutomationTransport._dismiss_blocking_overlays(page)` — generic overlay-dismiss helper that detects Flow changelog ("What's new") iframes and dismisses them via a close-button selector cascade with an Escape-key fallback. Invoked after editor entry on both image and video flows so first-run profiles no longer fail on the next click. Closes [#26](https://github.com/ffroliva/gflow-cli/issues/26).
|
|
26
|
+
- Release tags must now be **signed annotated tags** (`git tag -s vX.Y.Z`). CI's release job rejects unsigned tags so the GitHub release surfaces as Verified ([#30](https://github.com/ffroliva/gflow-cli/issues/30)).
|
|
27
|
+
- New documentation: [`docs/DEBUGGING.md`](docs/DEBUGGING.md) — evergreen reference for debugging, testing, and troubleshooting (listener log keys, selector-cascade discipline, lifecycle errors, Windows console encoding, test-suite memory). [`docs/LIVE_VERIFICATION_v0.7.0.md`](docs/LIVE_VERIFICATION_v0.7.0.md) — per-release end-to-end evidence (every CLI aspect ratio live-tested).
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- `FlowApiClient.generate_image()` and `generate_images_batch()`: `project_id` is now optional (`str | None = None`). When omitted, a new Flow project is created automatically. Existing callers passing an explicit `project_id` are unaffected. Closes [#16](https://github.com/ffroliva/gflow-cli/issues/16).
|
|
32
|
+
- `gflow video t2v/i2v/batch` now report "temporarily unavailable" — video generation is being rebuilt on the UI-automation transport (Phase A ships the T2V transport; CLI commands return in Phase B).
|
|
33
|
+
|
|
34
|
+
### Removed
|
|
35
|
+
|
|
36
|
+
- The 401-dead HTTP video API path (`FlowApiClient.generate_video`, `get_video_status`) — retired in favour of the new UI-automation transport (`VideoGenerationMixin` in `api/transports/ui_automation_video.py`).
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- `gflow auth login` now verifies a real Flow app session before reporting
|
|
41
|
+
success — fixes issue [#15](https://github.com/ffroliva/gflow-cli/issues/15), where a Google-only sign-in was wrongly accepted
|
|
42
|
+
and later failed with HTTP 401.
|
|
43
|
+
- **`gflow auth login --browser internal` now fails fast when Google rejects
|
|
44
|
+
Playwright's bundled Chromium**, returning `AuthBrowserRejectedError` exit
|
|
45
|
+
code 14 with guidance to rerun using real Chrome
|
|
46
|
+
(`gflow auth login --browser chrome`) or set
|
|
47
|
+
`GFLOW_CLI_AUTH_BROWSER=chrome` ([#17](https://github.com/ffroliva/gflow-cli/issues/17)).
|
|
48
|
+
- **`gflow image t2i --aspect 1:1` aspect-ratio tab regression** — Flow's
|
|
49
|
+
`1:1` tab is now selected via an exact-match (`:text-is`) cascade against
|
|
50
|
+
the labels `1:1`, `Square`, `1×1`, `1x1` instead of the prior
|
|
51
|
+
`:has-text("1:1")` substring match. The substring selector was matching an
|
|
52
|
+
invisible parent on some Flow UI variants, causing a 3 s timeout and a
|
|
53
|
+
silent fallback to Flow's default aspect. All five CLI aspect ratios
|
|
54
|
+
(`16:9`, `9:16`, `1:1`, `4:3`, `3:4`) are now live-verified.
|
|
55
|
+
- `UiAutomationTransport._attach_batch_response_listener` now emits a
|
|
56
|
+
`ui_automation.batch_response_seen` log for every `batchGenerateImages`
|
|
57
|
+
URL observed (BEFORE the per-project filter) and a
|
|
58
|
+
`ui_automation.batch_response_dropped_project_id_mismatch` log when the
|
|
59
|
+
filter rejects a response. Eliminates the silent black-hole that hid
|
|
60
|
+
listener-miss bugs during live verification.
|
|
61
|
+
|
|
10
62
|
## [0.6.0a6] — 2026-05-17
|
|
11
63
|
|
|
12
64
|
> **Stability & code-quality release.** Fixes a concurrency bug in image
|
|
@@ -633,7 +685,8 @@ shell-script template that branches on these codes.
|
|
|
633
685
|
|
|
634
686
|
First skeleton. Not functional end-to-end yet.
|
|
635
687
|
|
|
636
|
-
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.
|
|
688
|
+
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.7.0...HEAD
|
|
689
|
+
[0.7.0]: https://github.com/ffroliva/gflow-cli/compare/v0.6.0a6...v0.7.0
|
|
637
690
|
[0.6.0a6]: https://github.com/ffroliva/gflow-cli/compare/v0.6.0a5...v0.6.0a6
|
|
638
691
|
[0.6.0a5]: https://github.com/ffroliva/gflow-cli/compare/v0.6.0a4...v0.6.0a5
|
|
639
692
|
[0.6.0a1]: https://github.com/ffroliva/gflow-cli/compare/v0.5.0a1...v0.6.0a1
|