Skip to content

Storyboard runner: webhook_receiver_envelope grades "Failing" when receiver URL not configured; yaml states it should grade not_applicable #2356

Description

@kapoost

Repro

  • Agent registered on AAO panel: any AdCP agent (in my case signals.purrsonality.rocketscience.pl/mcp).

  • Agent does NOT expose a webhook receiver — it is a signals agent, not a buyer/orchestrator.

  • Panel's compliance run is not configured with webhook_replay_receiver.url.

  • AAO panel shows the storyboard as:

    UNIVERSAL: WEBHOOK-RECEIVER-ENVELOPE — Webhook receiver envelope: inbound POST conformance · 5 steps · Failing · 0/5 steps

    First failed step: POST delivery report inside MCP webhook envelope
    post_delivery_report_inside_mcp_webhook_envelope · replay_webhook_vector
    No webhook replay receiver URL configured. Pass webhook_replay_receiver.url in StoryboardRunOptions to run inbound receiver conformance.
    Showing the first failing step; 4 more failures remain.

The storyboard's own narrative (compliance/cache/<v>/universal/webhook-receiver-envelope.yaml) is explicit:

The storyboard grades not_applicable when the runner was not configured with a buyer receiver URL. It is for buyer/orchestrator receiver testing, not for seller endpoint grading.

Why the step returns are actually correct

dist/lib/testing/storyboard/runner.js executeReplayWebhookVectorStep handles the missing URL correctly at the step level:

```js
if (!receiver?.url) {
const detail = 'No webhook replay receiver URL configured. Pass `webhook_replay_receiver.url` in StoryboardRunOptions to run inbound receiver conformance.';
return {
step_id: step.id,
// ...
passed: true,
skipped: true,
skip_reason: 'grader_skipped',
skip: buildSkip('not_applicable', detail),
// ...
};
}
```

Each step returns `passed: true, skipped: true, skip.reason: 'not_applicable'`. Correct per storyboard yaml.

Where the bug is

The storyboard-level status rollup (or AAO panel's aggregation over that rollup) is treating a storyboard whose 5/5 steps are `passed: true, skipped: true, reason: not_applicable` as Failing 0/5 rather than as Not applicable or Silent.

Peer storyboards using the same skip pattern (`applicability_gate_missing`, `required_any_of_tools` unmet) do surface with `overall_passed: true, failed_count: 0, skipped_count: 1` and don't render as "Failing" on the panel. This one does. That's the inconsistency.

Expected

Storyboard-level status: Not applicable (or Silent) with `failed_count: 0`. Panel headline should not read "Failing", and "5 failures" should not be counted.

Actual

Panel headline: "Failing 0/5 steps", counts 5 failures, tells the operator to "review POST delivery report inside MCP webhook envelope, then re-test." There is nothing on the operator's side to fix — the agent under test isn't a webhook receiver and the runner has no receiver URL to replay against, exactly the case the storyboard yaml declares `not_applicable`.

Impact

Any agent that is not a buyer/orchestrator webhook receiver will show a spurious "Failing" storyboard on its AAO card, degrading the badge card presentation for otherwise clean signals / seller / creative / governance agents. Not badge-blocking today, but flagged in "Needs attention" and "1 storyboard not passing" counters, which distracts from real issues.

Encountered on `signals.purrsonality.rocketscience.pl/mcp` (Signal-owned agent, 3.0 + 3.1 badged, 15-day streak) — "Needs attention: 1 storyboard not passing. Start with webhook_receiver_envelope" while no other core / signals / error_handling storyboard has any actual issue.

Fix direction

Either:

  • A. Storyboard-level rollup: when 100% of steps in a storyboard are `skipped: true` with `skip.reason: not_applicable`, storyboard status classifies as `not_applicable`, not `failing`. AAO panel then renders it as such (or hides the card).
  • B. Runner: when no `webhook_replay_receiver` is configured AND the storyboard's declared applicability requires one, skip the whole storyboard rather than executing each step to per-step `not_applicable`. Storyboard status `skipped` naturally.

Option B mirrors what other capability-gated storyboards already do (`required_any_of_tools`, `required_capabilities` gates in `compliance/comply.ts`), and would be the cleaner fix.

Session

Discovered while sweeping AAO panel for badge-blocking issues after the 11.2.0 upgrade sweep.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions