Skip to content

chore(release): v0.38.0 - #336

Merged
ffroliva merged 7 commits into
mainfrom
chore/release-v0.38.0
Jul 17, 2026
Merged

ffroliva merged 7 commits into
mainfrom
chore/release-v0.38.0

Conversation

@ffroliva

Copy link
Copy Markdown
Owner

Summary

Release PR bringing the v0.38.0 integration history onto main.

Test plan

  • /gflow:check green (hygiene, doc links, ruff, pyright 0/0/0)
  • Full-suite CI green on the release tree (develop @ b97a8ea)
  • Live e2e: t2i --ui-mode classic (agentic->classic recovery observed), i2i dedup run pair (reference_deduped_by_filename, zero re-uploads), t2v veo-fast SUCCESSFUL
  • Doc-review council: YELLOW/YELLOW/GREEN, all Tier 2 fixes applied
  • PR CI green incl. SonarCloud, then merge with --merge (never squash)

🤖 Generated with Claude Code

ffroliva added 7 commits July 17, 2026 07:33
…r S3776) (#331)

Extract cohesive private helpers to bring these under the S3776 threshold,
with zero behavior change (verified: pyright 0/0/0, 1202 scoped tests, and
an adversarial behavior-diff review):
- mcp/tools _enrich_image_refs -> _ref_meta_entry
- api/client _enter_setup -> _launch_persistent_context / _open_page_pool / _setup_transport
- tools/expander -> _retry_after_gemini_error
- movie_manifest _parse_scene -> _validate_scene_{framing,model,style_variant} + _scene_opt_field
- ui/app middleware __call__ -> _log_mcp_payload / _forward_logged_mcp_message

The remaining 14 S3776/S107 issues (live video-automation CC 62, daemon CC 45,
stateful browser mgmt, and Click CLI signatures) were accepted in SonarCloud
with justification — refactoring verified/essential-complexity code for the
metric is net-negative. See the 2026-07-17 production-readiness assessment.
…#332)

Replace the blind "click the Agent pill once and give up" recovery with a
clean, reusable, state-aware component. Flow's Agent toggle is a
button[aria-pressed]:has(span.content) whose aria-pressed IS the mode
(false=classic media, true=agent) — locale-invariant, unlike the button text
or the apps_spark_2 "Tools" icon (present in BOTH modes; a false forced-agentic
signal that caused spurious "not recoverable" aborts).

New leaf module `mode_control` (read_mode + ensure_media_mode): reads
aria-pressed, closes the expanded chat sidebar (X) first, then toggles OFF only
when actually on — never a blind click, idempotent, bounded loop.
`_dismiss_agent_affordances` now delegates to `ensure_media_mode`, so every
caller (image + video mode-switch, driver detection) gets the robust recovery.
(The classic→agentic direction already has the robust `_force_agent_mode`.)

Live-validated: `scripts/dev/spike_mode_roundtrip.py` drove a full
classic→agent→sidebar→close→toggle-off→classic cycle on real Flow, asserting
aria-pressed + crop_* at every step. Unit tests for the component + updated
_exit_agent_mode integration tests. Removed the now-dead _AGENT_* loop constants.

Recon: `scripts/dev/spike_mode_switch_agentic_to_classic.py` (apps_spark_2=Tools).
Unblocks #299/#314/#183/#174. Follow-up: adopt read_mode + drop apps_spark_2/tune
from AGENTIC_UI_INDICATORS (still a last-resort escalation signal today).
…upload (#314) (#334)

`_attach_references` uploaded every local ref, so a repeated ref piled up
duplicate library entries (the reporter's 8× son.jpg). Flow names an uploaded
file by its EXACT filename and the picker search filters on that name, so a
repeat ref can be attached by selecting the existing tile — no duplicate
upload, and without persisting or trusting any media UUID across runs.

New soft helper `_try_select_existing_by_filename`: syncs the picker to the
editor's project (the library is project-scoped, #287), searches the filename,
and matches the tile by its image ALT (= the exact filename, locale-invariant —
the option's accessible name also carries a localised "Image"/"Imagem" suffix,
so an exact name match misses). On a match it selects + includes; on a miss it
clears the filter and returns False so the caller uploads. Wired via a new
opt-in `prefer_existing` flag — image i2i opts in; R2V video keeps upload-only.

Live-verified on ffroliva (project 9d5b9a86, credit-free): a 2nd i2i of
`zzdedupprobe.png` logged `reference_deduped_by_filename`, ZERO `image_uploaded`,
and produced a real image (forced classic via --ui-mode). Dedup also fired in
the agentic cohort. 6 unit tests + spike_issue314_picker_filename_search.py.
* docs: add PR-triage autopilot design spec

Design for an hourly hermes-ops autopilot that autonomously runs
/gflow:pr-council-review against external contributor PRs, motivated by
PR #237 sitting unreviewed for hours with no automation to catch it.

* docs: harden PR-triage autopilot spec after adversarial review

Three independent fresh-agent reviews (security/ops/completeness) against
the first draft converged on the same core gap: unbounded retry on a
permanently-failing PR is an uncapped-cost DoS vector. Adds a fail_count/
FAILED_PERMANENT dead-letter mechanism, a concurrency lock, ledger
atomicity note, fresh-per-review container decision, a credential
boundary separating the sandbox from the posting token (dedicated bot
account), Stage-1 hardening to match the council's tool-scope/sandbox
restrictions, a per-PR Stage-1 volume cap, and a report-content
constraint against confused-deputy disclosure.

* docs(specs): add PR-triage autopilot implementation plan and document ops layout

* feat(autopilot): implement Stage 0 deterministic pre-filter and fixture evals

* chore(autopilot): check off Task 1 in checklists

* feat(skills): add Section 9 Autonomous Mode to pr-council-review skill

* chore(autopilot): check off Task 2 in checklists

* feat(autopilot): implement Dockerfile.triage, entrypoint.sh, and run_sandboxed_review.sh

* chore(autopilot): check off Task 3 in checklists

* feat(autopilot): implement main orchestrator loop pr_triage_autopilot.py and tests

* chore(autopilot): check off Task 4 in checklists

* docs(autopilot): create PR-Triage Autopilot operations runbook

* chore(autopilot): check off Task 5 and DoD in checklists, update CHANGELOG

* docs(spec): add engine seam + email notification addendum (#238)

Review engine becomes pluggable (council-claude default, ledger records
engine; council-multi-cli named as backlog behind the seam). Email joins
Telegram as a high-signal-only channel sent by the host orchestrator with
the credential never entering the sandbox. Companion spec in hermes-ops:
2026-07-10-autopilot-notifications-and-home-channel-design.md.

* docs(spec): live-validation ceiling — e2e/benchmark is the final human gate

The sandbox structurally cannot run the e2e suite or /gflow:benchmark
(restricted egress, no Flow auth, credit spend forbidden), so autonomous
GREEN is capped at static-green. Every GREEN report must end with a
mandatory "Next step — live validation" section: operator-run e2e +
benchmark is the final triage gate, run only when all else is green, and
expected to bounce PRs back to development. Spec + skill §9 kept in sync.

* feat(autopilot): pluggable review-engine seam (council-claude default)

* refactor(autopilot): engine-seam polish from review (fail-fast resolve, DEFAULT_ENGINE, tighter tests)

* feat(autopilot): high-signal email alerts via hermes-ops Resend notifier

* fix(autopilot): verdict allowlist, utf-8 pipe encoding, notifier-failure logging

* fix(autopilot): ledger-dedupe gate verdicts, cap error text in email

* docs(autopilot): document engine/email env + correct deploy mechanism
…ach helper (#335)

Follow-up from the /code-review + /ponytail-review (ultra) pass on #314:

- **Scroll fallback (correctness):** `_try_select_existing_by_filename` now scrolls
  the virtualised picker grid (`_scroll_picker_grid_until_rendered`, #287) when the
  match isn't in the initial DOM — an existing dup that's off-screen after a broad
  search is selected, not silently re-uploaded. (Matches `_select_existing_asset`;
  also mitigates a project-switch race where the grid re-renders.)
- **DRY (reuse):** extracted `_attach_selected_tile` — the tile-click → wait-hidden
  → else-include → verify block that was duplicated in `_select_existing_asset` and
  the filename path. Both now call it (surface/detail/screenshot/timeout as params,
  so the media-UUID path's telemetry is byte-identical; its tests confirm).
- **Contract clarity:** docstring now states a found-but-unattachable match RAISES
  (real UI failure surfaced, not a silent re-upload) and notes the exact-filename
  key misses names Flow sanitises.

New unit test for the scroll-fallback path; `_select_existing_asset`'s existing
tests pass unchanged (extraction behaviour-preserving). pyright 0/0/0, 306 transport
tests green. Live e2e re-verify pending.
@ffroliva
ffroliva merged commit 736a33b into main Jul 17, 2026
10 checks passed
@ffroliva
ffroliva deleted the chore/release-v0.38.0 branch July 17, 2026 19:36
15990166686ll-crypto pushed a commit to 15990166686ll-crypto/gflow-cli that referenced this pull request Aug 24, 2026

This branch was previously deployed

1 inactive deployment
pypi — 6b5aa911 Deployed Jul 17, 2026 by ffroliva via build-and-publish #50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant