Skip to content

refactor(programs): B1 move-only — program code into src/programs - #1306

Merged
gewenyu99 merged 90 commits into
mainfrom
posthog/functional-b1-pr
Sep 25, 2026
Merged

gewenyu99 merged 90 commits into
mainfrom
posthog/functional-b1-pr

Conversation

@gewenyu99

@gewenyu99 gewenyu99 commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Scope: Moves only. Behavior preserved. Skim.

Related: #1320

Program definitions, detection, frameworks, the framework registry and the task stream move from src/lib and src/frameworks into src/programs. The framework registry is now src/programs/frameworks/registry.ts, next to the configs it lists. The Ink decks move to src/ui/tui/decks. The agent error map moves into src/agent, and the environment isolation helper moves into src/shared. Nothing else changes.

Stack: #1306 moves → #1307 surface shell → #1308 plumbing → #1357 runner context → #1309 docs → #1363 stream retry.

Entries and checks
  • @programs exposes the program registry and lookups. @programs/types exposes the shared types.
  • The architecture test's allowlist records the 171 edges that remain after the move. Later releases remove them. New imports still have to pass the gate.
  • Programs still import their Ink decks and a few TUI types: 19 programs -> ui/tui rows, 14 of them decks. The TUI takes over the deck lookup by ProgramId later in the refactor.

Checks at 6677a153, on current main: pnpm typecheck, pnpm lint (0 errors), pnpm vitest run (3,405 tests) and pnpm test:arch (11 tests) pass.

Created with PostHog Desktop

…on contracts

runAgent(config, input, {onProgress?, interaction?, signal?}) returns a
RunResult and never rejects. RunConfig and RunInput replace the session
reads, AgentProgress replaces the getUI() calls, an optional AgentInteraction
replaces the getUI() answerer, and every former wizardAbort returns as a
failure with the same fields. An unexpected throw returns as outcome
'crashed' with the original error attached.

Gates, authenticate, token refresh, flag fetch, binding resolution and the
exit move to src/lib/programs/run-agent-legacy.ts, which maps each progress
event to one WizardUI call so every existing caller keeps its output.
authenticate moves to programs unchanged. The allowlist architecture test is
removed; import enforcement lands with the A2 move.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
…the cut

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Restore detection progress, isolate progress observers, and preserve
completion and cleanup ordering. Type run outcomes and share status
history handling; cover harness, sequence, and adapter boundaries.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Track pending requests in the ask bridge and pass its accessor to both
Anthropic harness paths. This restores the permission guard against
Write/Edit calls racing an unanswered wizard_ask request.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Cover delayed answers across both sequences and harness bindings, plus
completion when questions are disabled. Production behavior is unchanged.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Keep the diagram as native Mermaid in the PR description.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
The agent builds WizardError for every decided failure, and it had to
import the process-exit module to do so. The class now lives in
src/lib/errors/wizard-error.ts; wizard-abort re-exports it so every
other importer is unchanged.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
TokenUsageDelta, SpinnerHandle and AuthErrorDetail are what the agent
puts on its progress events, and AgentChunk is what the streaming prompt
runner yields. They move next to the code that produces them;
wizard-ui.ts and the MCP prompts service re-export them so every UI
importer keeps its path. The agent no longer imports from src/ui for
these.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
OutroKind, OutroData, AskQuestion, AskAnswers, PendingQuestion and
TaskNotice are what runAgent returns and asks with, so they move into
src/lib/agent/progress.ts. Credentials moves next to the API types,
AdditionalFeature next to the other program enums in constants, and the
session's CloudRegion copy points at the one in @utils/types.
wizard-session.ts re-exports all of them, so its 127 importers are
unchanged. The agent no longer imports @lib/wizard-session for a shape;
the one remaining WizardSession reference is ProgramRun's session hooks.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
…e program hooks

The agent's RunConfig.run is now AgentRunDefinition: prompt, skill,
tools, copy, ask policy. ProgramRun extends it in
src/lib/programs/program-run.ts with the three session-taking completion
hooks (postRun, buildOutroData, buildOutroNextSteps) that only the
legacy adapter calls. Programs import ProgramRun from there; the agent
no longer references WizardSession anywhere.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Both read and write the session, drive the OAuth flow through the UI and
take a ProgramId. Plan section 4.5: programs own authentication and
refresh. File and test move unchanged; five importers repoint.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
… programs

yara-hooks and the audit ledger tools imported filename constants and
the AuditCheck shape from three programs. The document names now live
in @lib/constants, the ledger contract (file, check shape, read-side
coercion) in the new leaf @lib/audit-ledger, and each program re-exports
its own, so the audit views and the ledger watcher are unchanged.
Nothing agent-side imports @lib/programs at runtime any more.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
…data

PackageManagerDetector, PackageManagerInfo, DetectedPackageManager and
detectNodePackageManagers move into @utils/package-manager, which already
owns the lockfile detection they wrap. src/lib/detection/package-manager
re-exports them, so every framework config is unchanged; the agent's two
harnesses and the tools server now import the detector contract without
importing detection.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
createBenchmarkPipeline takes the run's emitter; the summary and JSON
writer plugins receive it through MiddlewareFactoryOptions and emit one
`log` event per line they used to print through getUI(). The legacy
adapter's reducer maps each back to WizardUI.log.info, so --benchmark
output is unchanged. Nothing under src/lib/middleware imports src/ui.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
flushScanReport takes `{ yaraReport }` and returns the report line when
it wrote one. The runner emits it as a `log` progress event from its
single flush seam; the legacy adapter's cleanup prints it through the UI
as before. yara-hooks no longer imports the UI or the session type.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
publish_handoff emits `{ kind: 'handoff', text }` instead of calling
getUI().setHandoffText. Both facades (the MCP server and the pi tools)
receive the run's emitter, the snapshot keeps the text as
RunSnapshot.handoffText, and the legacy adapter's reducer maps the event
to WizardUI.setHandoffText so the TUI and the headless host see exactly
what they saw before.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
ESLint no-restricted-imports on today's agent paths: no @ui, session,
detection, registry, runners, commands, steps, frameworks, setup-utils
or oauth imports of any kind, no wizardAbort, and @lib/programs as
types only until B1 moves PROGRAM_BINDINGS. No file allowlist; the rule
runs in the editor and in `pnpm lint`. A2b collapses the path list to
src/agent/**.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
`@agent` exports the runtime values callers use and `@agent/types` the
types; everything outside `src/agent` imports one of the two. The MCP
prompt streaming export loads on first call so the startup chunk does
not grow. The architecture scanner enforces the entries on resolved
paths and ESLint rejects deep `@agent/*` specifiers in the editor.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
`debug()` reports through an injected sink that the UI module installs,
so shared no longer looks the UI up. The progress tag helpers move from
`src/telemetry.ts` to `@utils/telemetry` and the detect error map moves
to programs, which own the detect error kinds. `src/shared` is now its
own surface in the architecture test; the remaining upward edges are
listed with their owners in the stack plan.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
@gewenyu99
gewenyu99 added this pull request to stack #1362 September 25, 2026 15:16

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note a pure move, adds a index type file

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore this file. This is a ledger taht will be deleted when the restack is over.

@gewenyu99 gewenyu99 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤞

@gewenyu99
gewenyu99 marked this pull request as ready for review September 25, 2026 15:49
@gewenyu99
gewenyu99 requested review from a team as code owners September 25, 2026 15:49
@gewenyu99
gewenyu99 requested review from TueHaulund, ablaszkiewicz, arnohillen, fasyy612, hpouillot and ksvat and removed request for a team September 25, 2026 15:49

@johncwaters johncwaters left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Automated review. Not written by a human.

Verdict: APPROVE WITH NITS

  • src/programs/registry.ts [NIT · general] MEDIUM: FRAMEWORK_REGISTRY moved from src/lib/registry.ts to a file with the generic name src/programs/registry.ts. That file sits next to program-registry.ts (PROGRAM_REGISTRY) and near warehouse-sources/registry.ts.

As a result, @programs/registry reads like an import of the program registry, and 11 files already use it. The file also lives outside src/programs/frameworks/, where the configs it lists are.

Because its imports were rewritten, git records the move as a delete plus an add, and blame history is lost.

Suggested fix: rename it to src/programs/frameworks/registry.ts or framework-registry.ts.

The real John is already reading with physical eyes.

@gewenyu99

Copy link
Copy Markdown
Collaborator Author

Hi, NotVincent here :disguise-emoji:, I will do the deeds

On the review note about src/programs/registry.ts: it moves to src/programs/frameworks/registry.ts, next to the configs it lists.

The registry only maps integrations to framework configs, so it lives
beside them. Importers now use @programs/frameworks/registry.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
Main's new task-stream sync lands beside the moved task stream, so its
importers use @programs/task-stream/wizard-run-sync and its edges join the
known task-stream rows.

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

Copy link
Copy Markdown
Collaborator Author

It's done, NotVincent will tell Vincent to double check.

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.

2 participants