gflow-cli 0.9.0__tar.gz → 0.9.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gflow_cli-0.9.0 → 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.9.0 → gflow_cli-0.9.1}/.github/workflows/ci.yml +4 -8
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.gitignore +3 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/CHANGELOG.md +91 -1
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/KNOWN_ISSUES.md +85 -28
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/PKG-INFO +2 -2
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/PLAN.md +36 -20
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/README.md +1 -1
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/RELEASE.md +17 -1
- gflow_cli-0.9.1/conftest.py +25 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/DATA_LAYER.md +4 -2
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/DEVELOPMENT.md +6 -1
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/INDEX.md +1 -1
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_v0.9.0.md +2 -0
- gflow_cli-0.9.1/docs/LIVE_VERIFICATION_v0.9.1.md +98 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/PROJECT_STATUS.md +5 -5
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/USAGE.md +5 -2
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/examples/README.md +3 -1
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/examples/sample_config.json +1 -1
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/examples/single_image_t2i.py +6 -4
- {gflow_cli-0.9.0 → 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/cdp_drive_and_probe.py +119 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/record_demo.ps1 +5 -2
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/__init__.py +1 -1
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/ui_automation.py +133 -24
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/ui_automation_video.py +70 -25
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/cli.py +17 -1
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/cli_data.py +66 -18
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/queries.py +22 -15
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/repository.py +23 -1
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/paths.py +9 -4
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_ui_automation.py +148 -4
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_ui_automation_video.py +144 -1
- 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.9.1/tests/conftest.py +79 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/test_settings_and_errors.py +2 -1
- gflow_cli-0.9.1/tests/e2e/test_locale_selectors_e2e.py +87 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/test_transports_e2e.py +128 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/test_video_t2v_e2e.py +23 -13
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/smoke/test_real_flow.py +8 -4
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_browser_manager.py +8 -2
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_cli_data.py +77 -7
- gflow_cli-0.9.1/tests/test_conftest_isolation.py +40 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_data_queries.py +26 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_paths.py +45 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/uv.lock +1 -1
- gflow_cli-0.9.0/docs/superpowers/notes/v0.9.0-schema-reconciliation.md +0 -108
- gflow_cli-0.9.0/docs/superpowers/plans/2026-05-24-v0.9.0-release-implementation.md +0 -2123
- gflow_cli-0.9.0/docs/superpowers/specs/2026-05-24-v0.9.0-release-design.md +0 -204
- gflow_cli-0.9.0/tests/cli/test_cli_data.py +0 -81
- gflow_cli-0.9.0/tests/conftest.py +0 -38
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.claude/README.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.claude/commands/gflow/changelog.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.claude/commands/gflow/doc-review.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.claude/commands/gflow/known-issues.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.claude/commands/gflow/plan.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.claude/commands/gflow/release.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.continue-here.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.env.template +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.gitattributes +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.github/CODEOWNERS +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.github/copilot-instructions.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.github/dependabot.yml +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.github/workflows/external-pr-triage.yml +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.github/workflows/release.yml +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.gitleaks.toml +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.planning/todos/pending/2026-05-11-add-project-logo-and-docs-site-promotion-plan.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.planning/todos/pending/pr-38-review.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.pre-commit-config.yaml +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/.secrets.baseline +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/AGENTS.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/CLAUDE.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/CONFIGURATION.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/CONTRIBUTING.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/DISCLAIMER.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/LICENSE +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/ROADMAP.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/AGENT_GUIDE.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/ARCHITECTURE.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/AUTHENTICATION.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/CONFIGURATION.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/DEBUGGING.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/GITHUB.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_data_layer.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_image_batch.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_v0.7.0.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_v0.8.1.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/LIVE_VERIFICATION_video_download.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/SECURITY.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/USER_GUIDE.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/assets/example-run.gif +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/2026-05-17-issue-15-handover.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-09-image-mvp-orchestration.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-09-image-mvp.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-09-video-mvp.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-10-phase-4-hardening-orchestration.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-10-phase-4-hardening.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/2026-05-14-shell-multi-prompt-orchestration.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_ARCH.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_SEC_UX.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_CODE.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_GEMINI.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_SECURITY.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_PYTHON.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_SECURITY.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_CODE.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_FOLLOWUP.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_PLANNER.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY_FOLLOWUP.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_FINAL_SEC_UX_VERIFIED.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_PLAN_SECURITY.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_SPEC_SECURITY.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/PLAN.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/orchestration.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-17-e2e-test-coverage.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-17-issue-15-auth-verification-fix.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-17-issue-15-i2v-bearer-auth.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-17-issue-15-orchestration.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-18-video-phase0-submit-spike.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-19-video-phase-a-execution-state.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-19-video-phase-a-orchestration.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-19-video-phase-a-t2v.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-20-video-download-t2v-cli.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-21-multi-image-prompt-orchestration.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-21-multi-image-prompt.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-22-pr-38-review.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-22-stay-mounted-batch-session-plan.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-23-locale-agnostic-selectors.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/plans/2026-05-24-data-layer.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-10-phase-4-hardening-design.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-14-shell-multi-prompt-design.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-15-auth-login-real-chrome-design.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-17-e2e-test-coverage-design.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-17-i2v-uploadimage-401-bearer-auth-design.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-17-issue-15-auth-verification-fix-design.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-17-issue-15-root-cause-findings.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-18-ui-automation-video-generation-design.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-21-multi-image-prompt-design.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-22-pr-38-review-design.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-22-stay-mounted-batch-session-design.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-23-locale-agnostic-selectors.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-23-readme-v0.8.1-refresh-design.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/specs/2026-05-24-data-layer-design.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/examples/batch_from_config.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/examples/multi_prompt_t2i.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/examples/sample_prompts.txt +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/llms.txt +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/README.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/01_upload_image.json +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/04_archive_workflow.json +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/05_createProject.json +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/06_batchGenerateImages.json +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/08_batchAsyncGenerateVideoStartAndEndImage.json +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/09_batchAsyncGenerateVideoReferenceImages.json +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/10_batchCheckAsyncVideoGenerationStatus_successful.json +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/samples/captured/11_batchCheckAsyncVideoGenerationStatus_failed.json +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/ci/check_doc_links.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/ci/check_repo_hygiene.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/debug_editor.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/debug_gen_settings.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/debug_settings.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/dev/active_plan.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/dev/capture_image_add_media_dom.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/dev/capture_locale_invariants.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/dev/monitor_pr_38.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/diag_capture_flow_traffic.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/diag_recaptcha_mint.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/smoke_image.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/smoke_real_chrome_image.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/smoke_video_editor.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/smoke_worker_style.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/scripts/verify_chrome_auth_viability.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/skills/README.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/skills/gflow-cli/SKILL.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/sonar-project.properties +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/__main__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/_cli_helpers.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/_retry.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/client.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/dto.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/image.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/recaptcha.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/routes.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/_common.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/_fingerprint.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/base.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/experimental/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/experimental/bearer.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/transports/experimental/sapisidhash.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/api/video.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/base.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/factory.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/internal_chromium.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/real_chrome.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/strategies.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/auth/verification.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/browser_manager.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/cli_image.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/cli_run.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/cli_video.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/config.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/migrations/0001_initial.sql +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/migrations/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/models.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/recorder.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/redaction.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/data/store.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/errors.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/exceptions.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/image_batch.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/manifest.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/observability.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/src/gflow_cli/profile_store.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tasks/lessons.md +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/test_assets/sample_batch.json +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/test_assets/sample_batch.tsv +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/test_assets/sample_batch_invalid.tsv +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_client.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_client_image.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_concurrency.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_dto.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_image.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_image_dto.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_recaptcha.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_retry.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_routes.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/test_video.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_base.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_bearer.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_common.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_evaluate_fetch.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_factory.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_fingerprint.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_sapisidhash.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_ui_automation_batch.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/api/transports/test_ui_automation_image_mode.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/auth/strategies/test_factory.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/auth/strategies/test_strategies.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/auth/test_verification.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_cli_image.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_cli_image_seed_removed.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_cli_run.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_cli_video.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_error_handling.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_helpers.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/cli/test_t2i_multi_prompt.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/test_packaging.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/test_recorder.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/test_redaction.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/test_repository.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/data/test_store_migrations.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/conftest.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/test_auth_verification_e2e.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/test_data_layer_e2e.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/e2e/test_image_batch_e2e.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/auth.feature +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/auth_login.feature +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/conftest.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/image.feature +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/test_auth_login_steps.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/test_auth_steps.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/test_image_steps.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/features/test_step_collision_guard.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/fixtures/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/fixtures/seeded_catalog.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/image_batch/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/image_batch/test_image_manifest.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/image_batch/test_observability_events.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/smoke/__init__.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_auth.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_config.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_errors.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_manifest.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_observability.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_profile_store.py +0 -0
- {gflow_cli-0.9.0 → gflow_cli-0.9.1}/tests/test_smoke.py +0 -0
|
@@ -32,7 +32,7 @@ uv run pyright src
|
|
|
32
32
|
**4. Tests + coverage** (report only)
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
uv run pytest -q --cov=gflow_cli --cov-fail-under=80
|
|
35
|
+
uv run python -m pytest -q --cov=gflow_cli --cov-fail-under=80
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
## Output
|
|
@@ -46,3 +46,7 @@ uv run pytest -q --cov=gflow_cli --cov-fail-under=80
|
|
|
46
46
|
|
|
47
47
|
Ruff fix and format may rewrite multiple files. Always `git diff` before staging.
|
|
48
48
|
Pyright errors and test failures require manual intervention — do not attempt silent workarounds.
|
|
49
|
+
If the coverage run crashes the current MCP/sandbox session with `Connection closed`, re-run the
|
|
50
|
+
same marker-filtered suite in smaller chunks without coverage and rely on CI for the coverage XML.
|
|
51
|
+
Project pytest defaults already exclude `e2e` and `live`; those markers are explicit,
|
|
52
|
+
credit-spending gates and must be requested with a separate `-m e2e` / `-m live` command.
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Multi-dimensional LLM council review of an open PR. Adaptive dimensions per PR surface (data / transports / CLI / docs / auth). Baseline always includes correctness, code quality, security, and tests. With no argument, lists open PRs ranked by review priority.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# `/gflow:pr-council-review [PR#]` — PR Council Review Gate
|
|
6
|
+
|
|
7
|
+
Council-driven PR review. Dispatches **4 baseline + N adaptive** parallel reviewers, each scoped to one dimension, then synthesizes a single consensus verdict. Validated on PR #93 (2026-05-26) — see memory `llm-council-code-review-pr93`.
|
|
8
|
+
|
|
9
|
+
**Two modes:**
|
|
10
|
+
1. **No argument** → list open PRs ranked by review priority; user picks.
|
|
11
|
+
2. **`PR#` argument** → run the full council on that PR.
|
|
12
|
+
|
|
13
|
+
Treat **YELLOW as soft block** (per memory `llm-council-data-layer-fixes`).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 0 · Pre-flight
|
|
18
|
+
|
|
19
|
+
**All four checks are mandatory. Any failure halts before Phase 1/2.**
|
|
20
|
+
|
|
21
|
+
1. **`gh` authenticated** — run `gh auth status`. Non-zero exit → stop with: *"`gh` is not authenticated. Run `gh auth login` and re-invoke."* Do NOT proceed to dispatch agents that would all fail opaquely.
|
|
22
|
+
2. **Inside the repo** — assert `AGENTS.md` AND `CLAUDE.md` exist in the working directory.
|
|
23
|
+
3. **Resolve the argument:**
|
|
24
|
+
- **Empty** → jump to **Phase 1 (Prioritize)**.
|
|
25
|
+
- **PR number** → validate it with `gh pr view <N> --json number`. If error → stop with the error verbatim. Do NOT silently fall back to Phase 1.
|
|
26
|
+
4. **Draft check** (PR# mode only) — if `gh pr view <N> --json isDraft` returns `true`, surface a banner citing memory `draft-pr-merge-trap`: *"PR #N is DRAFT. Reviewing is fine, but do NOT merge a draft (the merge API can close it + delete the head ref). Run `gh pr ready N` first if you intend to merge. Continue review? (yes/no)"*. Ask the user before dispatching.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 1 · Prioritize (no-argument mode)
|
|
31
|
+
|
|
32
|
+
Run once, list open PRs in recommended order, then stop and ask the user which to review.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
gh pr list --state open --json number,title,author,isDraft,headRefName,updatedAt,additions,deletions,labels,reviewDecision,statusCheckRollup
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Empty-list short-circuit:** if the result is `[]`, print *"No open PRs to review."* and exit. Do NOT render an empty table or fall through to Phase 2.
|
|
39
|
+
|
|
40
|
+
Rank with these heuristics (highest priority first):
|
|
41
|
+
|
|
42
|
+
| Signal | Weight | Why |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| `isDraft == false` AND CI all-green | +3 | Ready to merge once approved — highest ROI |
|
|
45
|
+
| Touched path includes `src/gflow_cli/api/transports/` | +2 | UI-automation is the highest-risk surface (memory `pr-must-verify-on-affected-surface`) |
|
|
46
|
+
| Touched path includes `src/gflow_cli/auth/` or `recaptcha` | +2 | Auth changes need security-deep-dive |
|
|
47
|
+
| Touched path includes `src/gflow_cli/data/` | +2 | Migration safety + #86 hygiene history |
|
|
48
|
+
| Older than 7 days (stale risk) | +1 | Conflict risk grows with age |
|
|
49
|
+
| `additions + deletions <= 300` | +1 | Small PRs ship faster |
|
|
50
|
+
| Label contains `release-blocker`, `security`, `hotfix` | +5 | Anything labelled urgent jumps the queue |
|
|
51
|
+
| `isDraft == true` AND CI red | −2 | Author still iterating; review wastes their time |
|
|
52
|
+
|
|
53
|
+
Present a numbered table:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
| Rank | PR# | Title | Ready? | CI | Surface | Why prioritized |
|
|
57
|
+
|------|-----|-------|--------|----|---------| ---------------|
|
|
58
|
+
| 1 | #71 | feat(image): native count selector … | ✅ | green | transports | Ready + transports surface + small (220 LOC) |
|
|
59
|
+
| 2 | …
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Then **stop and ask** the user to pick a PR number. Do NOT auto-start a review on Rank 1 — *recommend*, do not *pre-select*. The user MUST type the PR number they want reviewed.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 2 · Gather context (PR# mode)
|
|
67
|
+
|
|
68
|
+
Pull in parallel. Use `ctx_batch_execute` to avoid context-window flood.
|
|
69
|
+
|
|
70
|
+
**Commands** (label → cmd):
|
|
71
|
+
- `PR_META` → `gh pr view <N> --json title,body,author,baseRefName,headRefName,state,isDraft,additions,deletions,changedFiles,labels,files,statusCheckRollup`
|
|
72
|
+
- `PR_DIFF` → `gh pr diff <N>`
|
|
73
|
+
- `PR_CHECKS` → `gh pr checks <N>`
|
|
74
|
+
- `TOUCHED_PATHS` → `gh pr view <N> --json files --jq '.files[].path' | sort -u`
|
|
75
|
+
- `RECENT_COMMITS` → `gh pr view <N> --json commits --jq '.commits[-5:] | .[] | "\(.oid[:7]) \(.messageHeadline)"'`
|
|
76
|
+
|
|
77
|
+
**Reference files** (Read inline; small enough to load):
|
|
78
|
+
- `CLAUDE.md` — Claude-Code-specific protocol
|
|
79
|
+
- `AGENTS.md` — universal agent rules
|
|
80
|
+
- `docs/INDEX.md` — docs routing
|
|
81
|
+
- `~/.claude/projects/C--development-github-gflow-cli/memory/MEMORY.md` — memory index
|
|
82
|
+
|
|
83
|
+
**Memory traversal:** For each `TOUCHED_PATH`, glob memory for related entries:
|
|
84
|
+
- `transports/` (image OR video) → `[[pr-must-verify-on-affected-surface]]`, `[[flow-locale-leak-icon-ligatures]]`, `[[playwright-click-no-downstream-event-signature]]`, `[[rest-transports-drop-ui-fields]]`, `[[image-video-mode-switch-symmetry]]`, `[[video-generation-spec]]`, `[[image-generation-401-next]]`
|
|
85
|
+
- `data/` → `[[data-layer-overview]]`, `[[data-layer-test-pollution-trap]]`, `[[data-layer-v0.9.0-bugs]]`, `[[exit-code-16-data-store]]`, `[[on-started-callback-recorder-safety]]`
|
|
86
|
+
- `auth/` → `[[real-browser-auth-mandatory]]`, `[[release-signing]]`
|
|
87
|
+
- `cli` → `[[release-back-merge-gap-recovery]]`, `[[wheel-build-sanity-gate]]`
|
|
88
|
+
- `tests/` (any) → `[[bdd-stubs-mirror-runtime-signatures]]`, `[[background-e2e-pytest-pattern]]`, `[[full-test-suite-ooms]]`, `[[stale-test-discovery]]`, `[[structlog-cache-logger-off-for-tests]]`
|
|
89
|
+
- `tests/features/` (BDD) → also `[[bdd-stubs-mirror-runtime-signatures]]` (silent TypeError trap)
|
|
90
|
+
- `scripts/` (dev / CI / release helpers) → `[[wheel-build-sanity-gate]]`, `[[release-back-merge-gap-recovery]]`
|
|
91
|
+
- `.planning/`, `docs/superpowers/` (process artifacts) → `[[release-spec-plan-memory-consolidation]]`
|
|
92
|
+
- `docs/`, `*.md` → `[[readme-hybrid-router-pattern]]`, `[[llm-council-doc-review-v0.9.0]]`, `[[agents-md-vs-llms-txt]]`, `[[pypi-readme-staleness-fix]]`
|
|
93
|
+
- `pyproject.toml`, `.github/` → `[[release-spec-plan-memory-consolidation]]`, `[[pr-hygiene-revert-and-multi-commit]]`, `[[draft-pr-merge-trap]]`, `[[pypi-rejected-filename-reusable]]`
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 3 · Detect adaptive dimensions
|
|
98
|
+
|
|
99
|
+
The **baseline** 4 dimensions run for every PR. **Adaptive** dimensions activate only when the touched paths or labels match. Build the council roster before dispatching.
|
|
100
|
+
|
|
101
|
+
| Dimension | Always? | Activates when… |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| **D1 — Correctness & completeness** | ✅ baseline | always |
|
|
104
|
+
| **D2 — Code quality & best practices** | ✅ baseline | always |
|
|
105
|
+
| **D3 — Security** | ✅ baseline | always |
|
|
106
|
+
| **D4 — Tests & coverage** | ✅ baseline | always |
|
|
107
|
+
| **D5 — UI / live-verification** | adaptive | any path under `src/gflow_cli/api/transports/` or `tests/e2e/` |
|
|
108
|
+
| **D6 — Data-migration safety** | adaptive | any path under `src/gflow_cli/data/` or `*.sql` |
|
|
109
|
+
| **D7 — CLI UX & help-text consistency** | adaptive | any path matching `src/gflow_cli/cli*.py` or `src/gflow_cli/commands/` |
|
|
110
|
+
| **D8 — Docs cross-reference & drift** | adaptive | ≥2 of these touched: `README.md`, `docs/**`, `CHANGELOG.md`, `AGENTS.md`, `CLAUDE.md`, `PLAN.md` |
|
|
111
|
+
| **D9 — Auth / reCAPTCHA / Chrome-profile** | adaptive | any path under `src/gflow_cli/auth/` or label `security` |
|
|
112
|
+
| **D10 — Release-gate compliance** | adaptive | `pyproject.toml`, `src/gflow_cli/__init__.py`, `.github/workflows/`, or `release/*` branch |
|
|
113
|
+
| **D11 — BDD step-stub signatures** | adaptive | any path under `tests/features/` (silent TypeError trap, memory `bdd-stubs-mirror-runtime-signatures`) |
|
|
114
|
+
| **D12 — Dev / release scripts** | adaptive | any path under `scripts/` |
|
|
115
|
+
|
|
116
|
+
**Baseline floor is non-negotiable.** D1–D4 ALWAYS run, even on docs-only PRs. The user spec explicitly required quality / security / best-practices / tests as a floor — do not skip.
|
|
117
|
+
|
|
118
|
+
**Docs-only PRs** (defined as: 100% of touched paths match `*.md`, `docs/**`, `CHANGELOG.md`, `README.md`, `LICENSE`, `AUTHORS`) → D4 reframes from "test code coverage" to "docs-verification" (broken cross-references, dead links, code examples that don't run). The dimension still runs; only its lens shifts.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 4 · Dispatch the council
|
|
123
|
+
|
|
124
|
+
Use `superpowers:dispatching-parallel-agents`. Send **all** agents in one message — they must run concurrently. Each agent must:
|
|
125
|
+
|
|
126
|
+
- Get the PR number, base branch, and head branch.
|
|
127
|
+
- Be told its dimension AND told what NOT to duplicate (the other dimensions' scope).
|
|
128
|
+
- Use `ctx_execute` for large outputs (diff, file reads) — never flood the context.
|
|
129
|
+
- Output a structured report: **Verdict (GREEN / YELLOW / RED)**, **Must-fix** (numbered, file:line refs), **Nice-to-have** (numbered), **Confirmed-good/safe/correct** (1-line bullets).
|
|
130
|
+
- Be word-limited to **under 500 words** so the synthesizer doesn't drown.
|
|
131
|
+
|
|
132
|
+
**Per-dimension prompt skeleton** (fill in `<…>`):
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
You are one of <N> parallel reviewers on a council reviewing PR #<N> of `gflow-cli` at C:\development\github\gflow-cli.
|
|
136
|
+
|
|
137
|
+
Your dimension is **<DIMENSION NAME>**. Other agents handle <other dimensions> — do NOT duplicate their work.
|
|
138
|
+
|
|
139
|
+
Get the diff with `gh pr diff <N>` via ctx_execute. If `additions + deletions > 5000`, do NOT pull the full diff at once — instead enumerate touched files with `gh pr view <N> --json files --jq '.files[].path'`, then read per-directory with `gh pr diff <N> -- <path>` to keep each call under 2k lines. Read the unchanged surrounding code with Read for any file you flag.
|
|
140
|
+
|
|
141
|
+
Assess specifically:
|
|
142
|
+
1. <dimension-specific question 1, with code citation hooks>
|
|
143
|
+
2. <…>
|
|
144
|
+
3. <…>
|
|
145
|
+
|
|
146
|
+
**Mandatory memory you MUST consult and cite if relevant** (from the Dimension → Slugs table below): <fixed slug list for this dimension>.
|
|
147
|
+
|
|
148
|
+
Output a structured report under 500 words:
|
|
149
|
+
- Verdict: GREEN / YELLOW / RED
|
|
150
|
+
- Must-fix (numbered, file:line refs)
|
|
151
|
+
- Nice-to-have (numbered)
|
|
152
|
+
- Confirmed-<good/safe/correct> (1-line bullets)
|
|
153
|
+
|
|
154
|
+
Be skeptical. Cite file paths and line numbers. **If you have nothing to flag in your dimension, say so explicitly and state GREEN with a one-line justification — do NOT manufacture findings to look thorough.**
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Dimension → mandatory slugs table** (always pass these in the prompt, regardless of which paths the PR touches — they encode the recurring traps for that dimension):
|
|
158
|
+
|
|
159
|
+
| Dim | Mandatory memory slugs |
|
|
160
|
+
|---|---|
|
|
161
|
+
| D1 | `[[pr-must-verify-on-affected-surface]]` |
|
|
162
|
+
| D2 | (none mandatory; consult surrounding code style) |
|
|
163
|
+
| D3 | `[[real-browser-auth-mandatory]]`, `[[release-signing]]` |
|
|
164
|
+
| D4 | `[[pr-must-verify-on-affected-surface]]`, `[[full-test-suite-ooms]]`, `[[stale-test-discovery]]`, `[[structlog-cache-logger-off-for-tests]]` |
|
|
165
|
+
| D5 | `[[flow-locale-leak-icon-ligatures]]`, `[[playwright-click-no-downstream-event-signature]]`, `[[rest-transports-drop-ui-fields]]`, `[[image-video-mode-switch-symmetry]]`, `[[verification-ledger-5-layer]]` |
|
|
166
|
+
| D6 | `[[on-started-callback-recorder-safety]]`, `[[data-layer-test-pollution-trap]]`, `[[exit-code-16-data-store]]`, `[[data-layer-v0.9.0-bugs]]` |
|
|
167
|
+
| D7 | (none mandatory) |
|
|
168
|
+
| D8 | `[[readme-hybrid-router-pattern]]`, `[[agents-md-vs-llms-txt]]`, `[[pypi-readme-staleness-fix]]`, `[[llm-council-doc-review-v0.9.0]]` |
|
|
169
|
+
| D9 | `[[real-browser-auth-mandatory]]` |
|
|
170
|
+
| D10 | `[[release-back-merge-gap-recovery]]`, `[[wheel-build-sanity-gate]]`, `[[pypi-rejected-filename-reusable]]`, `[[draft-pr-merge-trap]]` |
|
|
171
|
+
| D11 | `[[bdd-stubs-mirror-runtime-signatures]]` |
|
|
172
|
+
| D12 | `[[wheel-build-sanity-gate]]` |
|
|
173
|
+
|
|
174
|
+
**Per-dimension specifics** (concrete checks each agent must perform):
|
|
175
|
+
|
|
176
|
+
- **D1 Correctness & completeness:**
|
|
177
|
+
- Does the fix address the *root cause* or only the symptom? Cite the function being changed.
|
|
178
|
+
- Are edge cases handled? Spot-check 2 boundary conditions.
|
|
179
|
+
- Does the CHANGELOG entry match what shipped? Quote both.
|
|
180
|
+
- **PR-body compliance:** does the PR body's description match the diff? Are the PR body's test-plan checkboxes (the `- [ ]` / `- [x]` markers) accurate? If any unchecked box represents work the PR claims to deliver, flag it. If the PR claims `Closes #N` for an issue whose acceptance criteria are not met by the diff, flag it.
|
|
181
|
+
- **D2 Code quality:** Style consistency with surrounding code? Comments explain WHY not WHAT (per `CLAUDE.md`)? Any abstraction that doesn't earn its keep? SRP intact? Type annotations on every new signature?
|
|
182
|
+
- **D3 Security:** Injection vectors? Env-var trust boundary? Shell interpolation (`subprocess`, `shell=True`)? Path traversal? Secret-shaped literals? `--no-verify` or signature-bypass in commits?
|
|
183
|
+
- **D4 Tests:**
|
|
184
|
+
- **Mandatory affected-surface check** (cardinal rule, memory `pr-must-verify-on-affected-surface`): identify the runtime surface the fix touches (T2V / I2V / R2V / data / CLI / auth / etc.). If the test suite does not exercise that exact surface (e.g. a fix for `_attach_frame` with only T2V tests), this is **automatically YELLOW**. Cite the test `file:line` that proves coverage of the affected surface — or state explicitly that no such test exists.
|
|
185
|
+
- Test pyramid placement (unit vs integration vs e2e)?
|
|
186
|
+
- Do tests verify *behavior* or just shape (static strings, mocked returns)?
|
|
187
|
+
- Coverage delta meaningful, or dead-coverage (counts new constants without exercising them)?
|
|
188
|
+
- **D5 UI/live-verify:** Will this selector match real Flow DOM on non-EN locales? Is there runtime evidence beyond static-string invariants? Has the PR author pasted live-verify evidence (file count + magic bytes + Pillow dims + structlog events such as `new_project_clicked` / `submit_clicked` / `frame_attached` / `image_mode_entered` / `count_setter_completed` / `reference_attached`) in the PR body or a comment? **Absent live-verify on a UI-automation PR is YELLOW per memory `pr-must-verify-on-affected-surface`.**
|
|
189
|
+
- **D6 Data-migration & on_started safety:**
|
|
190
|
+
- **Mandatory on_started callback check** (memory `on-started-callback-recorder-safety`): grep the diff for `VideoStartedCallback` / `on_started` / any new callback invoked inside a transport during a paid Flow generation. Verify each callsite is wrapped in `try/except DataStoreError` (and ideally a broad guard). **A bare callback in a paid-generation path is automatically RED** — uncaught exceptions abort paid generation.
|
|
191
|
+
- Schema-compat with existing rows? Migration script idempotent?
|
|
192
|
+
- `DataStoreError` vs `DataMigrationError` vs `DataIntegrityError` semantics correct? Pre-Flow failures vs post-success-warn-and-return-0 per memory `exit-code-16-data-store`?
|
|
193
|
+
- **D7 CLI UX:** Help text matches behavior? Flag names follow `--kebab-case`? Does the new flag appear in `--help` golden-snapshot tests? Examples in docstring runnable?
|
|
194
|
+
- **D8 Docs drift:** Cross-references mutually consistent (CLAUDE.md / AGENTS.md / docs/INDEX.md / README.md / PLAN.md)? Code examples actually run? Version strings consistent across files?
|
|
195
|
+
- **D9 Auth:** Chrome-strategy profile required (memory `real-browser-auth-mandatory`)? Profile-dir SecurityError boundary intact (`outside of GFLOW_CLI_HOME`)? No new secret-shaped strings?
|
|
196
|
+
- **D10 Release-gate:**
|
|
197
|
+
- **Quote the version string** from `pyproject.toml` AND from `src/gflow_cli/__init__.py` and confirm they match exactly. If only one was bumped → RED.
|
|
198
|
+
- Verify `CHANGELOG.md` `[Unreleased]` was emptied and a new version section added — cite the line range.
|
|
199
|
+
- Wheel build clean (`uv build` + ZIP-dupe check per memory `wheel-build-sanity-gate`)?
|
|
200
|
+
- Back-merge gap from prior releases addressed (memory `release-back-merge-gap-recovery`)?
|
|
201
|
+
- **D11 BDD step-stub signatures:** any new `_run_*` kwarg or runtime signature change requires mirroring in `tests/features/_fake_*` stubs — silent `TypeError` trap. Cite each fake stub touched (or assert no signature change occurred).
|
|
202
|
+
- **D12 Dev/release scripts:** any new script must run cleanly on Windows (memory `windows-dev-quirks`); release scripts must include the wheel-build sanity gate.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## 5 · Synthesize the verdict
|
|
207
|
+
|
|
208
|
+
After all agents return:
|
|
209
|
+
|
|
210
|
+
1. **Tally verdicts:** count GREEN / YELLOW / RED per dimension.
|
|
211
|
+
2. **Handle missing agents:** if any dimension failed to return (timeout, dispatch error), mark it `UNKNOWN` and downgrade the consensus by one step (GREEN → YELLOW, YELLOW → YELLOW, RED stays RED). Never wait indefinitely. Surface which dimension is missing so the user can re-dispatch if they want.
|
|
212
|
+
3. **Consensus rule:**
|
|
213
|
+
- Any RED → **RED** (block merge).
|
|
214
|
+
- Any YELLOW → **YELLOW** (soft block — must address before merge, per memory `llm-council-data-layer-fixes`).
|
|
215
|
+
- All GREEN → **GREEN** (mergeable).
|
|
216
|
+
4. **Deduplicate must-fix AND confirmed-good items:** if two dimensions flag the same issue (or confirm the same positive), list it once and credit both.
|
|
217
|
+
5. **Live-verify gate** (D5 fired + PR body has unchecked live-verify boxes): emit an explicit `AskUserQuestion` with three options — (a) *Run now (estimate: ~1 Flow image credit per locale)*, (b) *Block merge — add to PR body as required reviewer action*, (c) *Skip and accept the risk*. Cite memory `verification-ledger-5-layer` in the question body so the user is reminded that file count alone is not proof. Do NOT spend credits without an explicit affirmative click.
|
|
218
|
+
6. **YELLOW escape valve:** when reporting in Phase 6, the `AskUserQuestion` MUST include a *"Dismiss YELLOW with justification (logged)"* option so the user is never trapped without a path forward. Dismissal requires a one-line reason that gets appended to the PR body or comment, so the override is auditable.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 6 · Report
|
|
223
|
+
|
|
224
|
+
Output to the user, in this exact shape:
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
# PR #<N> — Council Review Verdict
|
|
228
|
+
|
|
229
|
+
## Consensus: <emoji> <GREEN | YELLOW | RED>
|
|
230
|
+
|
|
231
|
+
| Dimension | Verdict | Headline |
|
|
232
|
+
|---|---|---|
|
|
233
|
+
| <D1> | … | <one-line summary> |
|
|
234
|
+
| <D2> | … | … |
|
|
235
|
+
…
|
|
236
|
+
|
|
237
|
+
## Must-fix (<N>)
|
|
238
|
+
1. **<short title>** — `<file>:<line>`. <description>. <which dimension flagged>.
|
|
239
|
+
2. …
|
|
240
|
+
|
|
241
|
+
## Nice-to-have (<N>)
|
|
242
|
+
1. …
|
|
243
|
+
|
|
244
|
+
## Confirmed-good (high-confidence positives)
|
|
245
|
+
- …
|
|
246
|
+
|
|
247
|
+
## How to proceed
|
|
248
|
+
<AskUserQuestion: which must-fixes to apply now, whether to run live-verify, etc.>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Always end with an `AskUserQuestion` so the user can drive next steps (apply fixes, post evidence, dismiss findings).
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 7 · Provenance & extensions
|
|
256
|
+
|
|
257
|
+
> **Provenance:** the council protocol below was validated on PR #93 (locale selectors + DB isolation, merged 2026-05-26). The audit found an unanchored regex + a silent-test-pyramid gap that 152 passing unit tests missed. Then a meta-council audited *this* command itself, surfacing 13 must-fix items now applied. See memory `[[llm-council-code-review-pr93]]`.
|
|
258
|
+
|
|
259
|
+
- Council baseline = 4 dimensions (D1–D4) always run. Adaptive ceiling = D5–D12 (currently). Going beyond ~12 dimensions adds noise faster than signal — split into two reviews instead.
|
|
260
|
+
- Each agent currently uses `general-purpose`. If a future dedicated `code-reviewer` subagent ships, swap it in.
|
|
261
|
+
- If a PR touches paths that don't match any adaptive dimension, document the gap and add a new dimension here (D13+).
|
|
262
|
+
- The command is **stateless** — concurrent invocations on different PR numbers don't share data, so two instances can run in parallel without interference.
|
|
263
|
+
- **Idempotence:** running the same council on the same PR SHA should produce comparable verdicts on different days. If verdicts drift, the cause is usually (a) memory grew new precedents, or (b) the mandatory-slug table here needs an update. Drift is informational, not a defect.
|
|
264
|
+
- No destructive git/gh actions are taken by this command. Reviews are read-only. The user always drives apply-fix / push / merge through subsequent commands.
|
|
265
|
+
- **Sibling commands.** `/review` is the single-agent Claude-Code built-in (one-pass code review, fast and cheap) — use it for spot-checks, draft iteration, or when the council is overkill. `/gflow:pr-council-review` is the multi-agent council version — use it before merge, on high-risk surfaces (auth, transports, data, release-gate), or whenever a single-agent pass would miss the cross-dimension defects the council is designed to catch.
|
|
@@ -54,14 +54,10 @@ jobs:
|
|
|
54
54
|
run: uv run pyright src
|
|
55
55
|
|
|
56
56
|
- name: Test (smoke only) + coverage
|
|
57
|
-
# e2e tests
|
|
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/
|
|
@@ -7,6 +7,95 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.9.1] — 2026-05-27
|
|
11
|
+
|
|
12
|
+
> **Locale and catalog patch release.** Hardens the headed-browser UI
|
|
13
|
+
> automation path for localized Flow profiles, fixes I2V start/end-frame
|
|
14
|
+
> attachment on non-English Chrome/Flow sessions, and repairs first-run catalog
|
|
15
|
+
> edge cases found after v0.9.0.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- `NEW_PROJECT_SELECTORS` now covers all 14 supported locales (EN / PT / ES /
|
|
20
|
+
FR / DE / IT / NL / JA / ZH / KO / PL / RU / TR / ID) and leads with
|
|
21
|
+
locale-stable icon selectors (`add_2` Material Symbols ligature on
|
|
22
|
+
`<button>` and on `[role='button']` ARIA-role variants, plus an anchored
|
|
23
|
+
`^\+\s+\S+$` regex for `+ <word>` host elements). English-only
|
|
24
|
+
`[aria-label*='New project']` and `[aria-label*='Project']` ARIA fallbacks
|
|
25
|
+
removed.
|
|
26
|
+
`SUBMIT_BUTTON_SELECTORS` drops its English-only
|
|
27
|
+
`button[aria-label*="Create"]` fallback — the preceding `arrow_forward` icon
|
|
28
|
+
entries already cover this button in every locale. Both selector tuples are
|
|
29
|
+
now fully locale-invariant for non-English Chrome profiles. The `--lang=en-US`
|
|
30
|
+
Chromium launch arg is retained only to stabilise `IMAGE_MODEL_OPTION_SELECTORS`
|
|
31
|
+
(English product names); its removal is tracked as issue #24 Phase 5 (#94).
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- Bare `pytest` no longer collects live/e2e tests by default. The project-wide
|
|
36
|
+
pytest `addopts` now excludes `e2e` and `live` unless callers explicitly pass
|
|
37
|
+
a different `-m` expression, and `tests/smoke/test_real_flow.py` is marked
|
|
38
|
+
with both markers so marker-filtered local and CI runs cannot accidentally
|
|
39
|
+
launch a real Flow browser session.
|
|
40
|
+
- Browser-manager PID tests no longer call the real `os.kill` while pretending
|
|
41
|
+
to be on POSIX from a Windows runner. The POSIX liveness branches are now
|
|
42
|
+
tested with mocked `os.kill`, avoiding hard interpreter/session exits during
|
|
43
|
+
local test runs.
|
|
44
|
+
|
|
45
|
+
- Running the pytest suite no longer writes fixture rows into the developer's
|
|
46
|
+
production `gflow.db` catalog. A new autouse `_isolate_settings` fixture in
|
|
47
|
+
`tests/conftest.py` redirects `GFLOW_CLI_HOME` and `GFLOW_CLI_DB_PATH` to
|
|
48
|
+
per-test `tmp_path` dirs and clears the `get_settings()` `lru_cache` before
|
|
49
|
+
and after every test, preventing the cached singleton from ever resolving to
|
|
50
|
+
a `platformdirs` production path. Closes
|
|
51
|
+
[#86](https://github.com/ffroliva/gflow-cli/issues/86).
|
|
52
|
+
|
|
53
|
+
- `gflow video i2v` no longer silently breaks on non-English Chrome profiles.
|
|
54
|
+
PR #70's structural-first `_attach_frame` cascade matched **zero** real
|
|
55
|
+
slots — its anchor selector assumed the `swap_horiz` icon used class
|
|
56
|
+
`google-symbols` (it uses `material-icons`) and the slots were `<button>`
|
|
57
|
+
(they're `<div type="button">`). Production I2V therefore relied on the
|
|
58
|
+
English-text fallback, which silently misses on any non-EN profile (pt-BR
|
|
59
|
+
shows `Inicial`/`Final`, DE shows `Anfang`/`Ende`, etc.). Replaced
|
|
60
|
+
`FRAME_SLOTS_STRUCT` with the locale-free pattern
|
|
61
|
+
`div[type='button'][aria-haspopup='dialog']` and added a `.first`-of-remaining
|
|
62
|
+
fallback for the End-frame case (after Start is attached, only one slot
|
|
63
|
+
matches and the prior `.nth(slot_index)` went out-of-bounds). Live-verified
|
|
64
|
+
with `tests/e2e/test_transports_e2e.py::test_e2e_i2v_start_end_frame_attach`
|
|
65
|
+
on `ffroliva` + `GFLOW_CLI_LOCALE=de-DE` (Chrome rendered pt-BR; both
|
|
66
|
+
non-EN). Closes [#63](https://github.com/ffroliva/gflow-cli/issues/63).
|
|
67
|
+
|
|
68
|
+
### Changed
|
|
69
|
+
|
|
70
|
+
- `gflow data media <id>` now searches across **all** profiles by default,
|
|
71
|
+
matching the cross-profile default of `gflow data list`. Pass
|
|
72
|
+
`--profile NAME` to disambiguate the rare case where the same Flow
|
|
73
|
+
media ID exists under multiple profiles (the command refuses to
|
|
74
|
+
guess and prints the list of candidate profiles, each annotated with
|
|
75
|
+
its `kind`). Closes
|
|
76
|
+
[#87](https://github.com/ffroliva/gflow-cli/issues/87).
|
|
77
|
+
|
|
78
|
+
### Fixed
|
|
79
|
+
|
|
80
|
+
- `gflow data list` no longer crashes with `no such table: assets` on a
|
|
81
|
+
missing or freshly-created catalog DB. The query path now routes through
|
|
82
|
+
`DataStore.open`, which applies schema migrations on first connect —
|
|
83
|
+
first-time users and anyone recovering from a wiped DB get an empty
|
|
84
|
+
table and exit 0 instead of a `DataStoreError`. Closes
|
|
85
|
+
[#88](https://github.com/ffroliva/gflow-cli/issues/88).
|
|
86
|
+
- `gflow auth list` no longer crashes with `UnicodeEncodeError` on Windows
|
|
87
|
+
consoles whose code page cannot encode the default-profile marker `●`
|
|
88
|
+
(cp1252 in PowerShell / cmd by default). The renderer now picks a glyph
|
|
89
|
+
safe for the active `sys.stdout.encoding` — `●` on UTF-8, ASCII `*` on
|
|
90
|
+
cp1252 / ascii / latin-1 / unknown. Closes [#82](https://github.com/ffroliva/gflow-cli/issues/82).
|
|
91
|
+
|
|
92
|
+
### Documentation
|
|
93
|
+
|
|
94
|
+
- `PLAN.md` refreshed to reflect develop state through v0.9.0 — marks Phase 6
|
|
95
|
+
(data layer) shipped via PR #58 + #78 + #81, Phase 7 Issue #24 Phase 2
|
|
96
|
+
shipped via PR #70, Phase B I2V/R2V shipped via PR #48, and resolves the
|
|
97
|
+
duplicate Phase 7 numbering (pluggable storage renumbered to Phase 8).
|
|
98
|
+
|
|
10
99
|
## [0.9.0] — 2026-05-25
|
|
11
100
|
|
|
12
101
|
> **Maturity & Visibility release.** Surfaces the SQLite catalog (PR #52/#58)
|
|
@@ -945,7 +1034,8 @@ shell-script template that branches on these codes.
|
|
|
945
1034
|
|
|
946
1035
|
First skeleton. Not functional end-to-end yet.
|
|
947
1036
|
|
|
948
|
-
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.9.
|
|
1037
|
+
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.9.1...HEAD
|
|
1038
|
+
[0.9.1]: https://github.com/ffroliva/gflow-cli/compare/v0.9.0...v0.9.1
|
|
949
1039
|
[0.9.0]: https://github.com/ffroliva/gflow-cli/compare/v0.8.1...v0.9.0
|
|
950
1040
|
[0.8.1]: https://github.com/ffroliva/gflow-cli/compare/v0.8.0...v0.8.1
|
|
951
1041
|
[0.8.0]: https://github.com/ffroliva/gflow-cli/compare/v0.7.0...v0.8.0
|
|
@@ -319,19 +319,76 @@ issue and not blocked by any code change in this repo.
|
|
|
319
319
|
|
|
320
320
|
- **Status:** Mitigated · **Severity:** Medium · **Tracking:** [issue #24](https://github.com/ffroliva/gflow-cli/issues/24)
|
|
321
321
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
322
|
+
Status stays *Mitigated* (not *Resolved*) because `--lang=en-US` is still
|
|
323
|
+
passed and `NEW_PROJECT_SELECTORS` / `SUBMIT_BUTTON_SELECTORS` tails still
|
|
324
|
+
carry English-text fallbacks; the icon-first leads cover the common path,
|
|
325
|
+
but the dependency only fully clears after a live e2e on a non-English
|
|
326
|
+
Chrome profile.
|
|
327
|
+
|
|
328
|
+
**Phase 2 progress (2026-05-25, develop / post-v0.8.1, unreleased):**
|
|
329
|
+
|
|
330
|
+
- **`ONBOARDING_SELECTORS` restructured** — replaced the original 9 English/PT-BR
|
|
331
|
+
text-only entries with a two-tier cascade:
|
|
332
|
+
1. `_ONBOARDING_STRUCTURAL_SELECTORS` (3 strict entries) — locale-free ARIA/ID
|
|
333
|
+
anchors: `button#L2AGLb` (Google Funding Choices SDK stable ID) plus exact
|
|
334
|
+
ARIA-label matches (`Accept all`, `I agree`). These are programmatic SDK
|
|
335
|
+
constants, not UI strings.
|
|
336
|
+
2. `_ONBOARDING_TEXT_SELECTORS` (~37 entries) — leads with two
|
|
337
|
+
case-insensitive ARIA-partial entries (`aria-label*='Accept' i` /
|
|
338
|
+
`*='Agree' i`) that catch many CMP dialogs (OneTrust, Cookiebot) whose
|
|
339
|
+
aria-label values stay in English even on non-EN pages, followed by
|
|
340
|
+
`:has-text()` selectors covering 14 locales: EN, PT, DE, ES, FR, IT, NL,
|
|
341
|
+
JA, ZH, KO, PL, RU, TR, ID. The ARIA-partial entries live in this tier
|
|
342
|
+
because English aria-label values are not guaranteed across every CMP.
|
|
343
|
+
3. `ONBOARDING_SELECTORS = (*_ONBOARDING_STRUCTURAL_SELECTORS, *_ONBOARDING_TEXT_SELECTORS)`
|
|
344
|
+
so structural entries are always tried first.
|
|
345
|
+
Cascade-ordering invariant is verified by `TestBypassOnboarding` in
|
|
346
|
+
`tests/api/transports/test_ui_automation.py`.
|
|
347
|
+
|
|
348
|
+
- **`_attach_frame` (I2V/R2V frame slots) flipped to structural-first** — was
|
|
349
|
+
English text-label first (`FRAME_SLOT_BY_LABEL`) with structural fallback; now
|
|
350
|
+
tries `FRAME_SLOTS_STRUCT` first, falls back to `FRAME_SLOT_BY_LABEL` only
|
|
351
|
+
when structural count is insufficient. Slot selection unit tests live in
|
|
352
|
+
`TestAttachFrameSlotSelection` (`tests/api/transports/test_ui_automation_video.py`).
|
|
353
|
+
|
|
354
|
+
**Correction (2026-05-26, issue #63):** PR #70's original
|
|
355
|
+
`FRAME_SLOTS_STRUCT = "div:has(> button:has(i.google-symbols:text-is('swap_horiz'))) > div[aria-haspopup='dialog']"`
|
|
356
|
+
matched **zero** elements on real Flow DOMs — the `swap_horiz` icon uses class
|
|
357
|
+
`material-icons` (NOT `google-symbols`) and the slots are `<div type="button">`,
|
|
358
|
+
not children of any `div > button` wrapper. Production I2V therefore relied on
|
|
359
|
+
the English-text fallback and silently broke on non-EN profiles. Discovered
|
|
360
|
+
via DOM probe + LIVE e2e on `ffroliva` (de-DE → pt-BR effective). Replaced
|
|
361
|
+
with `FRAME_SLOTS_STRUCT = "div[type='button'][aria-haspopup='dialog']"` (a
|
|
362
|
+
unique pattern in Flow's editor). Also added a `.first` fallback for the
|
|
363
|
+
End-frame case — after Start is attached, only one structural slot remains
|
|
364
|
+
and the prior `.nth(slot_index)` went out-of-bounds. Both fixes shipped
|
|
365
|
+
together via [#63](https://github.com/ffroliva/gflow-cli/issues/63).
|
|
366
|
+
|
|
367
|
+
- **`GFLOW_CLI_LOCALE`** — Playwright `locale=` env override from PR #51 remains
|
|
368
|
+
available (default `en-US`).
|
|
369
|
+
|
|
370
|
+
- **`--lang=en-US` dependency reduced** — `ONBOARDING_SELECTORS` and `_attach_frame`
|
|
371
|
+
no longer require it. The arg is still passed because removing it requires a
|
|
372
|
+
broader live-e2e sweep (I2V/R2V across multiple locales); it will be dropped
|
|
373
|
+
once that completes.
|
|
374
|
+
|
|
375
|
+
- **Live e2e on `de-DE` (2026-05-25)** — `GFLOW_CLI_LOCALE=de-DE` T2V on
|
|
376
|
+
`ffroliva` (Pro) completed in 70.9 s and returned `MEDIA_GENERATION_STATUS_SUCCESSFUL`
|
|
377
|
+
with a 3.1 MB 1280×720 H.264 mp4 (8 s clip). Confirms the structural-first
|
|
378
|
+
selectors and `GFLOW_CLI_LOCALE` env override work end-to-end on a locale
|
|
379
|
+
outside the original 9-entry English/PT-BR list.
|
|
380
|
+
|
|
381
|
+
- **Live I2V e2e on `de-DE` (2026-05-26, issue #63 closure)** —
|
|
382
|
+
`GFLOW_CLI_LOCALE=de-DE` I2V (Start + End frames) on `ffroliva` via
|
|
383
|
+
`tests/e2e/test_transports_e2e.py::test_e2e_i2v_start_end_frame_attach`
|
|
384
|
+
completed in 124 s and returned a terminal `SUCCESSFUL` `VideoResult` with a
|
|
385
|
+
downloaded mp4 carrying valid `ftyp` magic bytes. The test asserts on the
|
|
386
|
+
`ui_automation_video.frame_attached` structlog event for both Start and End,
|
|
387
|
+
proving the structural cascade resolved both slots without falling through
|
|
388
|
+
to the EN-text tier. Note: Chrome's UI rendered in pt-BR despite
|
|
389
|
+
`GFLOW_CLI_LOCALE=de-DE` (env affects Playwright's `Accept-Language`, not
|
|
390
|
+
Chrome's profile language) — both are non-EN so the test still verifies the
|
|
391
|
+
locale-leak fix.
|
|
335
392
|
|
|
336
393
|
**Earlier — Phase 7 multi-image-prompt work** addressed the count-tab selectors:
|
|
337
394
|
- `_COUNT_TAB_TEXT_RE = ^(1x|x[2-4])$` only matches the digit+x format Flow
|
|
@@ -339,21 +396,21 @@ issue and not blocked by any code change in this repo.
|
|
|
339
396
|
- `_set_count` falls back to positional `.nth(count - 1)` when the read-back
|
|
340
397
|
text is unrecognised — locale-invariant.
|
|
341
398
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
399
|
+
**Earlier — PR #48:**
|
|
400
|
+
- Added `--lang=en-US` Chromium launch arg; parts of `NEW_PROJECT_SELECTORS` /
|
|
401
|
+
`SUBMIT_BUTTON_SELECTORS` tails still match by English text (icon-first selectors
|
|
402
|
+
lead and cover the common path, so these are maintenance debt rather than
|
|
403
|
+
active blockers).
|
|
404
|
+
|
|
405
|
+
**Full resolution requires:** live e2e verification on a non-English Chrome profile
|
|
406
|
+
(`GFLOW_CLI_LOCALE=<non-EN>` + a non-English browser profile) to confirm no
|
|
407
|
+
regression, then removing `--lang=en-US`.
|
|
408
|
+
|
|
409
|
+
**Workaround:** with Phase 2 changes, most locales are handled automatically.
|
|
410
|
+
For locales outside the 14 covered by `_ONBOARDING_TEXT_SELECTORS`, ARIA-based
|
|
411
|
+
structural selectors fire first and cover Google's Funding Choices consent SDK.
|
|
412
|
+
For non-standard CMP dialogs not covered, prefer accounts whose Flow renders in
|
|
413
|
+
one of the 14 supported locales or in English.
|
|
357
414
|
|
|
358
415
|
---
|
|
359
416
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gflow-cli
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.1
|
|
4
4
|
Summary: Unofficial CLI for Google Flow — drive Veo image-to-video generations from the terminal.
|
|
5
5
|
Project-URL: Homepage, https://github.com/ffroliva/gflow-cli
|
|
6
6
|
Project-URL: Issues, https://github.com/ffroliva/gflow-cli/issues
|
|
@@ -158,7 +158,7 @@ gflow CLI → Provider (interchangeable) → Flow (ui_automation) / Mock (te
|
|
|
158
158
|
|
|
159
159
|
## Project status
|
|
160
160
|
|
|
161
|
-
**v0.9.
|
|
161
|
+
**v0.9.1 — alpha.** Image (T2I / I2I / upload) + Video T2V / I2V / R2V live end-to-end on `ui_automation`, with a video `--model` picker (5 Veo models) + `--duration` / `--count`. New in v0.9.1: hardened locale-invariant Flow selectors, fixed I2V start/end-frame attachment for non-English Chrome/Flow sessions, and safer first-run catalog behavior. Only video `batch` (manifest runner) is still queued for Phase B — use a shell for-loop until then ([USAGE](docs/USAGE.md#gflow-video-batch)). Full milestone history → [docs/PROJECT_STATUS.md](docs/PROJECT_STATUS.md). Changelog → [CHANGELOG.md](CHANGELOG.md). Where the project is heading → [ROADMAP.md](ROADMAP.md).
|
|
162
162
|
|
|
163
163
|
## License & legal
|
|
164
164
|
|