Skip to content

fix(orchestrator): report the steps a failed dependency stopped - #1275

Merged
edwinyjlim merged 1 commit into
mainfrom
posthog/report-blocked-orchestrator-steps
Sep 22, 2026
Merged

edwinyjlim merged 1 commit into
mainfrom
posthog/report-blocked-orchestrator-steps

Conversation

@Gilbert09

Copy link
Copy Markdown
Member

Problem

A task that is still pending when the orchestrator drain ends never ran and
never will: one of its dependencies failed terminally, so nextRunnable can
never return it. Nothing marks it terminal, so it emits no completed,
skipped, or failed event — the step simply leaves no trace.

That makes an accepted step vanish from the funnel. The seeded data-source step
is given dependencies on the planned coding tasks, so a terminal failure
upstream of it strands it: the user was offered the step, accepted it, and the
outcome is then unrecorded rather than counted. Telemetry for the last day
shows runs ending this way, including one where the accepted data-source step
left no outcome at all.

The user-facing message had the same gap. The abort reported N steps never ran — a count with no names, so someone who had just agreed to connect their
data sources could not tell whether that was one of them.

Why: this came out of reading the seeded-task funnel. Every other terminal
state is recorded with a reason; this one is the hole, and it is the hole an
accepted step falls through.

Changes

  • drainVerdict also returns blockedTypes alongside the existing blocked
    count.
  • A new orchestrator task blocked event fires once per still-pending task at
    drain end, carrying the task type, whether it was optional, and the required
    types that failed. Additive: no existing event or property changes, and the
    queue is not mutated — the run cache is already wiped by this point, and
    writing to it would recreate the folder the cleanup just removed.
  • describeDrainFailure composes the abort line from both halves, so the
    message names the step that failed and the steps it stopped.

Test plan

  • New unit tests in
    src/lib/agent/runner/sequence/orchestrator/__tests__/optional-tasks.test.ts
    for blockedTypes (including a stranded optional seeded step) and for all
    three describeDrainFailure shapes.
  • Full unit suite green (177 files, 2841 tests); ESLint and Prettier clean on
    the touched files.
  • tsc --noEmit error count unchanged from main (31 pre-existing, none in
    the touched files).

Created with PostHog Desktop

🤖 Generated with Claude Code

A task still pending when the drain ends never ran and never will: a
dependency failed, so `nextRunnable` can never return it. Nothing marks it
terminal, so it emits no completed/skipped/failed event at all — a step the
user was offered and accepted disappears from the funnel rather than showing
up as an outcome. The abort message had the same gap, reporting only how many
steps never ran and not which.

Emit `orchestrator task blocked` per still-pending task at drain end, and name
those steps in the abort message. The queue is left as it is: the run cache is
already wiped by this point, and writing to it would recreate the folder the
cleanup just removed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: e3b8a0c8-f668-4172-950b-91242cb09e59
@Gilbert09
Gilbert09 requested a review from a team as a code owner September 19, 2026 12:02
Copilot AI lite review requested due to automatic review settings September 19, 2026 12:02

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

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.

Copy link
Copy Markdown
Member Author

Overlaps textually with #1013 (stale automated draft, no commits since 2026-07-28), which edits the same abort line for a different reason: it splits the guard into two exception names and fixes the 1 steps never ran pluralisation. This PR is about the missing terminal event — a blocked task emits no outcome at all today — and names the steps instead of counting them, which subsumes that pluralisation. If #1013 is revived the two will conflict on that one line; worth reconciling at review time.

@Gilbert09 Gilbert09 added the stamphog Auto-merge stamp for automated PRs label Sep 19, 2026 — with PostHog
@edwinyjlim
edwinyjlim merged commit 0f62680 into main Sep 22, 2026
21 checks passed
@edwinyjlim
edwinyjlim deleted the posthog/report-blocked-orchestrator-steps branch September 22, 2026 17:19
gewenyu99 added a commit that referenced this pull request Sep 23, 2026
Brings in the eight main fixes since beccc79 (#1275, #1280, #1284, #1294,
#1295, #1301, #1302, #1305). One conflict: agentic detection keeps main's
two-attempt retry loop from #1305 and adds A1's progress emitter to the
agent it initializes.

Generated-By: PostHog Desktop
Task-Id: d14e92bb-6ee1-49b5-8502-39cb80079589
posthog Bot added a commit that referenced this pull request Sep 23, 2026
…int aborts

The orchestrator's post-drain guard raised `orchestrator drain ended with
failed tasks` on a drain where nothing failed but tasks stayed blocked behind
a dependency that never completed. The user-facing copy already named the
steps, so only the exception misnamed itself — and it sent triage looking for
a failure the queue state does not contain. A small pure `drainFailureError()`
now returns the stable exception name per cause (mirroring the pi harness's
completion guard), so a blocked-only drain groups under its own name instead of
"failed tasks".

Separately, every abort's captured exception was fingerprinted server-side
from its stack trace, which carries the install path — pnpm dlx content
hashes, `.npm/_npx` dirs, CI checkouts, local clones. One cause therefore
shattered into an issue per install, each reading "1 occurrence, 1 user,
1 session". Aborts are raised from a fixed set of guard sites, so
`wizardAbort` now supplies a stable message-derived `$exception_fingerprint`,
following the pattern already proven on the OAuth flow. A callsite that wants
different grouping can still set the property in its `WizardError` context.

Rebased onto main after #1275, which merged into the same guard. This keeps
its per-task `orchestrator task blocked` events, the `describeDrainFailure`
message that names both the failed step and the steps it stranded, and the
missing-scope copy — and reconciles the guard down to the one thing #1275 left
unsolved: the split exception name. The user-facing text and pluralisation now
come from `describeDrainFailure`, so `drainFailureError` returns only the name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

3 participants