Skip to content

fix(wizard-ask): return an explicit cancellation outcome, not a sentinel - #1218

Open
Gilbert09 wants to merge 1 commit into
mainfrom
posthog/wizard-ask-explicit-cancellation
Open

fix(wizard-ask): return an explicit cancellation outcome, not a sentinel#1218
Gilbert09 wants to merge 1 commit into
mainfrom
posthog/wizard-ask-explicit-cancellation

Conversation

@Gilbert09

Copy link
Copy Markdown
Member

Problem

wizard_ask is how the seeded warehouse task collects a source's credentials,
one call per detected source. When a call collects nothing, the result the
agent reads is:

{ "answers": { "host": "__cancelled__", "password": "__cancelled__" } }

Two things are missing from that.

The cancellation is encoded, not stated. __cancelled__ appears nowhere in
the tool's schema or description — an agent can only act on it if it already
knows the sentinel. The tool description tells it to "treat a cancelled or
timed-out response as the user declined" without saying how to recognise one.
A task agent on this flow asked for exactly this: an explicit decline
indicator, separate from the cancelled answer values, so it can report its own
completion state honestly. That report is what feeds the skip reason we added
in #1195, so the input to it being guesswork undermines the measurement too.

A dismissal and a timeout are indistinguishable. The bridge already knows
which happened — it stamps timed_out on the analytics event — but throws the
distinction away before the agent sees it. They call for different behaviour.
A dismissal is one decline: fall back for that source, carry on with the next.
A timeout means nobody is reading the terminal, and every later prompt in the
run will end the same way after the same 20-minute wait. Cancelled prompts
are the dominant in-task loss in this flow, and timeouts are a real slice of
them, including runs that timed out more than once — each one a full wait
spent on a prompt that could not be answered.

Why: users who accept the offer to connect their data sources and then
walk away lose the whole step, and the agent cannot tell that case from a
deliberate "not this one".

Changes

  • WizardAskBridge.request resolves to { answers, timedOut }. timedOut is
    the one fact only the bridge holds; the flag also replaces the
    duration >= timeout inference the analytics event was using.
  • New shared describeAskCancellation() in wizard-tools/tools.ts builds a
    cancelled envelope — reason (user-cancelled / timed-out), the
    uncollected questionIds, and a note on what to do next. Shared by both
    harness facades, the same discipline HANDOFF_FIELDS applies to the handoff
    schema, so the MCP server and the pi-native tool cannot drift.
  • Both facades attach it to the tool result; answers is unchanged, so the
    skill text that reads it (a context-mill artifact) keeps working as-is.
  • The tool description now points at the envelope rather than at the answer
    values.

The notes stay about the ask itself and say nothing about task queues or
complete_taskwizard_ask serves programs that have neither.

Not touched: the cap accounting and the refund (a cancelled ask is still
free), the sentinel itself, the timeouts, and the offer.

Test plan

pnpm build && pnpm test && pnpm lint — 2647 tests pass, 0 lint errors.

New cases: the bridge reports a dismissal and a timeout distinctly; the
descriptor names the uncollected ids, separates the two reasons, handles a
partly answered ask, and never counts a vaulted {secretRef} answer as
cancelled; the pi tool emits the envelope, distinguishes a timeout, and omits
it entirely when every question was answered.


Created with PostHog Desktop

A cancelled or timed-out `wizard_ask` came back as `{ answers: { host:
"__cancelled__" } }` and nothing else. The sentinel is not named anywhere in
the tool schema, and a prompt the user dismissed is byte-identical to one
nobody answered before it timed out.

Both facades now return a `cancelled` envelope alongside `answers`: the
question ids that were not collected, whether the user dismissed the prompt
or it timed out, and what to do next. The bridge reports `timedOut` — the one
fact only it holds — and the shared descriptor builds the envelope, so the MCP
server and the pi-native tool cannot drift.


Generated-By: PostHog Desktop
Task-Id: 2e6fcdd3-5969-4b4d-ab93-a70ef50ce512
Copilot AI lite review requested due to automatic review settings September 7, 2026 11:56
@Gilbert09
Gilbert09 requested a review from a team as a code owner September 7, 2026 11:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

github-actions Bot commented Sep 7, 2026

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

@Gilbert09 Gilbert09 added the stamphog Auto-merge stamp for automated PRs label Sep 7, 2026 — with PostHog
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stamphog Auto-merge stamp for automated PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants