feat(wizard-tools): publish_handoff creates the notebook, outro opens it - #1047
Draft
gewenyu99 wants to merge 10 commits into
Draft
feat(wizard-tools): publish_handoff creates the notebook, outro opens it#1047gewenyu99 wants to merge 10 commits into
gewenyu99 wants to merge 10 commits into
Conversation
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>
…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
… 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
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
publish_handoff now owns the whole handoff: it stores the text, creates the PostHog notebook itself, and sets the URL. The agent no longer makes a notebooks-create MCP call and echoes [NOTEBOOK_URL] back at us, so that marker and AgentSignals.NOTEBOOK_URL are gone along with both harnesses' parsing of it. The notebook is where the report lives now, so the outro auto-opens it and no program advertises a local report file any more. A file is written only when the notebook could not be created — the report never ends up existing nowhere. Generated-By: PostHog Code Task-Id: 3ab3f6ae-5b80-45a2-849d-ac6efdff3505
🧙 Wizard CIRun 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:
Test all apps in a directory:
Test an individual app:
Show more apps
Results will be posted here when complete. |
…ng a handoff we didn't deliver Three problems from reviewing the previous commit: Removing the `[NOTEBOOK_URL]` parsing was premature. This ships before the context-mill side, and the released skills still upload their own notebook and emit the marker — with the parsing gone and no report file advertised either, an audit run showed the user neither a notebook link nor a path. The marker is read again, documented as legacy, and can go once every released skill publishes through the tool. The notebook title was built from the program id, so it read "PostHog posthog-integration (wizard) – app". It takes the program's description now, and `buildHandoffContext` keeps the id for the fallback filename only. publish_handoff returned ok when the notebook failed AND the fallback write failed, so the agent was told the report was published when it had reached nobody. That case reports failure. Generated-By: PostHog Code Task-Id: 3ab3f6ae-5b80-45a2-849d-ac6efdff3505
A success now carries its url in the type, so the caller stops re-checking a field the ok flag already implies and the error string stops needing a default that could never be hit. buildNotebookContent had no caller outside the module. Generated-By: PostHog Code Task-Id: 3ab3f6ae-5b80-45a2-849d-ac6efdff3505
gewenyu99
marked this pull request as draft
July 31, 2026 03:34
Every publish_handoff call now reports what happened to it. `handoff called` fires before any work, so it is the denominator and shows calls that produced no outcome at all; `handoff rejected`, `handoff notebook failed` and `handoff published` cover the branches, with the notebook's duration and error string. Each event carries program_id, so notebook success rate is answerable per program rather than only in aggregate. Sizes and truncation ride along; the report text never does — it quotes the user's own code. Losing the notebook is recoverable and expected (a token without notebook:write), so it stays an event. Losing the notebook AND the fallback write means the report reached nobody, which raises an exception. Generated-By: PostHog Code Task-Id: 3ab3f6ae-5b80-45a2-849d-ac6efdff3505
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.
Stacked on #1045.
publish_handoffnow owns the whole handoff: it stores the text, creates the PostHog notebook itself, and sets the URL. The agent no longer makes anotebooks-createMCP call and echoes[NOTEBOOK_URL]back — that marker andAgentSignals.NOTEBOOK_URLare gone, along with both harnesses' parsing of it.The notebook is where the report lives now, so the outro auto-opens it and no program advertises a local report file. A file is written only when the notebook could not be created, so the report never ends up existing nowhere.
Shape
wizard-tools/notebook.ts—POST /api/projects/:id/notebooks/, retry/backoff/429/401 semantics copied from the task-stream destination, never throws.publishHandoffis async and takes a context (credentials, installDir, fallback filename, notebook title), built bybuildHandoffContextat all four harness call sites so they can't drift.setReportFileUI seam alongsidesetNotebookUrl, merged inInkUI.setOutroDatathe same way.HeadlessUInow keeps both, so cloud runs stop dropping the notebook URL.useAutoOpenNotebook— fires once, viaopenTrackedLink(same path OAuth uses), skipped when non-TTY. URL stays printed either way.successMessage/ prompt stops naming a.mdfile;skillPrompt()now orders apublish_handoffcall instead of a report file, which was the largest remaining source of stray files.Requires context-mill
The skills still tell agents to write files and create notebooks — that's the paired context-mill PR. Both audit ledger row ids (
write-report,upload-notebook) stay seeded on purpose so the currently released skills keep resolving cleanly while this ships first.Checks
tsc --noEmit26 errors, byte-identical to the base branch.vitest run119 files / 1669 tests, 0 failures (+1 new).check-screenspasses. Prettier and eslint clean.Created with PostHog Code