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