Skip to content

fix(examples): capture the connector response on the two showcase REST ping flows - #7618

Merged
os-help merged 2 commits into
mainfrom
claude/issue-7542-showcase-flow-isoutput
Aug 11, 2026
Merged

fix(examples): capture the connector response on the two showcase REST ping flows#7618
os-help merged 2 commits into
mainfrom
claude/issue-7542-showcase-flow-isoutput

Conversation

@os-help

@os-help os-help commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Fixes #7542

What was wrong

TaskCompletedRestPingFlow and ShowcaseDeclarativeConnectorPingFlow in examples/app-showcase/src/automation/flows/index.ts both told the reader that the call and its { status: 'ok' } response were captured on the flow run. Neither flow declared any variables at all.

run.output is not a free side effect of dispatching. The engine collects it from the flow's declared isOutput variables only — AutomationEngine.execute, "Collect output variables":

const output: Record< string, unknown > = {};
if (flow.variables) {
    for (const v of flow.variables) {
        if (v.isOutput) output[v.name] = variables.get(v.name);
    }
}

So both flows dispatched fine and returned an empty run.output, while the comment said the response was there — which sends the next reader hunting for an engine bug that does not exist. The sibling ShowcaseMcpConnectorEchoFlow is the proof it was authoring and not engine: same dispatch path, one declared variable, captured output.

The fix

Route 1 from the issue (the preferred one): declare the output variable both flows were evidently meant to carry.

The name was derived from what the step actually produces, not copied from the contrast fixture. connector_action writes a node's handler output back under ${nodeId}.${key} (engine.ts), the rest connector's request action returns { status, ok, body } (packages/connectors/connector-rest/src/rest-connector.ts), and both flows' connector node id is ping — so the response payload is ping.body. showcase_status_api is materialized by the same createRestConnector bundle through createRestProviderFactory, so the declarative flow is identical in this respect.

variables: [{ name: 'ping.body', type: 'json', isOutput: true }],

The comments were tightened alongside to name the variable, so the claim and the declaration cannot drift apart again.

Route 2 (weaken the comments) was measured and rejected: the capture works perfectly for these flows once asked for — see the verification below.

Verification — runtime capture, not schema validity

New file examples/app-showcase/test/connector-ping-run-output.test.ts. It drives the real flow definitions imported from src/automation/flows/index.ts through a real AutomationEngine with the real connector bundles — createRestConnector for the plugin rest connector, and createRestProviderFactory fed the real StatusApiConnector metadata for the ADR-0097 instance. Only fetch is stubbed, so the handler's { status, ok, body } output shape is the shipped one. The assertion is a content pin on the captured value:

expect(result.output).toEqual({ 'ping.body': { status: 'ok' } });

This is the runtime-capture level, not the schema level — an actual run of both flows, with the response value pinned. A booted app was not needed.

Reverse verification (predicted direction: red, with an empty output) — the fix was taken out with a path-scoped git checkout origin/main, never git stash:

FAIL  showcase_declarative_connector_ping captures it too, through the materialized ADR-0097 instance
AssertionError: expected {} to deeply equal { 'ping.body': { status: 'ok' } }
- { "ping.body": { "status": "ok" } }
+ {}

3/3 red, and the two dispatch cases fail with run.output = {} — the issue's reported symptom reproduced verbatim — while the recorded outbound request was still there, confirming dispatch itself was never the defect. Fix restored: 3/3 green.

Full local runs:

  • pnpm --filter @objectstack/example-showcase test18 files, 171 tests passed
  • pnpm --filter @objectstack/example-showcase typecheck → clean
  • pnpm --filter @objectstack/example-showcase validate → exit 0 (only pre-existing unrelated warnings)
  • node scripts/check-nul-bytes.mjs → OK

Notes

  • Changeset: none. examples/app-showcase is private: true and publishes nothing, so this is the skip-changeset label route (label applied on this PR).
  • Scope: src/system/connectors/ is untouched — that is batch-mate Showcase REST connectors hard-wire baseUrl to http://127.0.0.1:3000, so self-ping flows fail fetch failed on any isolated instance — a port mismatch, not an egress block #7538's baseUrl fix. origin/main was merged before opening this PR. The test reads StatusApiConnector but asserts only the flow-owned path (/api/v1/health), so it stays green across an env-overridable baseUrl.
  • Checklist: docs/qa/platform-checklist/areas/automation.json (connector-dispatch-matrix) asserts that the rest ping and declarative ping both record GET /api/v1/health{status:'ok'}. Under route 1 that clause becomes true as written, so it needed no edit — route 2 would have required changing it.

Generated by Claude Code

claude added 2 commits August 11, 2026 08:57
…T ping flows (#7542)

`TaskCompletedRestPingFlow` and `ShowcaseDeclarativeConnectorPingFlow` both
claimed in their source comments that the call and its `{ status: 'ok' }`
response were captured on the flow run. Neither declared any variables, and the
engine collects `run.output` from declared `isOutput` variables only — so
`run.output` came back empty and the comment pointed the next reader at an
engine bug that does not exist.

Both flows now declare the output variable they were evidently meant to carry,
mirroring the sibling `ShowcaseMcpConnectorEchoFlow`. The name follows what the
step actually produces: the `rest` connector's `request` action returns
`{ status, ok, body }`, written back under `${nodeId}.${key}`, and both flows'
connector node is `ping` — so `ping.body` is the parsed health payload.

New test drives the real flow definitions through a real `AutomationEngine`
with the real `createRestConnector` / `createRestProviderFactory` bundles
(only `fetch` stubbed) and content-pins `run.output` to `{ status: 'ok' }`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015fkdTyGmMD5s8ZtEifvuGy
@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 11, 2026 8:58am

Request Review

@os-help os-help added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed size/m labels Aug 11, 2026 — with Claude
@os-help
os-help marked this pull request as ready for review August 11, 2026 09:39
@os-help
os-help added this pull request to the merge queue Aug 11, 2026
Merged via the queue into main with commit ae66145 Aug 11, 2026
32 checks passed
@os-help
os-help deleted the claude/issue-7542-showcase-flow-isoutput branch August 11, 2026 09:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

2 participants