Skip to content

refactor: C2a — programs separate from the TUI, CLI and each other - #1369

Draft
gewenyu99 wants to merge 19 commits into
posthog/functional-c1-movefrom
posthog/functional-c2a-tui
Draft

gewenyu99 wants to merge 19 commits into
posthog/functional-c1-movefrom
posthog/functional-c2a-tui

Conversation

@gewenyu99

Copy link
Copy Markdown
Collaborator

Replaces #1312, which GitHub marked merged after a mis-stacked push.

Problem

Programs imported TUI, CLI and legacy code, and ProgramConfig carried screen steps, decks and tips.

Change

  • Programs import only env, shared and the agent entries.
  • ProgramConfig drops steps, getContentBlocks and getTips, and gains onReady, runSteps and healthCheck.
  • Flows, decks and tips live in the TUI registry (src/tui/programs), keyed by program id.
  • Programs read a ProgramSession, and the TUI's WizardSession extends it.
  • The run enums move to shared/run-state.ts, and the outro types to shared/outro.ts.
  • Runner contexts replace getUI() in run and ciPreRun.
  • wizardAbort shows its outro through a presenter the UI installs.
  • The TUI and the CLI reach programs only through their entries.

This PR also covers C2b's scope (the CLI owns headless runs and abort).

Checks

  • Typecheck, lint, 3,454 unit tests and the arch test pass.
  • Local nine-program snapshot sweep: eight programs complete with exit 0. self-driving stops at the "Connect GitHub" gate because local PostHog has no GitHub App.

Created with PostHog Desktop

TUI screens, decks and the store imported program internals by path (audit
types, doctor issues, detection helpers, the framework registry). @programs
and @programs/types now export what the TUI uses, and the TUI imports from
them. Source-map project detection stays out of CLI startup behind a lazy
wrapper; task streaming gets a loader for the runners. The bin.js startup
closure is unchanged (310 sources).

Allowlist 87 -> 56.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
The skill spellbook and the outage cache installed skills, and the suggested
prompts screen streamed an agent prompt, by importing @agent directly. The
TUI may import agent types only, so @programs now re-exports downloadSkill and
runMcpPromptViaSdk and the TUI imports them from there. The streaming module
still loads on first call.

Allowlist 56 -> 53.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
isInGitRepo, getUncommittedOrUntrackedFiles, isReact19Installed,
installPackage, getPackageDotJson, updatePackageDotJson, getPackageManager,
createNewConfigFile and the CliSetupConfig types have no callers; the last
callers went with the deleted prettier and env-file steps. versionSatisfiesRange
only served them. Its tests go with it.

What remains in setup-utils is project-data resolution and two package.json
readers, which the next commits give owners.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
tryGetPackageJson and isUsingTypeScript read project files and nothing else;
they join the other package.json helpers. Programs and the environment
module import them from there. No behavior change.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Project-data resolution (API key, OAuth login, provisioning signup) moves
from shared setup-utils to src/programs/project-data.ts, where programs own
it. It and the OAuth flow no longer look the UI up: performOAuthFlow takes an
OAuthFlowHost (login URLs, spinner, manual code, timeout and port overlays,
abort), resolution takes a ProjectDataHost, and authenticate takes an
AuthHost, the projection plus both. bindAuthHost adapts a UI object into one
while keeping each method's receiver.

The CLI builds its host from the current UI and wizardAbort; TUI screens that
log in build theirs from the TUI's own store. Same messages, same order, same
abort paths. The deprecated abort() delegator goes with its two tests.
SpinnerHandle moves to shared so the OAuth host can name it.

Allowlist 53 -> 48.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
WizardSession mixed what a program invocation knows (launch values,
detection, login, composition, outputs) with what the TUI adds (screen
confirmations, overlays, pending question and notice, presentation).
ProgramSession and buildProgramSession now live in src/programs;
WizardSession is ProgramSession & TuiSessionState and buildSession spreads
the two. Same fields, same defaults, same docs; no reader changes.

The legacy session imports the leaf module rather than @programs, whose
registry imports modules that import the session; that edge leaves when the
session moves to the TUI.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
run, ciPreRun, seedTasks, the ready context and the run-step targetDir and
onRunPrep read program state only, so they take ProgramSession. Screen
predicates and the store-init context keep WizardSession until the flow moves
to the TUI. Callers pass a WizardSession, a subtype; no call site changes.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Six programs ran detection through a screenless `detect` step's onReady, and
two described how a run step runs (child program, target dir, prep) on the
step itself. Both are program knowledge, not flow. ProgramConfig gains
onReady (detection before the flow) and runSteps (run composition keyed by
flow step id); the headless detect steps go, and the steps keep only what the
TUI renders and gates on.

The store, the non-interactive runner and the composed walk read the config
instead. Each program had at most one onReady, always first, so ordering is
unchanged; flow and frame goldens are untouched.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Each program's step list (screens, show/complete/gate predicates, the
health-check init work, the AI opt-in gate) is TUI flow, and it lived in
the programs layer typed against the whole TUI session. The step lists move
to src/tui/flows, one module per program, registered in PROGRAM_FLOWS; the
FlowStep type, StoreInitContext, createProgramSequence and
postAuthGateSteps move to src/tui/flow.ts. ProgramConfig no longer has
steps.

Product checks the flows need stay in programs and are exported through
@programs: needsFrameworkSetup (was duplicated in two flows),
isPostHogPresent and isSourceMapsProjectSelected.

The store, the router's sequences and the runners read the flow registry. A
parity test holds one flow per registered program and runSteps keys on run
screens; flow, frame and post-auth goldens are unchanged.

Allowlist 48 -> 43.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
WizardSession, TuiSessionState and buildSession move to src/tui/session.ts;
every reader imports each name from its owner instead of the legacy
re-export hub: run and MCP state from @shared/run-state, consent from
@shared/scan-consent, feature enums from @shared/constants, the question and
notice shapes from @agent/types, the session itself from @tui/session.

The outro contract (OutroKind, OutroData) moves to src/shared/outro.ts so
shared exit code can render it without the agent; @agent re-exports it.
Analytics reads the session through a structural SessionPropertiesSource.
The mint-failure helper joins the TUI screens that use it. src/lib and the
@lib alias are gone.

Allowlist 43 -> 39.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
The family picker rendered a menu of CLI Command objects: which children
show, in what order, with which labels, and what to run are CLI decisions.
The TUI keeps a generic renderFamilyPicker; chooseFamilyChild,
orderFamilyChildren and createFamilyPickerDefault move to
src/cli/commands/factories/family-picker.ts with their tests.

addMCPServerToClientsStep and removeMCPServerFromClientsStep only serve
`wizard mcp add|remove` and printed through getUI(); they move to
src/cli/commands/mcp/client-steps.ts. The MCP client library stays in the
TUI. The agentic detect screens report through an InkUI over their own store
instead of the singleton, and the spellbook takes ProgramConfig from
@programs/types. No getUI() call is left in src/tui.

Allowlist 39 -> 37.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Links to the agent-skill flow, the AI opt-in gate, the session and the flow
step type follow them into src/tui; run composition is ProgramConfig.runSteps.
Path and name updates only.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Merge the restacked C1 (9ec6760) into C2a. The conflicts are import
lines: C2a's `@tui/session` imports sit beside the e2e harness and
ErrorCodes imports, and the standalone agent test keeps C2a's session
types from `@agent/types`.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Merge the restacked C2a (d5145f3), which carries the A3
terminal-failure fix, the B-layer syncs and the surface e2e routes.
The tree matches d5145f3, where typecheck, lint and tests pass.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Merge the joined C1 (9fb8fb7) into C2a. The remote B review fixes now
use C2a's split session:

- `@lib/wizard-session` imports point at `@tui/session`, `@shared/outro`,
  `@shared/run-state` and `@shared/api`.
- B's register-then-commit skill cleanup and `deferSkillCleanupCommit`
  apply to C2a's hoisted run steps.
- `watchAuditLedger` is reached through `@programs`.
- The learn-deck program filter and the real-TUI host walk
  `rawProgramFlow` with `advanceStep`, since `ProgramConfig.steps` is
  gone.
- The scanner allowlist drops two stale entries.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Takes the trimmed B2 adapter in run-program-agent (preflight, workflow connector, credentials provider, data projection) and keeps this PR's cliAuthHost login and @tui/session types; the adapter's own gate walk over rawProgramFlow and its watchAuditLedger go, since runProgram now owns the health check, post-auth gates and file watchers, and getDetectedWarehouseSources comes through @programs so the allowlist loses the row B2 added. The @programs entry drops the refreshAccessTokenIfNeeded and watchAuditLedger re-exports, the audit recipes lose both their steps and their ledger seeding, and the runtime-registry test compares the registry with rawProgramFlow and ProgramConfig.runSteps instead of ProgramConfig.steps. Tests B2 added or moved (ask-policy, the integration-prompt helper, agentic-retry) import the TUI session.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Carry the host-only B2 cut into C2a. runProgram now takes the run and
program settings from its caller, and the preflight, runtime registry,
recipe resolution and workflow connector are gone. The session adapter
reads the health check and post-auth gates from the program's TUI flow,
since C2a moved the steps off ProgramConfig. The adapter test mocks
readiness again and covers the flow-derived health gate. The programs
README now describes flow-owned steps.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Programs import no TUI, CLI or legacy code. ProgramConfig drops steps, getContentBlocks and getTips and gains onReady, runSteps and healthCheck; flows, decks and tips move to the TUI program registry. Programs read ProgramSession; run enums move to shared/run-state and outro types to shared/outro; runner contexts replace getUI(); detection takes onProgress; wizardAbort shows its outro through an installed presenter. The TUI and CLI reach programs only through @programs, @programs/types and @programs/<id>.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
@github-actions

Copy link
Copy Markdown

🧙 Wizard CI

Run the Wizard CI and test your changes against wizard-workbench example apps by replying with a GitHub comment using one of the following commands:

Test all apps:

  • /wizard-ci all

Test all apps in a directory:

  • /wizard-ci ai-observability
  • /wizard-ci basic-integration
  • /wizard-ci feature-flags
  • /wizard-ci mcp-analytics
  • /wizard-ci replay-vision
  • /wizard-ci revenue
  • /wizard-ci self-driving
  • /wizard-ci warehouse
  • /wizard-ci warehouse-seeded

Test an individual app:

  • /wizard-ci ai-observability/anthropic
  • /wizard-ci ai-observability/google-adk
  • /wizard-ci ai-observability/groq
Show more apps
  • /wizard-ci ai-observability/manual-capture
  • /wizard-ci ai-observability/openai
  • /wizard-ci ai-observability/openai-agents
  • /wizard-ci ai-observability/opentelemetry
  • /wizard-ci ai-observability/vercel-ai
  • /wizard-ci basic-integration/android
  • /wizard-ci basic-integration/angular
  • /wizard-ci basic-integration/astro
  • /wizard-ci basic-integration/django
  • /wizard-ci basic-integration/fastapi
  • /wizard-ci basic-integration/flask
  • /wizard-ci basic-integration/flutter
  • /wizard-ci basic-integration/javascript-node
  • /wizard-ci basic-integration/javascript-web
  • /wizard-ci basic-integration/laravel
  • /wizard-ci basic-integration/next-js
  • /wizard-ci basic-integration/nuxt
  • /wizard-ci basic-integration/python
  • /wizard-ci basic-integration/rails
  • /wizard-ci basic-integration/react-native
  • /wizard-ci basic-integration/react-router
  • /wizard-ci basic-integration/sveltekit
  • /wizard-ci basic-integration/swift
  • /wizard-ci basic-integration/tanstack-router
  • /wizard-ci basic-integration/tanstack-start
  • /wizard-ci basic-integration/vue
  • /wizard-ci feature-flags/django
  • /wizard-ci feature-flags/next-js
  • /wizard-ci mcp-analytics/custom-dispatcher
  • /wizard-ci mcp-analytics/typescript-sdk
  • /wizard-ci replay-vision/javascript-node
  • /wizard-ci replay-vision/next-js
  • /wizard-ci replay-vision/react-vite
  • /wizard-ci revenue/stripe
  • /wizard-ci self-driving/astro
  • /wizard-ci self-driving/fastapi
  • /wizard-ci self-driving/nuxt
  • /wizard-ci self-driving/react-router
  • /wizard-ci self-driving/sveltekit
  • /wizard-ci warehouse/monorepo-env
  • /wizard-ci warehouse/multi-source-next
  • /wizard-ci warehouse/stripe-node
  • /wizard-ci warehouse/zero-source
  • /wizard-ci warehouse-seeded/next-stripe
  • /wizard-ci warehouse-seeded/next-stripe-declined

Test against a Context Mill branch:

  • /wizard-ci all context-mill:my-branch

Add context-mill:<branch> to any command above to pin the Context Mill branch. It defaults to main.

Results will be posted here when complete.

@gewenyu99
gewenyu99 added this pull request to stack #1372 September 27, 2026 15:28
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