Repository navigation
Run with PostHog Code from the Edit with your agent popover #514
Copy link
Copy link
Closed
Labels
Description
Map: Map: send code-managed email templates with one PostHog call
Spec: Spec: copy-as-code and open-a-PR for code-managed templates (revision 3), section "Run with PostHog Code in the popover (stack B)"
Cast: Opus 5.5, high
Repository: PostHog/posthog (frontend)
Stack: B, second slice
Question
From the "Edit with your agent" popover, can a person without a coding agent start PostHog Code on their sentence and follow it to a PR?
Delivers end to end.
- Button. The popover gains "Run with PostHog Code" next to "Copy prompt". It sends the same sentence to Request a change: start a PostHog Code task that opens a PR for a code-managed template #513's route through the generated client.
- Disabled reasons:
- "Describe the change first";
- "PostHog doesn't know this template's GitHub repository" (no
source_repository, or not on GitHub); - "Connect GitHub to run PostHog Code" (no GitHub integration on the project);
- absent entirely when PostHog Code isn't available to the project.
- In flight: the button is disabled and loading, so a double click sends one request.
- Success: a toast and the notice link the task ("PostHog Code is working on it. It opens a pull request when it's done."). The sentence is cleared. Nothing changes in the template.
- Errors show
detailandfix; the sentence and Copy prompt stay. - Events:
message template change run requested{template_id}andmessage template change run failed{template_id, code}(the server event from Request a change: start a PostHog Code task that opens a PR for a code-managed template #513 covers success).
Test seams.
- Kea logic tests on
messageTemplateLogicat the API boundary:- the request carries the sentence exactly;
- one request on a double click;
- each disabled reason;
- an error keeps the sentence.
- A story for the enabled, disabled and success states.
- Prior art:
messageTemplateLogic.test.ts; the MCP analytics "create a fix task" button inproducts/mcp_analytics/frontend/tool-quality/, for how a page checks the GitHub integration.
Write scope. products/workflows/frontend/TemplateLibrary/: the popover component from #503 and its story, messageTemplateLogic.ts, templateCopy.ts.
Proof.
- Red: the "one request on a double click" test fails.
- Green: the logic tests pass.
- Local: against the private scratch repository
Silthus/posthog-workflows-github-scratch:- start a change from the page;
- screenshot the popover and the success notice;
- follow the task to its PR, and show the PR changes only the template's file.
- If PostHog Code can't run on the dev stack, record the gap and prove with stories and the mocked API.
- Screenshots at 1280px with the side panel open and at full width.
Acceptance criteria
- The button only appears when PostHog Code is available, and says why it's disabled otherwise.
- One click starts at most one task.
- Screenshots in the PR.
Blockers
Blocked by #503 (the popover) and #513 (the route).
How to build (map #461)
/tddred-green-refactor, outside-in, at the seams named above. Real Postgres, Valkey and ClickHouse; mock only what the seam section allows.- Repo skills apply where the diff touches their area:
/writing-tests,/writing-ui-components,/writing-kea-logics,/writing-user-facing-copy,/writing-code-comments,/improving-drf-endpoints,/routing-outbound-api-calls. - Read code from
origin/spec/code-managed-templates(the fork's integration branch for feat(messaging): upload, send and lock code-managed email templates PostHog/posthog#118924), not frommaster. - Public repo: no usage numbers, customer names, internal metrics, Slack content or security reasoning in code, commits or the PR. Fixture addresses use
example.com. The private note the map points at is background only; never quote it. - Shipped means a draft PR handed off for review (see the map's Notes for remotes and branches). Never mark ready, enqueue or merge. The conductor names the stack's integration branch.
Reactions are currently unavailable
Activity
Silthus commentedon Oct 17, 2026
Runtime: T3 child task
Task:
node:delegated-task:command%3Amcp%3A1778d880-5a25-404c-80d0-25fc5ccca3b2%3Adelegate-task%3Awf-email-impl-514-1Cast: Opus 5.5, high. Cap 180 minutes.
Silthus commentedon Oct 17, 2026
Note
🤖 Opus 5.5 responding on behalf of Michael
Resolution
Landed:
60fb98f06a5onspec/template-request-change(fast-forward804a0b87d6c..60fb98f06a5).Branch:
spec/template-request-change/514. No PR: the ship ticket #517 opens it.The range also carries the merge of stack A (
495bca44dec, which brings #503's popover from62c695af6cb). #509 was not on stack A yet, so whoever lands second merges it.What landed
POST messaging_templates/{id}/request_change/through the generatedmessagingTemplatesRequestChangeCreate.GET desktop/access/once, after a code-managed template loads. It is the sameget_desktop_access_decisionthe route checks. A refusal or a failed check hides the button.source_repository, or one that doesn't match the route'sgithub.com/<owner>/<name>pattern);detailandfixin an error banner. The sentence and Copy prompt stay. Without an error envelope: "PostHog Code couldn't start." and "Try again in a few minutes."message template change run requested{template_id}when the request leaves, andmessage template change run failed{template_id, code}.MessageTemplate.tsxintoCodeManagedNotice.tsx, so a story can show it with the task link. Same copy and Duplicate action.Proof
Test seam:
messageTemplateLogicwith the API mocked at HTTP (useMocks), inmessageTemplateLogic.test.ts, block "run with PostHog Code". Stories are the second seam.Red, test by test, before each slice:
TypeError: logic.actions.runWithPostHogCode is not a function.7 failed.3 failed.Mutation on the final code: dropping
isRequestingChangeRunfrom the guard fails the double-click test withReceived length: 2(log).Green:
messageTemplateLogic.test.ts:49 passed(log).TemplateLibrary/pluslib/components/Git:7 suites, 100 passed, nothing skipped (log).{instruction}with the sentence byte for byte;requestedeventallowed: true/false/503postHogCodeAvailabletrue / false / false201400 github_repository_not_connected/500without a bodydetailandfix(or the fallback) kept; sentence, popover and Copy prompt kept;failedevent withcode/nullLocal gate on the landed tree:
tsgo --noEmit --checkers 1infrontend/throughfleet heavy: exit 0 (log).pnpm --filter=@posthog/frontend fix: exit 0.pnpm install --frozen-lockfile: consistent.hogli ci:preflight --strict):"failures": 0(log).build:openapior mypy run.Screenshots, Storybook from this worktree, API mocked at HTTP, MockHog project,
example.com-style repository, no customer data. Narrow is a 560px window, about the scene of a 1280px window with the side panel open. Wide is 1440px.Template page (real
Appscene, scratch story, not committed):detailandfixCommitted stories,
Products/Workflows/Template library/Edit with your agent. The 640px story frame clips at 560px, so read the page shots above for narrow:RunWithPostHogCode(enabled)RunWithPostHogCodeNeedsGitHub(disabled, tooltip on hover)RunWithPostHogCodeStarted(notice with the task link)WithAPath, unchanged: no access mock, so no buttonA browser script counted
request_changePOSTs per story: 0 for the enabled and disabled stories, 1 for the started and refused ones.Gaps
Silthus/posthog-workflows-github-scratch. So no task, no PR, and no "the PR changes only the template's file" proof. The route's task arguments are Request a change: start a PostHog Code task that opens a PR for a code-managed template #513's proof. The ticket allows this fallback. Ship stack B: request a change through PostHog Code #517 can run it where PostHog Code runs.Calls made
desktop/access/. It runs the route's Desktop access decision. Credits are not checked on the page: an organization without credits seesposthog_code_not_availablewith its fix in the popover.github_repository_not_connectederror.detailandfix, so the page shows both and keeps no second table of messages. The only frontend copy is the fallback for a response without the envelope.initKea, which would duplicate the banner. Turning that off means editingfrontend/src/initKea.ts, outside this product.urls.taskDetail(task_id), an in-app route, not the absolutetask_url.requestedevent fires when the request leaves, after the guards. A blocked click sends no event.templateCopy.tsis unchanged. Nothing in it relates to this slice.pnpm installafter the stack A merge, because Edit with your agent: copy a prompt for a code-managed template's file #503 added@testing-library/domanduser-eventtoproducts/workflows.qa-swarmreview.Follow-ups
spec/template-request-changeagain.EditWithAgentButton.tsxis the likely conflict: Copy as code: copy a code-managed template as its HTML file #509 changes the trigger, this ticket changes the footer.