feat(web): caption approval before FetLife email publish#53
Merged
Conversation
Allow web UI users to review, edit, and confirm AI-generated captions before publishing to FetLife via email. Previously the publish action re-ran caption generation from scratch, discarding the displayed caption. - Add caption_override parameter to WorkflowOrchestrator.execute() - Thread optional caption through PublishRequest, route, and service - Replace read-only caption div with editable textarea - Add live character counter (N/240) and "(edited)" indicator - Add inline confirmation modal before publish (XSS-safe, DOM API) - Normalize whitespace-only captions to None (falls through to AI) - Add 5 tests covering override, fallthrough, and sanitization Co-authored-by: Cursor <cursoragent@cursor.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.
Description
Allow web UI users to review, edit, and confirm AI-generated captions before publishing to FetLife via email. Previously, clicking "Publish" re-ran AI caption generation from scratch, discarding the caption the user had reviewed after "Analyze & Caption". The FetLife email was sent with a caption the user never approved.
Type of Change
Related Issue
Addresses user feedback: "cannot approve the caption needed to send emails to FetLife before publishing."
Changes Made
workflow.py: Addedcaption_overrideparameter toWorkflowOrchestrator.execute(). When provided (and non-whitespace), skips AI caption generation and uses the override. Logscaption_override_usedfor audit trail.models.py: Added optionalcaptionfield toPublishRequest(backward-compatible, defaults toNone).app.py: Route handler extracts and normalizesbody.caption(whitespace-only →None), passes through to service.service.py:publish_image()acceptscaption_overrideand forwards to orchestrator. Logs when override is received.index.html(CSS): Textarea styling, character counter, edited badge — all matching existing dark theme.index.html(HTML): Replaced read-only caption<div>with editable<textarea>, addedN / 240character counter and "(edited)" indicator.index.html(JS): UpdatedsetCaption()for textarea, addedupdateCaptionMeta()with live counter, added XSS-safe inline confirmation modal (showPublishConfirm()), updatedapiPublish()to send caption in POST body.test_workflow_feature_toggles.py: 5 new tests — override happy path, empty string fallthrough, whitespace-only fallthrough, sanitization byformat_caption, andNonepreserving default behavior. Enhanced_StubPublisherto capture received captions.test_web_app_additional.py/test_web_service.py: Updated stubs to accept newcaption_overrideparameter.Testing
Security Considerations
format_captionsanitization still enforced)textContentDOM API, notinnerHTML— XSS-safe)Checklist
Additional Notes
caption_overrideget the existing AI generation flow unchanged.isPlaceholdercheck), route handler (strip() or None), and workflow (caption_override.strip()check)._MAX_LEN["email"]incaptions.py. Server-sideformat_captionstill enforces the hard trim — the counter provides user feedback, not the enforcement.