Repository navigation
Conversation
…once it verifies Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…once it verifies Behind workflows-email-domain-wizard, turning on a workflow whose email sender is not verified saves waiting_for_domain instead of active. When the domain verifies, a background task takes each waiting workflow live and sends hog_flow_activated with activated_by domain_verified. Go-live never checks the flag. Adds enable_requested_at, enable_requested_by and went_live_at to HogFlow (migration 0039). Refs Silthus/personal#195 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… fails enable_waiting yields each workflow as it commits, after its timing sweep, and the task sends that workflow's activation event before it moves on. A retry skips workflows that are live already, so their events can no longer be lost when a later workflow raises. Refs Silthus/personal#195 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🤖 CI report✅ Complexity (TypeScript) — cleanCyclomatic complexity above the limit in changed typescript files (10 for production files, 15 for test files). Warn only: worth simplifying when you next touch these functions. ✅ Comment density — 3% of added code lines are comments (23 of 797)This section warns when comments are more than 3% of the code lines a PR adds, and alerts above 6%. Before agent-assisted PRs, the typical share was about 2%. Only full-line comments count. Docstrings, generated files, snapshots, migrations, and workflow files are left out. Comments that restate the code, record how the change came about, or narrate the next line add noise for the next reader. Keep the comments that explain a reason the code cannot show, and remove the rest. See Files with the most added comment lines:
This check does not block merging. It updates on every push and clears when the share drops. ✅ Bundle size — no changeUncompressed size of every built Total: 76.88 MiB · no change No file changed by more than 1000 B. Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report ✅ Eager graph — within budgetHow much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy
🟢 Largest files eagerly shipped from
|
| Size | File |
|---|---|
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 24.6 KiB | ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js |
| 6.3 KiB | ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js |
| 4.7 KiB | ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js |
| 4.0 KiB | ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js |
| 1.7 KiB | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.6 KiB | src/lib/utils/bootTiming.ts |
| 1.6 KiB | src/index.tsx |
| 1.2 KiB | src/RootErrorBoundary.tsx |
| 949 B | src/scenes/ChunkLoadErrorBoundary.tsx |
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
| Size | File |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 217.5 KiB | ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 100.8 KiB | src/products.tsx |
| 86.1 KiB | src/lib/api.ts |
| 68.2 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 41.9 KiB | ../node_modules/.pnpm/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js |
| 36.4 KiB | ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js |
| 27.0 KiB | ../node_modules/.pnpm/tailwind-merge@2.2.2/node_modules/tailwind-merge/dist/bundle-mjs.mjs |
| 24.6 KiB | ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 KiB | ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 100.8 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
| 92.5 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 86.1 KiB | src/lib/api.ts |
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
| Size | File |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 KiB | ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 144.1 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 100.8 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
| 92.5 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
| Size | File |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 KiB | ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 100.8 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
| 92.5 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 86.1 KiB | src/lib/api.ts |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx
| Size | File |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 KiB | ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 144.1 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 100.8 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
| 92.5 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
Largest files eagerly shipped from src/scenes/activity/explore/EventsScene.tsx
| Size | File |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 KiB | ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 144.1 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 100.8 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
| 92.5 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
Largest files eagerly shipped from src/scenes/web-analytics/WebAnalyticsScene.tsx
| Size | File |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 KiB | ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 182.9 KiB | src/queries/validators.js |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 144.1 KiB | ../packages/quill/packages/primitives/dist/index.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 100.8 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
| Size | File |
|---|---|
| 322.9 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 316.1 KiB | ../node_modules/.pnpm/posthog-js@1.438.23_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/rrweb.js |
| 286.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 239.9 KiB | ../packages/quill/packages/quill/dist/index.js |
| 217.5 KiB | ../node_modules/.pnpm/@posthog+icons@0.39.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 153.8 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 100.8 KiB | src/products.tsx |
| 94.5 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
| 92.5 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of PostHog#32479
✅ Toolbar bundle — eager 2.29 MiB within budget
What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.
| Metric | Size | Δ vs base | Budget |
|---|---|---|---|
| Eager (shipped) entry + static imports |
2.29 MiB · 18 files | no change | ████░░░░░░ 40.1% of 5.72 MiB |
| Deferred (lazy) | 2.11 MiB · 40 files | no change | n/a — loads on demand |
Loader dist/toolbar.js |
1.2 KiB | no change | █░░░░░░░░░ 6.0% of 19.5 KiB |
Largest eagerly-shipped chunks
| Size | File |
|---|---|
| 904.9 KiB | dist/toolbar/toolbar-app-PJL3ZOG5.css |
| 694.7 KiB | dist/toolbar/chunk-chunk-S67E62V7.js |
| 259.9 KiB | dist/toolbar/chunk-chunk-LBUEMA4R.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-FDH2IBXT.js |
| 130.4 KiB | dist/toolbar/chunk-chunk-RZCYPLTY.js |
| 74.8 KiB | dist/toolbar/toolbar-app-U2PZEED2.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-TSAL54PB.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-3Y7AY6NT.js |
| 21.7 KiB | dist/toolbar/chunk-chunk-WUPVVGIN.js |
| 6.8 KiB | dist/toolbar/chunk-chunk-DV7IWQNF.js |
Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile
✅ Dist folder size — 🔺 +6.4 KiB (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 968.92 MiB · 🔺 +6.4 KiB (+0.0%)
ℹ️ MCP UI apps size — 34 app(s), 27969.1 KB JS
Built size of each MCP UI app (main.js + styles.css).
| App | JS | CSS |
|---|---|---|
| debug | 844.3 KB | 209.1 KB |
| action | 767.7 KB | 209.1 KB |
| action-list | 835.3 KB | 209.1 KB |
| cohort | 766.7 KB | 209.1 KB |
| cohort-list | 834.3 KB | 209.1 KB |
| email-template | 766.6 KB | 209.1 KB |
| error-details | 771.6 KB | 209.1 KB |
| error-issue | 768.9 KB | 209.1 KB |
| error-issue-list | 836.7 KB | 209.1 KB |
| experiment | 832.4 KB | 209.1 KB |
| experiment-list | 836.1 KB | 209.1 KB |
| experiment-results | 834.9 KB | 209.1 KB |
| feature-flag | 834.7 KB | 209.1 KB |
| feature-flag-list | 838.4 KB | 209.1 KB |
| feature-flag-testing | 770.0 KB | 209.1 KB |
| inline-scan | 767.2 KB | 209.1 KB |
| insight-actors | 833.8 KB | 209.1 KB |
| llm-costs | 831.1 KB | 209.1 KB |
| session-recording | 768.9 KB | 209.1 KB |
| survey | 768.3 KB | 209.1 KB |
| survey-global-stats | 831.1 KB | 209.1 KB |
| survey-list | 836.0 KB | 209.1 KB |
| survey-stats | 831.1 KB | 209.1 KB |
| trace-span | 767.1 KB | 209.1 KB |
| trace-span-list | 835.2 KB | 209.1 KB |
| vision-observation-list | 834.4 KB | 209.1 KB |
| workflow | 767.0 KB | 209.1 KB |
| workflow-list | 834.7 KB | 209.1 KB |
| workflow-setup-status | 766.7 KB | 209.1 KB |
| query-results | 1086.5 KB | 209.1 KB |
| render-ui | 1162.4 KB | 209.1 KB |
| visual-review-snapshots | 771.6 KB | 209.1 KB |
| workflow-data-suggestions | 769.4 KB | 209.1 KB |
| workflow-sending-rules | 768.0 KB | 209.1 KB |
… broken - Verification reloads the senders on workers before it queues the go-live, so a workflow never goes live while workers still hold its sender as unverified. - A lookup failure while sending the go-live event no longer retries the task, which would skip the workflow that is live already and drop its event. - An edit to a waiting workflow checks its senders again, so switching to a verified sender takes it live. - The integration delete guard counts waiting workflows, so a sender a waiting workflow uses cannot be deleted before the workflow goes live. Refs Silthus/personal#195 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rkflow live Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ing workflow live Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Enabling an archived workflow through the API or MCP returned 200 and left it archived, while the base enabled it. It now waits for an unverified sender or goes live, like enabling a draft. Refs Silthus/personal#195 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the reload of verified senders on the workers failed, waiting workflows still went live at once, while workers could hold the sender as unverified for up to five minutes and fail its sends. The go-live now waits past that cache. Enabling an archived workflow now also reports hog_flow_activated, like a draft. Refs Silthus/personal#195 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Problem
A project whose email domain is still verifying cannot turn on a workflow that sends from it and have it start on its own once the domain verifies. Today Enable either goes live with an unverified sender or the person has to come back later and turn it on.
This is the first slice of "send once verified" (Silthus/personal#195): an agent or API caller can already see and rely on it, before any UI exists.
Impact: pays into workflow activation. It adds the event for a waiting workflow that went live after verification (
hog_flow_activatedwithactivated_by: domain_verified). The event for a workflow turned on while it waits follows in the next slice.Caution
🔴 Merge risk: high · one-way door (merge-risk rubric)
0039onHogFlowand a newwaiting_for_domainstatus in the API and MCP contract. Waiting workflows go live by themselves and send real email once their domain verifies.workflows-email-domain-wizardon. Flag off, Enable behaves as on master. Node loads onlystatus='active'flows, so a waiting workflow never runs.nodejs/line (hogflow.tsstatus enum) so upstream's lane check passes. Once feat(workflows): let the node hog flow type hold a waiting for domain status #617 merges, this diff againstmasterhas nonodejs/change.Changes
PATCH status=activeor a create asactivesaveswaiting_for_domainwhen an email step sends from an unverified sender. A rotation waits for any unverified member. MCPworkflows-enablePATCHes, so it returns the same status.EmailIntegration.apply_verificationqueuesenable_waiting_workflows_taskon commit. The task takes each waiting workflow live once none of its senders is unverified, and ignores the flag.hog_flow_activated(activated_by: domain_verified) right after each workflow goes live, credited to the person who enabled it. A retry after a later failure cannot drop it.enable_requested_at,went_live_at.enable_requested_byis stored for event credit./graph, the email edit, and publish).hog_flow_activated(activated_by: user), so enabling an archived workflow counts too.active, orwaiting_for_domainwith an unverified sender. Before, it returned 200 and stayed archived.waiting_for_domainitself (400).workflows_enable_waiting_failed_total, and the workflow keeps waiting.HogFlowSchemastatus enum (type only),raw_id_fieldsfor the new FK in admin.flowchart LR A[Enable: PATCH status=active] --> B{flag on and a sender unverified?} B -- no --> C[active] B -- yes --> D[waiting_for_domain] E[apply_verification] -- reload workers --> R{reload sent?} R -- yes --> F[enable_waiting_workflows_task] R -- no: wait past the worker cache --> F F --> G{senders all verified?} G -- yes --> C G -- no --> D classDef ph fill:#1d4aff,color:#fff,stroke:#1d4aff classDef wait fill:#f7a501,color:#000,stroke:#f7a501 class C ph class D waitProduction lines: 474 (+439 −35) against the base, by
git diff --numstat. Tests, generated types and the migration are excluded. This is over the 400-line budget because the review fixes (edit go-live, its activation event, the integration delete guard, the archived enable and the reload wait) belong with the behavior they protect.Replaces part of PostHog#123660 (the send once verified core). The rest of that PR follows in the next slices.
How did you test this code?
hogli ci:preflight --strict(pre-push, no failures). The suites of every touched module ran:products/workflows/backend(all passed), and the targeted send once verified,posthog/api/test/test_integration.pyandposthog/models/integrationsuites (all passed). Repo-wide mypy is clean on the stacked slice above, which contains this HEAD.Live run (on
6bc8eef8217;eb0db58e39dreuses it, see Proofs). A dev server, a real Celery worker and the local MCP server ran from this branch, on a private database and Redis.workflows-enable, with an unverified sender: the workflow saveswaiting_for_domain. The CDP trigger loader's own query (status='active') does not return it.POST …/integrations/<id>/email/verify: the worker takes the workflowactive, setswent_live_at, and the loader query returns it.activeat once. A client sendingwaiting_for_domaingets a 400.?status=waiting_for_domainlists the waiting workflow.0039afterwards, behave the same.maildevprovider withverified: false, the state an SES sender has before its DNS checks pass. The flag is stubbed on atposthoganalytics.feature_enabled, the seam the API tests patch.Shadow diff (base
287950a29f1, this PR's base). The same 20 requests went to a base server and a HEAD server with identical seeded rows: create, rename, enable, re-enable, live and draft edits, MCP graph edit, publish, disable, archive and enable, create as active with a verified sender and a verified rotation, and lists. Responses, saved workflows, versions and revisions match the base. The only differences are the fields this PR adds (enable_requested_at,went_live_at,enable_requested_by_id). The first run found the archived enable no-op above; it is fixed test-first.Test rationale:
TestHogFlowSendOnceVerified(API level,test_hog_flow.py): Enable saves the status its senders and the flag allow, a rotation waits, re-enable after verification activates once, create-as-active waits, a client cannot setwaiting_for_domain, an archived workflow follows the enable rule and sends the activation event only when it goes live, a failing edit is refused, and an edit or publish to a verified sender takes it live with one activation event. No existing test covers the enable rule. The API level is the contract agents use.TestVerifiedSenderTakesWaitingWorkflowsLive(test_email_sender_verification.py): verification takes waiting workflows live with or without the flag. A second unverified sender keeps it waiting, and a workflow turned off first stays off. A broker failure keeps the verification. A failed last retry is logged and counted. A partial batch keeps the events of the workflows already live. Senders reload on workers before the go-live is queued, and a failed reload queues it past the worker cache. A lookup failure after go-live does not retry the task. These go throughapply_verificationand the Celery task, the seam the go-live runs on.Test seams: the HogFlow REST API,
EmailIntegration.apply_verification, andenable_waiting_workflows_task.Proofs (per qa-swarm
PROOF.md):b81b27d61fb. Final reads: the missing activation event on edits (fixed in214c842217e), the missing publish test (added in8c40e5f1573), then three reads with no findings. Round 2 on the archived enable fix: a go-live after a failed worker reload, and no activation event for archived to active, both fixed ineb0db58e39d. Final read ofeb0db58e39d: no findings. Each fix has a red-first test6bc8eef8217(above); reused foreb0db58e39d, which changes only the countdown after a failed reload and a usage event6bc8eef8217(above); reused foreb0db58e39d, which changes no response or saved fieldDecisions
hog_flow_activated?Involvement: no grilling rounds; reviews by GPT-6.1 Sol (2 rounds, 6 final reads); live run and shadow diff captured.
Release status
Docs update
None. The behavior is behind a flag and has no user docs yet.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: Claude Code, Claude Opus 5.5 (implementation); GPT-6.1 Sol (review)
tdd,django-migrations,improving-drf-endpoints,writing-tests,pr-description,merge-risk.🤖 Generated with Claude Code