Repository navigation
Conversation
Background sweeps check pending SES email senders and save the verified flag, so Channels and MCP reads see a verified sender without the user opening the verification UI. Senders whose verification was requested in the last hour are checked every minute, older ones up to 7 days every 5 minutes. A resolved SES VDM advisor finding marks the pending senders on its domain as requested again. SES status reads are batched per 100 senders and paced in background providers. Matching senders are row-locked while marked verified, and the first verified sender becomes the project's default when none exists. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Enabling a workflow whose email sender's domain is not verified yet now saves `waiting_for_domain` instead of `active`, behind `workflows-email-domain-wizard`. A waiting workflow does not trigger. - One enable rule in the HogFlow writes module (`enable`, `disable`), used by API create and PATCH with `status: active` and by `set_workflow_enabled`. It returns the usage events and the view sends them after commit. - `HogFlow` stores `enable_requested_at`, `enable_requested_by` and `went_live_at`; the API returns the two timestamps read-only. - Disable, archive and delete of a waiting workflow report how long it waited. - The workflows list and header show a "Waiting for domain" badge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the verify button or the background sweep verifies an email sender, every workflow waiting for that sender's domain goes `active` within seconds, as long as none of its other senders is still unverified. - `enable_waiting` in the HogFlow writes module locks each waiting row, skips it unless it still waits, and saves `active` with `went_live_at`. It returns `hog_flow_activated` with `activated_by: domain_verified`. It ignores the flag, so turning the flag off never strands a workflow. - The verification write calls the facade's `enable_waiting_workflows` inside its transaction. The facade schedules a task after commit that retries database errors 5 times with backoff, then logs an error and counts `workflows_enable_waiting_failed_total`. The task sends its events with `ph_scoped_capture`, credited to the person who enabled. - Edits to a waiting workflow validate as strictly as an activation and save in place. An edit that leaves no unverified sender takes it live. - Deleting an email sender that a waiting workflow uses is refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…main The workflow detail and every single-workflow write response now carry the workflow's unverified email senders (id and domain). The list endpoint leaves them out. With workflows-email-domain-wizard on, the header Enable and the list toggle ask the person to confirm when a sender's domain is not verified yet, and name the domains. Confirm sends the usual status: active, so the server saves waiting_for_domain. Cancel saves nothing. The list toggle loads the workflow's detail to read the senders. A workflow that went live after waiting shows a one-time "Started sending" notice. The dismissal is stored in the browser, keyed by workflow id and went_live_at. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The wizard stack does not carry the sender verification refresh the core builds on, so both sides rewrote the SES verify path and the verified write: - ses.py keeps the core's split into verify_email_domain and get_email_domain_verification (the sweep reuses one batched identity read), and builds its records with the wizard's build_email_domain_records. - email.py keeps the core's apply_verification for the sweep and the wizard's verify(on_domain_verified)/status(). verify() still stamps verification_requested_at when it does not succeed, and the wizard's _mark_domain_verified matches senders the way the core does (same domain, provider and MAIL FROM subdomain). - Both sides add FEATURE_FLAGS.WORKFLOWS_EMAIL_DOMAIN_WIZARD with the same line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A rotation sends from integrationIds when the list is set, so the sender check reads the same senders Node picks from. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Enable on the API, MCP and create paths share one step, and the go-live check after an edit runs only when no status is requested. Transactional email workflows skip the sender check inside that step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rkflows live The wizard's verify() and status poll write through _mark_domain_verified, which did not call enable_waiting_workflows, so a workflow waiting on the domain stayed waiting until the background sweep came by. The sweep's apply_verification now writes through the same function, so there is one writer of verified = true (ADR 0002) and it calls the facade inside its transaction. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…DNS is pending The wizard page's verifying step now shows a card: workflows that send from the domain can be turned on now and start sending once it is verified, with "Create the welcome email workflow" and "Go to workflows". The welcome action is shared with the ready step's next-workflow card. The card stays off the setup modal, so the guided onboarding and the broadcast flow that open it are unchanged, and off a stopped verification. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… state The merge converted SESIdentityStatus into the polling path's _SESIdentityState only to read its statuses. The verify path now reads SESIdentityStatus directly, so the conversion goes away. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
enable_waiting_workflows queues its task in an on-commit callback. When the broker refused the task, the error escaped the callback after the verification had committed, so email/verify, the wizard's status poll and the sweep failed for a domain that was already verified. The queue call now logs workflows.enable_waiting.failed and counts workflows_enable_waiting_failed_total, the same signal as a go-live that fails after its last retry. The wizard's send once verified card also uses LemonCard instead of a hand-built section. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Enable locks the sender rows it reads, so a verification that commits meanwhile waits for the waiting status and then finds the workflow. - Graph, email-step and publish edits run the same go-live check as a full save, and report its activation event. - A malformed email step reads as having no sender instead of failing the detail read. - The go-live task retries a failed worker reload like a database error, and a waited go-live sweeps parked timing steps like a re-enable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d and search A waiting workflow goes live by itself, so a realtime cohort it reads must not change under it, and search must still find it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ilter - The editor status bar shows Waiting for domain instead of Draft. - The list status filter has a Waiting for domain option. - The header Enable prompt stays open and loading until the save settles. - An enable that waits no longer reports workflow enabled on a later save. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
enable_waiting_workflows queued its task in an on-commit callback. When the broker refused the task, the error escaped the callback after the verification had committed, so email/verify and the sweep failed for a domain that was already verified. The queue call now logs workflows.enable_waiting.failed and counts workflows_enable_waiting_failed_total, the same signal as a go-live that fails after its last retry. Same fix as the wizard branch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e copy - Enable and verification lock sender rows ordered by id, so they never deadlock on a rotation. - A waited go-live sweeps timing steps after the whole batch, so a failed enqueue cannot stop the other workflows or drop their events. - The enable prompt cannot be cancelled while its save runs. - The cohort modal and the status bar copy say enabled and every domain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e events The workflows are already live when their timing sweeps are queued, so a failed enqueue is logged and the activation events still reach the sender. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merges spec/send-once-verified at 6a5872e into the wizard prompt branch. - posthog/models/integration/email.py: keeps one writer of verified = true, the wizard's _mark_domain_verified. It already locks senders ordered by id, which is the core's b4618a8 change to the deleted _mark_matching_senders_verified. - test_email_sender_verification.py: keeps the wizard's write parametrization of the queue-failure test and the core's database/redis parametrization of the task last-retry test. - The go-live queueing fix landed on both sides with the same shape and auto-merged to one queue_enable_waiting_workflows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The status bar names the sender domain state of the workflow and links to where the domain's verification shows: no domain configured, a domain that is not verified yet, and a workflow waiting for its domain. The header no longer repeats the waiting tag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tack Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… page No domain configured opens the email domain wizard. One pending domain opens its status page, where the DNS records' verification polls live. Several pending domains keep the channels list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An email step whose senders no longer exist has no domain to send from, so the status bar now says so once the integrations load. With the flag off, a waiting workflow keeps its sending-starts explanation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> # Conflicts: # products/workflows/frontend/Workflows/senderDomainNotice.ts
Silthus
added a commit
that referenced
this pull request
Oct 20, 2026
Silthus
added a commit
that referenced
this pull request
Oct 20, 2026
Silthus
added a commit
that referenced
this pull request
Oct 20, 2026
Silthus
added a commit
that referenced
this pull request
Oct 20, 2026
Silthus
added a commit
that referenced
this pull request
Oct 20, 2026
…less it has edits A field-by-field refresh kept the old save fence and the form's status, so the next save could conflict and a manual trigger stayed disabled. A saved workflow without unsaved changes now reloads in full. One with unsaved edits keeps them and refreshes on its next save or load. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ain setup was open Closing the setup checks whether the server saved the workflow meanwhile, as it does when a verified domain takes the workflow live. If so, the editor reconciles the way it does for an edit from another tab: a silent reload behind the syncing overlay while auto-save can flush, else the Reload or Keep mine banner. Enabling from the setup saves without that check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… save The check after the setup closes reads the save baseline once its request returns, and reconciles only a newer server copy, so a save of this editor that landed meanwhile is not mistaken for a change from the server. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…it events The check after the setup closes hands the server's copy to the same path as an edit from another tab. Its save queue holds the copy while a save of this editor runs and ignores the echo of that save, so a save that commits before its response lands is not mistaken for a change from the server. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Edit events can arrive out of order, so a held event is replaced only by one that is not older. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Silthus
changed the base branch from
feat/email-domain-wizard
to
feat/email-domain-wizard-suggestions
October 20, 2026 08:06
…main setup When the email domain setup opened from a workflow creates a sender, set it on every email step of the workflow that has no sender, and save at once so the setup can offer to enable the workflow. Steps that already have a sender keep it. The setup says which address the workflow now sends from, and the fill is tracked as a preselected sender. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fill notice belongs to the setup that made it, so opening or closing the setup resets it without its own reducer. The logic test now checks that the filled senders and the unsaved rename survive the save. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nted logic Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A save queued behind another one overwrote the shared edit version, so the first save's response treated the later edits as saved and reset the form without them. The sender fill from the domain setup queues behind an in-flight auto-save this way. Each save now carries the edit version it was dispatched with. A step that sends through a sender rotation also counts as having a sender, so the fill leaves it alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Silthus
added a commit
that referenced
this pull request
Oct 20, 2026
Silthus
added a commit
that referenced
this pull request
Oct 20, 2026
Silthus
added a commit
that referenced
this pull request
Oct 20, 2026
Silthus
added a commit
that referenced
this pull request
Oct 20, 2026
Silthus
added a commit
that referenced
this pull request
Oct 20, 2026
Silthus
added a commit
that referenced
this pull request
Oct 20, 2026
…ggestions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…izard Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The records step and the waiting page get a quiet menu that copies a link to the domain page for a teammate, or the records as plain text for a DNS owner outside PostHog. Each copy captures 'email domain records shared' with the method and step. The ready step shows no hand-off. Refs Silthus/personal#190 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On a Domain Connect host the records sit behind 'I'll add them myself', so a teammate opening the shared link saw the step without them. The link now carries records=shown, which reveals them without recording a setup method. Refs Silthus/personal#190 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs Silthus/personal#190 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 26, 2026
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.
Problem
waiting_for_domain, from send once verified) stays waiting when the wizard verifies the domain. The wizard's verify call and its status poll mark the senders verified without taking waiting workflows live. The background sweep checks only unverified senders, so it never picks the workflow up again.Stacked on #521 (
feat/email-domain-wizard-suggestions), the wizard's workflow suggestions, which sits on the email domain wizard stack tip #341. It also merges the send once verified core, #519 (branchspec/send-once-verified), last at4d367f40265, which refreshes a waiting workflow's status while its page is open. Landing order: the wizard stack, then #521, then PostHog#113091, then #519, then this PR. Once those land, this PR rebases to its own commits.Impact
Pays into the Workflows activation rate. A person who is waiting for DNS can turn a workflow on from the wizard, and it starts sending when the domain verifies, without a return visit.
Warning
🟡 Merge risk: medium · two-way door (merge-risk rubric)
workflows-email-domain-wizard. A revert restores the two writers.Changes
Counted over this PR's own commits (
534a795997b..e45577b8b82).7e5c7a089a2adds 1 production file (+4 −2) and 1 test file. The waiting page and the modal over the workflow add6194282515d..928cc853cce. The sender fill adds928cc853cce..07c48926720. The merge commits are described below; the latest are00601129b16ande21d433d578.The DNS records fold into one line while DNS is checked, the same summary as the last step: "4 of 8 settings in place at Cloudflare", with a spinner while checks run. Expanding it shows each record's live status and copy buttons. It opens by itself when checks stop with records missing.
The "While you wait" card offers the last step's first workflow choices from feat(workflows): offer data suggestions on the domain wizard's last step #521, under its message that workflows turned on now start sending once the domain is verified:
email-domain-verifying-*data-attrs, and its blockemail-domain-verifying-workflow-choices, so clicks on this page stay apart from the last step's.The editor's domain links open the wizard in a modal over the workflow, not a new tab, with the wizard's existing modal mode:
Opened from a workflow, the wizard offers the workflow's own next step in place of the suggestions. The modal says "For the workflow …".
activestatus through the existing enable path, so a workflow on a pending domain waits for it. It skips the Enable confirmation, because the button says what happens, and closes the modal.The waiting stage in an 1100px window
A sender created in the modal fills the workflow's empty sender. When the workflow's email step has no sender, the setup sets the sender it creates on every email step without one. A step that already has a sender keeps it.
email sender preselectedwithsurface: 'workflow'andreason: 'created_in_domain_setup', the event the editor already sends when it preselects a sender.A fresh workflow in a project with no email sender, after Set up a domain and Continue, at the waiting stage:
The same at 640px, and the entry point
After Enable and send once verified, the modal closes over the workflow, which now waits for its domain:
Earlier screens: the While you wait card at
e45577b8b82, and the links as new tabs ate8accd5a61aThe verifying step shows a "While you wait" card on the wizard page while DNS is pending. It says the person can turn on workflows that send from the domain now, and that they start sending once the domain is verified.
The editor's domain links open the wizard. The core's status bar notice gives each sender domain stage one link. On this stack:
/workflows/channels/email/new/workflows/channels/email/<id>, where the DNS records pollThe same stages in a 1100px window
EmailIntegration._mark_domain_verifiednow calls the workflows facade'senable_waiting_workflowsinside its transaction, as ADR 0002 requires of every writer ofverified = true.apply_verificationnow calls_mark_domain_verified, and the core's second writer is deleted. The one writer locks the senders on the same domain, provider and MAIL FROM subdomain, sets the default sender, and schedules the go-live task.workflows.enable_waiting.failedand countsworkflows_enable_waiting_failed_total, the signal a go-live already sends after its last retry. Before, the error failedemail/verify, the status poll and the sweep for a domain that was already verified. The core made the same fix, so the merge keeps onequeue_enable_waiting_workflows.Earlier screens: the While you wait card, before and after, at
e45577b8b82The merge commits
00601129b16brings in #521 at907d522a6de: the last step says "Your first sender" only for the project's first verified sender, and a new sender's name starts as the organization's name. It had one conflict, inReadyStep.tsx, where #521 renamedFirstSenderCardtoSenderCardand this PR had moved the records intoDnsRecordsSummary. The merge keeps this PR's step with #521'sSenderCard.e21d433d578brings in #519 at4d367f40265: while a workflow waits for its domain and its tab is visible, the editor checks its status every 10 seconds and shows it going live without a reload, keeping unsaved edits. It had two conflicts, inworkflowLogic.tsandworkflowLogic.sendOnceVerified.test.ts, where both sides added state, listeners and tests next to each other. The merge keeps both:ae8a6120f56brings in #521 atbcee93148d3, which this PR now sits on. It had one conflict, inNextWorkflowCard.tsx: the merge takes #521'sFirstWorkflowChoices.a549f43816ebrings in #521's fix for a long domain in the ready heading, cleanly.bb3934f5647brings in the core's verified sender rule, up toac56c64e64d: a step without a sender gets no notice when the project has a verified sender. It had two conflicts, insenderDomainNotice.tsand its test. The merge keeps the core's rule and this PR's wizard URLs, and the pending notice for a project's only pending domain links to that domain's page.b55373ebed9and9ad67d0d477bring in the core's move of the list's enable path to the generated client, up tob8a7c3c10fc. Both merged cleanly.4a2d7f61e00ande8accd5a61abring in the core's call to action polish, up tob233ec8ba71. The first merged cleanly. The second had one conflict insenderDomainNotice.ts: the merge keeps the core's new signature, which reads the existing senders, and this PR's wizard URL for "No domain configured".6ee3d98019bbrings in the core's review fixes, up to its reviewed head6a5872e04d9. It has two conflicts:email.py: the core's second writer stays deleted. Its last change locked senders ordered by id, which the one writer already does.test_email_sender_verification.py: both sides parametrized the queue-failure tests. The merge keeps this PR's three write paths and the core's database and redis errors.The broker fix that landed on both sides auto-merged to one implementation. No wizard code calls the names the core renamed.
534a795997b, the first merge: the wizard stack does not carry the sender verification refresh that the core builds on, so both sides rewrote the SES verify path and the verified write. The merge keeps:verify_email_domainandget_email_domain_verification, so the sweep reuses one batched SES read. The records come from the wizard'sbuild_email_domain_records.verification_requested_atstamp whenverify()does not succeed. The two Domain Connect chaos tests now compare the sender's config without that stamp, because each apply-url call asks SES to verify again.How did you test this code?
On head
e21d433d578, after the #521 and #519 merges:workflowLogic.sendOnceVerified.test.ts, "while the workflow waits for its domain"): a status check in flight while the domain setup closes and reloads the workflow. The server turned the workflow off in between, and the check's older answer says active. The editor keeps the reloaded copy. With the staleness guard removed, the test fails.AgentPromptButton.tsxandQuillTicketsList.tsx.e21d433d578, in Chromium through the app's URL, with the demo DNS and fake email backend:waiting_for_domain.On head
07c48926720, after the sender fill:WorkflowSenderDomainSetupModal.test.tsx): a fresh workflow in a project with no sender. It clicks Set up a domain, types the domain and continues. The fill save carries the new sender on the empty step and no status. At the waiting stage the card shows the sender line and "Enable and send once verified". The enable savesactive. The test failed before the fill: nothing was saved.workflowLogic.sendOnceVerified.test.ts, "a sender created in the domain setup"): only empty steps fill, a chosen sender and a sender rotation stay, and an unsaved rename survives the save. A fill queued behind an in-flight save keeps the sender when its own save fails. That case failed before07c48926720.AgentPromptButton.tsxandQuillTicketsList.tsx.status: active, and the status bar then read "Waiting for domain".On head
928cc853cce, after the waiting page and modal work:EmailDomainScene.test.tsx): the records fold while DNS is checked and expand on click; the suggestions show on the waiting page under theemail-domain-verifying-*data-attrs, and the shown event fires once per page.WorkflowSenderDomainSetupModal.test.tsx, new): clicks the status bar's Check domain status and follows the modal. Enable savesactiveand closes; Back only closes; the verified stage offers Enable workflow; a missing sender, a viewer and an already waiting workflow get no Enable.workflowLogic.sendOnceVerified.test.ts): the notice carries the domain's sender id; closing reloads the integrations; a server change while open reloads behind the syncing overlay, asks first over edits auto-save cannot flush, and does nothing when the server copy is unchanged; this editor's own save is never read as a server change, whether the check returns before or after the save response.resourceSaveQueue.test.ts): an older edit event held during a save no longer replaces a newer one.Verifying with suggestionsand a scratch story of the whole app with the modal over a workflow, at 1600px and an 1100px window. The full set is in proof storage.On head
bb3934f5647, after the verified sender rule merge:Workflows/workflowLogic*,workflowsLogic,Channels/EmailDomain). The stage cases assert each link, including the project with only a pending domain (/workflows/channels/email/7).fleet proof gatepasses.On head
9ad67d0d477, after the generated client merges:workflowsLogicandworkflowLogic.sendOnceVerifiedsuites pass, including the core's new current-environment case.b8a7c3c10fc, then nothing.fleet proof gatepasses.On head
e8accd5a61a, after the call to action merges:workflowLogic.sendOnceVerified.test.tsasserts the link of each stage: the wizard start for no sender and for a deleted sender, the domain's page for one pending domain, the Channels list for two. The three wizard URL cases failed before7e5c7a089a2.Workflows/workflowLogic*,workflowsLogic,Channels/EmailDomain).@posthog/quilland are gone after a rebuild.Email domain setupstories.fleet proof gatepasses.On head
6ee3d98019b, after the second merge:test_email.py,test_integration.py,test_domain_connect.py,products/workflows/backend).Channels/EmailDomain,Workflows).@posthog/quillmodule resolution inproducts/conversationsfrom the local install.hogli product:lint workflowspass. The strict pre-push preflight had 0 failures.fleet proof gatepasses.On head
e45577b8b824cb862087dafca8270bb561ac746b:test_verifying_a_sender_takes_its_waiting_workflows_livegains two cases,wizard_verifyandwizard_status_poll, beside the sweep cases. Each case runs the on-commit callbacks and the Celery task, then reads the workflow over the API. Both cases failed on the merge commit (the workflow stayedwaiting_for_domain) and pass now.test_a_go_live_that_cannot_be_queued_keeps_the_verificationmakes the broker refuse the task for the sweep and both wizard writes. It asserts that the sender stays verified and that the failure logs and counts. It raised on8d33d7bf5a4and passes now.EmailDomainScene.test.tsxchecks that the welcome action shows while the step checks DNS and is absent after a stopped verification. The first check failed without the card.waiting_for_domain.POST email/verifythen returnedsuccess, andGET email/status?refresh=truereturnedverified. On both paths the workflow then readactivewithwent_live_atset.EmailDomainJest suites pass.AgentPromptButton.tsxandQuillTicketsList.tsx.tycheck and the pre-push type check pass.Email domain setupStorybook stories. The page has no horizontal overflow at 520px or at 1440px.Test rationale: The seam 2 cases catch a verify or status path that writes
verified = truewithout the facade call, which the sweep cases cannot catch. The queue-failure case catches a broker error that fails a request after the verification committed. The scene check catches the card disappearing from the verifying step, or showing on a stopped verification. No logic test covers the card, because it has no state.Proofs per the QA swarm's proof rules:
e45577b, see above. It still holds, because the second merge changes no wizard path. The core ran its own live run at6a5872e04d9.Release status
The card and the wizard sit behind
workflows-email-domain-wizard. The one-writer change inEmailIntegrationis not flag-gated. It changes no behavior for senders without waiting workflows.Docs update
None.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: Claude Code in T3 Code, Claude Opus 5.5 (high). Design pass by GPT-6.1 Sol (high).
tdd,writing-tests,writing-ui-components,writing-user-facing-copy,writing-pr-descriptions,pr-description,merge-risk,adopting-generated-api-types, the QA swarm design pass.8d33d7bf5a4.e45577b8b82: a broker error after commit failed verified requests (major), and the card did not useLemonCard(minor). The final read found nothing.Email domain setupgain the card, so their visual review baselines need approval.Decisions
verified = trueapply_verificationgoes through the wizard's_mark_domain_verified; alternative was a facade call in eachverification_requested_aton Domain Connect apply-urlverified = truesurvives the second merge_mark_domain_verified; the core's second writer stays deleted, and its id-ordered lock is already in the one writerqueue_enable_waiting_workflows, with the core'sRedisErrorretrye45577b; the merge changes no wizard pathactivethrough the existing path and skips the Enable confirmationemail-domain-verifying-*data-attrs; the suggestions' shown event fires once per page with the same surfaceemail sender preselectedwithreason: 'created_in_domain_setup', the event the editor sends for a preselected senderSenderCardInvolvement: no grilling rounds, no prototypes; design passes, review rounds and a final read after every fix (GPT-6.1 Sol), six final reads for the waiting page and modal; for the sender fill, a design pass, one review round and a final read; a final read of the #521 and #519 merges; renders and live runs captured.
🤖 Generated with Claude Code