Repository navigation
Conversation
… send `npx @posthog/wizard transactional-email` runs the context-mill skill omnibus-send-transactional-email: the setup agent checks for a verified sender, writes the project secret API key to the env file, and adds the first send with posthog-node or the HTTP API. The intro spell book of a plain run lists it, and the skill's two [ABORT] reasons end the run with a next step. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…eanup Import `ProgramConfig` from `@programs/program-contract`, where the services refactor moved it, and take the outro's `exit` step from the skill cleanup in the flow trace. Co-Authored-By: Claude Opus 5.5 <[email protected]>
A run of a migrate-email-<provider> skill sets migrated_from, so the setup wizard finished event names the provider. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Silthus
force-pushed
the
feat/transactional-email-program
branch
from
October 31, 2026 10:14
ac0bf64 to
1c077af
Compare
…migration The tag stayed on the process after the skill changed, so a later skill's events still said the run migrated from the email provider. Every skill change now sets or clears it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Both abort cases carry the transactional emails docs link, so the error outro of a matched abort shows where to go next. The test reads the cases through the program's run config, so dropping them from the config fails it. The program sets its binding explicitly, and the added comments go. Co-Authored-By: Claude Opus 5.5 <[email protected]>
The program names Pi, the linear sequence and its model, so a change to the default binding no longer moves it off the sequence its abort cases need. The abort test drops a check the type already makes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Owner
Author
|
Moved to PostHog#1507. |
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.
Moved here from PostHog#1487, closed on 2026-10-25 so this fork stack is the only copy. It opens upstream again after review.
This revision
Restacked on
mainon 2026-10-31, with no conflicts.6654b675addsmigrated_fromtosetup wizard finishedfor a migrate-email run, test-first.1c077af6links the posthog.com transactional emails page.a90f038b(review fix) setsmigrated_fromon every skill change, so a later non-migration skill, or none, clears it.6da6fc9d(QA swarm fix) links the transactional emails docs from both abort outros, test-first, and drops the comments this PR added.df5cfbd3spells out the program's binding.Problem
A team that has never sent email from code has no guided way to start with PostHog. Wizard can add PostHog to a project, but the setup agent has no path to send a transactional email, such as a welcome email after signup.
With this PR,
npx @posthog/wizard transactional-emailchecks for a verified sender, writes the project secret API key to the env file, and adds the first send to the app's server code. A plain run that finds PostHog already installed lists the command in its intro spell book.Part of Silthus/posthog#544.
Impact
Pays into Grow Workflows through organizations that send email from code (not measured yet: it needs the send source on each send, PostHog/posthog#120628). In scope: transactional email. Expected move: medium, up. Run cost: n/a.
Merge Danger
Warning
🟡 Merge risk: medium · one-way door: a release publishes the
transactional-emailcommand name (merge-risk rubric)omnibus-send-transactional-email, is not in any skill menu. Its context-mill PR is closed, because PostHog/posthog#125415 adds thesending-transactional-emailsskill in PostHog/posthog instead. Released as is, the command fails when it downloads the skill. Point it at the new skill before it leaves draft (see Open).[ABORT] transactional email api not enabled. On the default Pi binding no program's[ABORT]ends the run yet (see Gaps), so such a run can still end on the success outro.migrated_fromis a new property on the events of a run whose skill ID ismigrate-email-<provider>,setup wizard finishedincluded. Other runs send the same events as before.emails.sendis out (PostHog/posthog-js#5418). A revert removes the command, the spell book row, and the property.Changes
transactional-email(src/programs/transactional-email/), built withcreateSkillProgram. It names its binding: Pi, the linear sequence, GPT-5.6 Sol at medium thinking, the same as the default today.transactional-email(nativeCommandFactory), registered inrunCli.transactional-email Send your first transactional email from code.https://posthog.com/docs/workflows/transactional-emails.integrations-*sender tools and theworkflows-*email tools. The skill's Wizard section treats a missing tool as inconclusive, sends the person to the PostHog UI to verify a sender, and takes only a send's404as "API not enabled".migrated_fromonsetup wizard finished(src/services/session/session-store.ts): when a run's skill ID ismigrate-email-<provider>, such asmigrate-email-resend, the session sets the analytics tagmigrated_fromto the provider, hereresend. Every event after the run picks its skill carries it, the existingsetup wizard finishedevent included. No new event.https://posthog.com/docs/workflows/transactional-emails, the page of PostHog/posthog.com#21564.The skill's Wizard section (ask through
wizard_ask, write the key withset_env_values, reach PostHog tools throughposthog_exec, the[ABORT]reasons) was in PostHog/context-mill#433, now closed. The skill that replaces it must carry the same section.Test plan
Test seams:
src/cli/__tests__/programs-cli.test.ts):transactional-emailruns with skillomnibus-send-transactional-email. Red before the command existed (module not found), green after.intro-menu.test.ts): the curated list resolves and ends withtransactional-email, and the row fits 80 columns. Red, then green.src/programs/transactional-email/__tests__): each[ABORT]reason from the skill matches exactly one case in the program's run config, and that case links the transactional emails docs. Red before6da6fc9d(no link), green after.migrated_from(src/services/session/__tests__/migrated-from.test.ts): amigrate-email-resendrun tagsmigrated_from: resend, and other skill IDs set no tag. A later skill ornullaftermigrate-email-resendclears the tag. Red before the session set it, and red again beforea90f038b(the tag stayedresend), green after.program-registry.test.tspins the linear Pi binding. The flow-traces snapshot records intro, health check, auth, run, and outro for the program.Lane gate on
df5cfbd3:pnpm typecheckgreen,pnpm lint0 errors,pnpm exec vitest run261 files and 3,866 tests green. CI: the fork runs no workflows, so this PR has no checks; the lane gate is the check.Rebase fixes, both from changes on
main:ProgramConfigfrom@programs/program-contract, wheremainmoved the program contract.exitscreen, which replacedkeep-skillsonmain.Proofs per qa-swarm
PROOF.md(all gaps):migrate-emailskill or this command needs read-only production access. Nomigrate-emailskill is published yet, so no run takes themigrated_frombranch today.migrated_fromis one added string property on existing events, which ingestion stores as is. No PostHog stack on this box to feed both builds through.Gaps:
[posthog:abort], the gateway refusal marker. It ignores a skill's[ABORT], so these abort cases, like those ofrevenue-analyticsandmcp-analytics, don't fire on the default binding yet. Fixing that is a separate PR.--local-context-mill), Wizard CI credentials, and a project with the transactional email API on.Decisions
integration:readandintegration:writeonce the OAuth app's scope ceiling holds them, together with themigratefamilymigrated_fromon the existingsetup wizard finishedevent, from the skill ID; no new eventmigrated_fromis derivedSessionStore.setSkillId, the one point every skill run passes:migrate-emailskills run from the menu with no Wizard program of their own. The alternative, tagging the rawskill_idand droppingmigrated_from, renames the property the send attribution namesOpen: which skill
transactional-emailruns.omnibus-send-transactional-emailis gone with PostHog/context-mill#433, so today the command fails when it downloads the skill. Recommended: runsending-transactional-emailsfrom PostHog/posthog#125415 once the skill menu publishes it, move this skill's Wizard section there, and keep this PR a draft until then.Open: the Pi harness ignores a skill's
[ABORT], so on the default binding a run where the API is off can end on the success outro. Recommended: fix[ABORT]handling in the Pi harness as its own PR, for every program on Pi (revenue-analyticsandmcp-analyticshave the same gap), before this command leaves draft, rather than moving this program to the deprecated Anthropic binding.Follow-ups:
linear.tswould covermcp-analyticstoo and let this program drop its per-case links.programs-cli.test.tsuses.Involvement: no grilling rounds, no prototypes, one GPT-6.1 Sol review round over this PR and PostHog/context-mill#433 (four findings: three fixed in PostHog#433, one deferred as above) and one final read (one finding, fixed in PostHog#433), one GPT-6.1 Sol review of the rebase fix (no findings), and one GPT-6.1 Sol round on the restack (one finding on a stale
migrated_fromtag, fixed test-first) with a clean read of the fix. QA swarm 2026-11-01: one two-family panel round (9 lenses, GPT-6.1 Sol and Claude Opus 5.5) and a fixes read; 5 findings fixed, 1 call, 2 open decisions, 3 follow-ups, 0 rejected. Proof captured as command output.LLM context
Written by Claude Opus 5.5 (
claude-opus-5-5) as a build lane of a planning map. The setup agent copy follows the "Wizard once, then the setup agent" rule.🤖 Generated with Claude Code