Skip to content

feat(wizard-tools): add publish_handoff tool for deterministic handoff - #1046

Closed
gewenyu99 wants to merge 1 commit into
fcgomes/upload-handoff-textfrom
posthog-code/publish-handoff-tool
Closed

gewenyu99 wants to merge 1 commit into
fcgomes/upload-handoff-textfrom
posthog-code/publish-handoff-tool

Conversation

@gewenyu99

Copy link
Copy Markdown
Collaborator

Problem

A run's handoff is produced across three separate agent-IO paths today: the agent Writes the report file, the agent calls notebooks-create via MCP (hand-encoding a multi-page report as ProseMirror JSON, with several failure modes the skill spends paragraphs warning about), and a passive HandoffWatcher reads the file back into the store so the task-stream push carries handoff_text. Three paths means three chances to drift, and three rounds of slow agent IO.

Stacks on #1045, which introduced the handoff_text upload to the PostHog session.

Changes

  • New publish_handoff wizard tool (src/lib/wizard-tools/handoff.ts) that in one deterministic, host-side call: atomically writes the report file, mirrors it into a shareable PostHog notebook via direct HTTP (using the run's already-provisioned notebook:write scope — no MCP round-trip), and sets the captured text on the store so the task-stream push carries handoff_text (the upload part feat(task-stream): publish the setup report as the session handoff doc #1045 introduced).
  • The tool is registered into the wizard-tools MCP server and the pi facade, sharing one pure-logic core so behavior can't drift between harnesses — same pattern as the orchestrator queue tools. It's registered only when the runner supplies a handoff context (report path + store hooks); absent in hosts without a store/report, the surface stays stable.
  • The HandoffToolsContext is built by the runners (which own the WizardStore + TaskStreamPush + the program's reportFile) and threaded through runAgent → the sequence runner → the harness inputs, mirroring how the orchestrator context is threaded.
  • The passive HandoffWatcher from feat(task-stream): publish the setup report as the session handoff doc #1045 stays as a fallback with a TODO(remove) note; once every program's skill content calls publish_handoff, it (and the force-read in TaskStreamPush.shutdown) can be deleted.

Coordinated with PostHog/context-mill: the integration-v2 report step now calls publish_handoff with the full report markdown, and the notebook step becomes a no-op confirmation (the tool already created the notebook).

Test plan

npx vitest run src/lib/wizard-tools/__tests__/handoff.test.ts — 12 new tests covering: blank-content rejection, oversize cap, notebook content shape, URL building, path-traversal rejection, file write + store hooks + notebook URL on success, blank rejection writes nothing, missing credentials still writes file + sets handoff_text (notebook skipped), notebook-upload failure still writes file + sets handoff_text, and the runner buildHandoffContext factory. Existing task-stream, wizard-tools, agent-interface, and orchestrator queue-tools suites still green (112 + 79 tests). pnpm typecheck introduces zero new errors vs. the #1045 base.


Created with PostHog Code

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
@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.

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