Skip to content

feat(ai-create): review the generated copy before spending image credits#191

Open
dantaspaulo wants to merge 1 commit into
trypostit:mainfrom
dantaspaulo:feat/ai-draft-review
Open

feat(ai-create): review the generated copy before spending image credits#191
dantaspaulo wants to merge 1 commit into
trypostit:mainfrom
dantaspaulo:feat/ai-draft-review

Conversation

@dantaspaulo

Copy link
Copy Markdown
Contributor

Problem

AI creation is one shot: the wizard sends the prompt and StreamPostCreation writes the copy AND renders the images in a single pass. The user only sees the result once everything has been generated and the post already exists.

That is expensive and frustrating. Images are the costly part of a generation, so a weak headline, an off-tone caption, or a carousel whose slides arrived in the wrong order all cost a full image render before the user can react — and fixing it means starting over and paying again.

Change

Generation is split into two phases, with a review step in between.

Phase A (PreparePostContent) writes only the structured text — the same generator and humanizer as today, no images — and stores it on a new AiPostDraft.

The review screen shows that text as editable blocks: headline, body, caption, photo keywords, and for carousels one card per slide, reorderable by dragging. Edits autosave (debounced) so nothing is lost.

Phase B reuses StreamPostCreation with the approved structure, so it skips text generation and renders images from exactly what the user signed off on.

The one-shot path is untouched: StreamPostCreation without preparedStructured behaves exactly as before.

How

  • PostContentComposer — the "generate, then humanize" step lifted out of StreamPostCreation verbatim so both phases share one implementation. This is a pure extraction: no behaviour change.
  • AiPostDraft + DraftStatus (preparing/ready/generating/completed/failed) hold the draft between phases. generate refuses a draft that is not ready, so a double click or a re-POST cannot create a duplicate post or bill images twice.
  • PostContentPrepared broadcasts on user.{id}.ai-draft.{draftId} when the text lands. The review screen also polls every 4s, so a dropped websocket cannot strand the user on the skeleton.
  • creationStatus gives the loading screen the same polling fallback for phase B.

Tests

15 tests covering the flow end to end: draft creation and job dispatch, the cross-workspace social account guard, rendering and authorization of the review screen, generate persisting the reviewed structure and dispatching phase B, the replay guard, autosave (persists while ready, no-op otherwise), validation, and PreparePostContent marking the draft ready while preserving the fields the humanizer does not return.

The full suite passes locally (2638 tests), Pint is clean, and ESLint passes on the touched frontend files.

Notes for review

  • Translations: en and pt-BR are written properly; the other 13 locales carry the English strings as an untranslated fallback so LocalizationParityTest passes. Happy to drop them to placeholders or take translations from you if you prefer.
  • I did not run Prettier over AiPostWizard.vue — it does not match printWidth: 80 on main today, and reformatting it would have buried the two-line change in noise. The two new components are formatted.
  • Whether the review step should be optional (a wizard toggle or a workspace setting) rather than always-on is a product call — happy to put it behind a flag if you would rather not change the default flow.

## Problem

AI creation is one shot: the wizard sends the prompt and the job writes the
copy AND renders the images in a single pass. The user only sees the result
once everything has been generated and the post exists.

That is expensive and frustrating. Images are the costly part of a
generation, so a weak headline, an off-tone caption or a carousel whose
slides arrived in the wrong order all cost a full image render before the
user can react — and fixing it means starting over and paying again.

## Change

Generation is split into two phases with a review step in between.

**Phase A** (`PreparePostContent`) writes only the structured text — the same
generator and humanizer as before, no images — and stores it on a new
`AiPostDraft`. **The review screen** shows that text as editable blocks:
headline, body, caption, photo keywords, and for carousels a card per slide
that can be reordered by dragging. Edits autosave. **Phase B** reuses
`StreamPostCreation` with the approved structure, so it skips text generation
and renders the images from exactly what the user signed off on.

Nothing about the one-shot path changes: `StreamPostCreation` without
`preparedStructured` behaves exactly as before.

## How

- `PostContentComposer` — the "generate then humanize" step extracted from
  `StreamPostCreation` verbatim, so both phases share one implementation.
  Behaviour is unchanged; this is a pure extraction.
- `AiPostDraft` + `DraftStatus` (`preparing/ready/generating/completed/failed`)
  hold the draft between phases. `generate` refuses a draft that is not
  `ready`, so a double click cannot create a duplicate post or bill images twice.
- `PostContentPrepared` broadcasts on `user.{id}.ai-draft.{draftId}` when the
  text lands; the review screen also polls every 4s so a dropped websocket
  cannot strand the user on the skeleton.
- `creationStatus` gives the loading screen the same fallback for phase B.

## Tests

15 tests covering the flow end to end: draft creation and job dispatch, the
cross-workspace social account guard, rendering and authorization of the
review screen, generate persisting the reviewed structure and dispatching
phase B, the replay guard, autosave (persists while `ready`, no-op otherwise),
validation, and `PreparePostContent` marking the draft ready while preserving
the fields the humanizer does not return.

The full suite passes (2638 tests).
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