Repository navigation
feat: character-create flow recorder + #153 locale fix - #158
Merged
Merged
Conversation
…TH-FIXES) Full grounded LLM council reviewed the plan against real source. Verdict GO-WITH-FIXES: architecture sound (single client-owned context; seam faithful; concurrency=1 -> one webm). Adds a council-revision addendum (authoritative) and a new Task 0 (fix #153 locale normalization, land-first). MUST-FIX baked in: Settings import path, orphaned channel_for_profile import, locale/#153. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
character_editor_url interpolated the locale verbatim, so the genuine CLI default "en-US" produced /fx/en-US/... which 404s the Flow character editor (only the short primary subtag is a valid segment). Reduce the tag to its lower-cased primary subtag (en-US -> en, pt-BR -> pt); short inputs pass through unchanged. Lets the tool stay language-agnostic with the real default locale. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-preserving) Extract the inline launch_persistent_context(**kwargs) call in FlowApiClient._enter_setup into an overridable _persistent_context_kwargs() method, so a dev-scoped recording subclass can augment the launch (add record_video_dir) without any recording concern living in core. The returned dict is value-for-value identical to the previous inline call. Promote `from gflow_cli.browser_manager import channel_for_profile` to module scope (browser_manager imports only gflow_cli.errors -> no cycle) and drop the now-orphaned function-local import (would have tripped ruff F401). Tests: a pin test fixes the seam's contract, and a call-site routing test asserts __aenter__ consults the seam exactly once (a re-inlined dict would drop it to 0 -- the pin test alone can't catch that). pyright src 0, 32 client tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…seam scripts/dev/_recording_client.py subclasses FlowApiClient and overrides ONLY _persistent_context_kwargs() to inject Playwright record_video_dir/record_video_size. No recording concern lives in core; the subclass is never imported by the package. Test asserts the recording kwargs are injected and the base kwargs are preserved. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
scripts/dev/record_flow_capture.py drives the genuine character_create saga through RecordingFlowApiClient and transcodes the captured .webm to .mp4. Free: character/image generation costs no credits. Council hardening folded in: - Settings imported from gflow_cli.config (MUST-FIX); built after the env vars. - Isolates BOTH the data store (GFLOW_CLI_DB_PATH) and the image output dir (GFLOW_CLI_OUTPUT_DIR) to throwaway temp dirs; forces GFLOW_CLI_CONCURRENCY=1. - Asserts EXACTLY ONE .webm is produced (refuses to guess otherwise). - Image-not-video guard: captures character_create structlog events and requires completed + a face event, fails on a failure event (refs=1 alone is insufficient). - recorder.close() in finally; ffmpeg-absent transcode falls back to the raw webm. Wiring tests cover the guard, the ffmpeg fallback, and argparse dispatch (no browser). Live verification (refs=1 + real footage) is a separate gated run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…play The recorder now types the name into the editor's name input (after the real character_create completes, still recording) so the promo video shows the name. Display-only: the editor title is decoupled from displayName (#151) and won't persist, which is irrelevant to the video. Located language-agnostically (tag the topmost editable text input structurally, proven by the #151 recon spikes) with a React native-setter fallback; degrades gracefully if the input isn't found. Adds a --name flag (default "Marina"). Live-verified on promo-denon82: the 36.7s capture shows "Marina" in the name field AND the generated face in the hero canvas (image/free). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ustness) Council branch-review follow-ups (all SHOULD-FIX / cheap NITs): - test_client.py: the routing test now asserts launch_persistent_context was invoked WITH the seam's exact dict (call_args.kwargs == seam output), not just that the seam was consulted — closing the behavior-preservation guard gap. - record_flow_capture.py _run: restore os.environ + rmtree the throwaway isolation dir in a finally (reentrant, no leaked catalog.db); pre-bind `cap`; type into client._pages[0] instead of the deprecated _page alias. - _recording_client.py: derive record_video_size from the base viewport (drop the parallel _VIDEO_SIZE constant so it can't desync). - routes.character_editor_url: fall back to "en" for a degenerate/empty locale (no double-slash URL) + test. - _FIND_NAME_INPUT_JS: clear any prior data-gflow-title tag (idempotent). pyright src 0, ruff clean, 46 affected tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t alias The new _persistent_context_kwargs() seam added a dict[str, Any] annotation that gave the pre-existing S1192 duplicated-literal smell a new-code location, failing PR #158's new_maintainability_rating gate. Define a single module-level `JsonObject = dict[str, Any]` alias (matching the data.models convention) and use it throughout client.py, so the literal appears exactly once. Annotations only — behavior unchanged (pyright src 0, 666 tests green). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
kittinan
pushed a commit
to kittinan/gflow-cli
that referenced
this pull request
Jun 6, 2026
…ased] The character-editor URL now normalizes BCP-47 locales to the short Flow segment (en-US -> en), fixing the 404 on the genuine default locale. Shipped in ffroliva#158. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
15990166686ll-crypto
pushed a commit
to 15990166686ll-crypto/gflow-cli
that referenced
this pull request
Aug 24, 2026
…t alias The new _persistent_context_kwargs() seam added a dict[str, Any] annotation that gave the pre-existing S1192 duplicated-literal smell a new-code location, failing PR ffroliva#158's new_maintainability_rating gate. Define a single module-level `JsonObject = dict[str, Any]` alias (matching the data.models convention) and use it throughout client.py, so the literal appears exactly once. Annotations only — behavior unchanged (pyright src 0, 666 tests green). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
15990166686ll-crypto
pushed a commit
to 15990166686ll-crypto/gflow-cli
that referenced
this pull request
Aug 24, 2026
…recording feat: character-create flow recorder + ffroliva#153 locale fix
15990166686ll-crypto
pushed a commit
to 15990166686ll-crypto/gflow-cli
that referenced
this pull request
Aug 24, 2026
…ased] The character-editor URL now normalizes BCP-47 locales to the short Flow segment (en-US -> en), fixing the 404 on the genuine default locale. Shipped in ffroliva#158. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes gflow's real
character createflow recordable as a browser-only video (for thegflow-cli-remotioncharacter promo), with the recording concern kept entirely out of core. Bundles a real production bug fix found along the way.Production changes (src/)
routes.character_editor_urlinterpolated the locale verbatim, so the genuine CLI defaulten-USproduced/fx/en-US/…which 404s the Flow character editor. Now normalizes a BCP-47 tag to its short Flow URL segment (en-US → en,pt-BR → pt), with anenfallback for degenerate input. Language-agnostic.launch_persistent_context(**kwargs)call into an overridable_persistent_context_kwargs()seam (value-for-value behavior-preserving), so dev tooling can augment the launch without any recording concern in core.channel_for_profilepromoted to a module-scope import.Dev tooling (scripts/dev/, NOT in the package)
RecordingFlowApiClient— subclasses the client and overrides only the seam to add Playwrightrecord_video_dir(size tracks the viewport).record_flow_capture.py— drives the genuinecharacter_createsaga through the recording client, then transcodes the.webmto.mp4. Isolates the DB and the image output dir to throwaway temp dirs, forcesconcurrency=1(exactly one webm), guards image-not-video viacharacter_createstructlog events, and types the name into the editor for on-screen display (display-only; the editor title is decoupled fromdisplayNameper fix(character): editor title shows "Untitled" — name box is decoupled from entityInfo.displayName #151).Process
Full grounded plan-council (verdict GO-WITH-FIXES — all MUST-FIX applied) → TDD per task → grounded branch-review council. Image generation is free (only video spends credits).
Live verification (promo-denon82, free)
Real headed run produced a 36.7 s / 1280×720 mp4 showing the genuine character editor: "Marina" typed in the name field + the generated face in the hero canvas.
character listshows the created character withrefs=1(a face was generated).#153confirmed live:--locale en-US→/fx/en/loaded with no 404.Test plan
pyright src0 errorstests/api+tests/devgreen locally (664+); CI runs the full matrixRefs #153. Feeds the
gflow-cli-remotioncharacter promo (PR #1).🤖 Generated with Claude Code