Skip to content

feat(task-stream): publish the setup report as the session handoff doc - #1045

Merged
gewenyu99 merged 7 commits into
mainfrom
fcgomes/upload-handoff-text
Jul 31, 2026
Merged

gewenyu99 merged 7 commits into
mainfrom
fcgomes/upload-handoff-text

Conversation

@fercgomes

@fercgomes fercgomes commented Jul 30, 2026 •

Copy link
Copy Markdown
Contributor

Problem

A run's real handoff is the markdown setup report the agent writes into the user's repo, but the wizard session stream never carries it, so the PostHog app can only say "the run finished" and point at a file the user may never open.

Ref PostHog/posthog#74935. App side: PostHog/posthog#75734 adds the handoff_text field on the wizard session plus the dialog that renders it.

Closes PostHog/posthog#74935

Changes

  • file-watcher grows a format: 'text' mode next to JSON (same mtime-poll plus fs.watch machinery, raw string delivery). The JSON error log line is unchanged.
  • New HandoffWatcher in the task-stream: watches the program's report file, mirrors its markdown into the store. Unlike the event-plan watcher it keeps following rewrites, because follow-up features (AI observability) append to the report after it first appears. ignoreInitialFile keeps a stale report from a previous run out of the session, and content is capped at the backend's 64 KB limit so an oversized doc can't 400 every subsequent full-state push.
  • TaskStreamPush accepts a handoffPath, starts/stops the watcher with the existing event-plan one, force-reads the file during the terminal flush, and includes handoff_text in the payload once captured. The backend keeps the field sticky per session, so pushes that raced the capture can't un-set it.
  • Runners pass handoffPath from the program's top-level reportFile, and posthog-integration now declares that field (self-driving and the skill-based programs already did). No product knowledge enters the transport: infra watches whatever file the program config names.

Test plan

npx vitest run: 5 new tests in handoff-watcher.test.ts (capture after write, follows rewrites instead of capturing once, stale-file ignore, blank rejection, 64 KB cap) plus a task-stream-push case asserting handoff_text is omitted before capture and carried after. Full suite: 1667 tests, 2 pre-existing failures unrelated to this change (a locale-dependent yargs assertion and nothing else; both fail identically on main on this machine).

End-to-end against the app needs PostHog/posthog#75734 deployed; until then the backend ignores the extra field, so shipping this first is safe.

LLM context

Authored with Claude Code (Fable 5), driven by fercgomes. Followed the wizard-development skill: the watcher is a task-stream concern fed by program config, mirroring the existing event-plan watcher rather than adding runner logic.

The wizard session API accepts a handoff_text field (the run's markdown
setup report) that the PostHog app renders as a handoff dialog. Watch
the program's report file and mirror it into the wire payload:

- file-watcher grows a text format alongside JSON
- HandoffWatcher follows the report for the whole run (rewrites
  included, since follow-up features append to it), ignoring a stale
  file from a previous run, capped at the backend's 64 KB limit
- TaskStreamPush includes handoff_text on every push once captured and
  force-reads the file during the terminal flush
- posthog-integration declares its top-level reportFile so the default
  flow gets the watcher (self-driving and the skill programs already
  declared theirs)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@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 basic-integration
  • /wizard-ci mcp-analytics
  • /wizard-ci revenue
  • /wizard-ci self-driving

Test an individual app:

  • /wizard-ci basic-integration/android
  • /wizard-ci basic-integration/angular
  • /wizard-ci basic-integration/astro
Show more apps
  • /wizard-ci basic-integration/django
  • /wizard-ci basic-integration/fastapi
  • /wizard-ci basic-integration/flask
  • /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 mcp-analytics/custom-dispatcher
  • /wizard-ci mcp-analytics/typescript-sdk
  • /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

Results will be posted here when complete.

@fercgomes fercgomes self-assigned this Jul 30, 2026
@fercgomes
fercgomes marked this pull request as ready for review July 30, 2026 18:59
@fercgomes
fercgomes requested a review from a team as a code owner July 30, 2026 18:59
gewenyu99 added a commit that referenced this pull request Jul 30, 2026
Consolidates the three agent-IO paths the handoff used to run separately
(write-file, notebooks-create via MCP, and the passive file-watcher) into a
single deterministic `publish_handoff` wizard tool. One call writes the report
file, mirrors it into a shareable PostHog notebook via direct HTTP (no MCP
round-trip, no JSON-encoding the agent has to get right), and sets the captured
text on the store so the task-stream push carries handoff_text — the upload
part #1045 introduced.

The tool is registered into the wizard-tools server (and the pi facade) only
when the runner supplies a handoff context (report path + store hooks), mirroring
how the orchestrator queue context is threaded. The passive HandoffWatcher stays
as a fallback (TODO: remove once all programs use the tool).

Coordinated with PostHog/context-mill, which rewrites the integration-v2
report/notebook step descriptions to call publish_handoff.

Generated-By: PostHog Code
Task-Id: 42ae71e9-0c89-4553-97a6-53c62e784fbb
…handoff

One explicit tool call replaces the three agent-IO paths the handoff ran
through: the agent Write-ing a report file, the agent hand-encoding ProseMirror
for notebooks-create over MCP, and relying on the passive file watcher to
mirror the file into handoff_text.

publish_handoff takes the full report markdown, mirrors it into a shareable
PostHog notebook via direct HTTP with the session's credentials, and — when the
program opts in via ProgramRun.uploadToPostHog (default false; only
posthog-integration and self-driving set it) — sets the text on the store so
the existing task-stream push carries handoff_text. No report file is written.

The usage contract lives in the tool description (shared between the MCP server
and the pi facade so they cannot drift), and the skill prompt now points at the
tool instead of hardcoding the report shape. The task-stream machinery is
untouched; the HandoffWatcher stays as the fallback for programs still writing
report files.

Analytics: `handoff published` / `handoff publish failed` via wizardCapture.

Coordinated with PostHog/context-mill (skills updated to call the tool after
this ships).

Generated-By: PostHog Code
Task-Id: 42ae71e9-0c89-4553-97a6-53c62e784fbb
@gewenyu99
gewenyu99 requested a review from a team as a code owner July 30, 2026 22:54
gewenyu99 added a commit to PostHog/context-mill that referenced this pull request Jul 30, 2026
…he notebook skill

The wizard now ships a publish_handoff tool: one call takes the full report
markdown, mirrors it into a shareable PostHog notebook (direct API,
credentials from the wizard session), and publishes it to the wizard session
as handoff_text. The notebook is no longer produced by the agent driving
notebooks-create through MCP, and no report file is written to the project.

- integration-v2-notebook skill: deleted (superseded by the tool).
- integration-v2 report agent + skill: compose the report from the run's
  queue log and event plan, then one publish_handoff call. Write dropped
  from allowedTools; no [NOTEBOOK_URL] marker.
- quack: publishes a short duck report via publish_handoff — the cheap
  end-to-end test of the tool without a real integration.

events-audit's notebook flow (a rich multi-node ProseMirror artifact) is
intentionally untouched.

Release order: the wizard change (PostHog/wizard#1045) must be released
first — skills are fetched at runtime, so this lands only once the tool
exists in the field.

Generated-By: PostHog Code
Task-Id: 42ae71e9-0c89-4553-97a6-53c62e784fbb
@gewenyu99

Copy link
Copy Markdown
Collaborator

Jesus Kimi butchered by plan, reverting first

…for the handoff"

This reverts commit e55f796, restoring the branch content to e9deb07 as originally authored. The publish_handoff implementation will be redone with a different approach.

Generated-By: PostHog Code
Task-Id: 6316a1d9-7a35-4a2b-8525-566e9931bcac
… file watcher

The handoff doc now reaches the session through one explicit tool call
instead of a report file mirrored by a watcher. The task-stream upload
itself (store → handoff_text on every push) is untouched.

- New publish_handoff wizard tool: takes the full report markdown, sets
  it on the store via getUI().setHandoffText(), capped at the backend's
  64 KB limit. Registered on both facades (MCP server + pi defineTool)
  with a shared description so they cannot drift, and included in the
  pi orchestrator's per-task wizard tools so the report task can call it.
- HandoffWatcher deleted, along with its TaskStreamPush/runner wiring
  and the file-watcher text mode added for it. No report file is
  written by the integration flow anymore.
- posthog-integration outro drops reportFile; the coding-agent handoff
  prompt now points at the report notebook URL (captured via
  [NOTEBOOK_URL]) and is omitted when the run never produced one. The
  orchestrator outro no longer checks for the report on disk.

Coordinated with PostHog/context-mill, where the integration skills
keep creating the notebook and switch from writing the file to calling
publish_handoff.

Generated-By: PostHog Code
Task-Id: 6316a1d9-7a35-4a2b-8525-566e9931bcac
gewenyu99 added a commit to PostHog/context-mill that referenced this pull request Jul 30, 2026
…ish_handoff only

The wizard's publish_handoff tool now does exactly one thing: publish
the report markdown to the wizard session. The notebook stays the
agent's job, created via notebooks-create as before.

- integration-v2-notebook skill restored; it now takes the composed
  report markdown directly (there is no file to Read) and keeps the
  notebooks-create transport and [NOTEBOOK_URL] marker.
- integration-v2 report agent + skill: compose the report, one
  publish_handoff call, then mirror into the notebook. No report file
  is written; Write stays out of allowedTools.
- integration (v1) conclude step: same treatment — compose in memory,
  publish_handoff, notebook. The local posthog-setup-report.md is gone.
- quack: keeps its publish_handoff ending as the cheap end-to-end test,
  with the notebook claims removed from the tool contract.

Release order unchanged: PostHog/wizard#1045 ships the tool first;
skills are fetched at runtime, so this lands only after that release.

Generated-By: PostHog Code
Task-Id: 6316a1d9-7a35-4a2b-8525-566e9931bcac
publishHandoff takes string, not unknown — both facades already
guarantee it via their schemas (zod / typebox), so only the blank check
remains. Comments cut to one line except where the why genuinely needs
more; the store setter drops its stale watcher reference and logs like
setNotebookUrl does.

Generated-By: PostHog Code
Task-Id: 6316a1d9-7a35-4a2b-8525-566e9931bcac
Two logToFile lines so a local run can verify the handoff from the
verbose log: the payload assembly logs phase + handoff_text size, and
the PostHog destination logs successful sends (failures already log).

Generated-By: PostHog Code
Task-Id: 6316a1d9-7a35-4a2b-8525-566e9931bcac
@gewenyu99

Copy link
Copy Markdown
Collaborator

Real run, 1-file Express app, project 228144. Wizard b15323fe + context-mill 1e914e46 (skills from a local dev server).

28-outro

publish_handoff: Handoff published (2541 chars)
store.setHandoffText: 2541 chars

Notebook created on this path: cnQzg9rC — PostHog setup (wizard) – wz-express-app, 2540 markdown chars. No posthog-setup-report.md written.

Carried through the task stream (headless route — the e2e harness never builds TaskStreamPush):

[task-stream-push] push phase=running   handoff_text=absent      ×23
publish_handoff: Handoff published (1809 chars)
store.setHandoffText: 1809 chars
[task-stream-push] push phase=running   handoff_text=1809 chars
[task-stream-push] push phase=completed handoff_text=1809 chars  ×2

That run's notebook: rxswIWNn.

{ "runPhase": "completed", "skillsComplete": true, "newDeps": ["posthog-node"],
  "screenPath": ["intro","auth","run","outro","mcp","slack-connect","keep-skills"] }
Full run — 31 frames

01-intro

02-auth

03-run

04-run

05-run

06-run

07-run

08-run

09-run

10-run

11-run

12-run

13-run

14-run

15-run

16-run

17-run

18-run

19-run

20-run

21-run

22-run

23-run

24-run

25-run

26-run

27-run

28-outro

29-mcp

30-slack-connect

31-keep-skills

@gewenyu99 gewenyu99 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

All good, remember to merge this and the attached context mill PR together.

@gewenyu99
gewenyu99 enabled auto-merge (squash) July 31, 2026 20:14
@gewenyu99
gewenyu99 merged commit ce8b70d into main Jul 31, 2026
16 checks passed
@gewenyu99
gewenyu99 deleted the fcgomes/upload-handoff-text branch July 31, 2026 20:16
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.

Wizard sync handoff

2 participants