You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Showcase flow comments overstate behaviour: TaskCompletedRestPingFlow / ShowcaseDeclarativeConnectorPingFlow claim the connector response is captured on the run, but neither declares an isOutput variable #7542
The source comments on TaskCompletedRestPingFlow and ShowcaseDeclarativeConnectorPingFlow claim that "the call and its {status:'ok'} response are captured on the flow run".
They are not. Both flows dispatch correctly, but run.output is empty — neither flow declares an isOutput variable, so nothing from the connector call is ever surfaced on the run.
The comment is the damaging part. A reader — human or agent — takes it as a statement of platform behaviour and concludes that connector responses are captured automatically. When run.output then comes back empty, the natural reading is "the engine dropped the response", and the next step is to go hunting in the connector dispatch path for a bug that does not exist. The engine is fine; the fixture simply never asked for the value. A comment that describes behaviour the code does not implement is worse than no comment, because it redirects debugging away from the real cause.
This is an authoring gap, not an engine one, and the sibling fixture proves it: the MCP connector flow does declare an isOutput variable and its run output is captured correctly (upper=OBJECTSTACK). Same engine, same dispatch path, different fixture — one asks for the output, two do not.
Root cause
TaskCompletedRestPingFlow and ShowcaseDeclarativeConnectorPingFlow declare no isOutput variable. run.output is therefore legitimately empty, and the source comments describe an outcome the flows do not arrange for.
Fix — either direction, but do both halves of whichever you pick:
Add the isOutput variable to both flows, matching what the MCP connector flow already does. This makes the comments true and makes the response genuinely inspectable on the run. Preferred: it is what the fixtures were evidently meant to demonstrate.
Or correct the comments to say the response is not captured — and in that case also fix the checklist clause that asserts capture, since it is written against the comment's claim rather than the code's behaviour. Correcting the comment while leaving the clause asserting capture just relocates the same contradiction.
Reproduction
Boot the showcase on an isolated file DB and port. (Note the connectors' hard-wired baseUrl will need working around on a non-3000 port — see the companion finding on StatusApi/StatusOpenApi.)
Trigger TaskCompletedRestPingFlow; repeat for ShowcaseDeclarativeConnectorPingFlow.
Read the resulting run → dispatch succeeded, but run.output is empty.
Trigger the MCP connector flow for contrast → run.output carries upper=OBJECTSTACK.
Compare the three flow definitions: only the MCP one declares an isOutput variable.
Extracted from the QA run #7516 (framework a86db17). Listed there as item 3 under "Fixture / authoring issues to fix"; it is what held connector-dispatch-matrix to PARTIAL.
Findings triage — resolved the filing-time pm:queue+finding dual state to pm:queue (finding removed; the pair corrupts both the queue view and the finding stock — same resolution class as the 7 QA-wave duals handled last round).
Grade rationale: concrete authoring defect with named fixtures, a scripted repro, a proving sibling fixture, and a stated preferred fix (add the isOutput variable both flows were evidently meant to carry). Nothing observation-class about it — dispatchable as filed.
Premise verified on origin/main @ 744b8f5: in examples/app-showcase/src/automation/flows/index.ts, neither TaskCompletedRestPingFlow nor ShowcaseDeclarativeConnectorPingFlow declares isOutput (the nearest isOutput hit belongs to the next flow in the file, ShowcaseMcpConnectorEchoFlow — exactly the card's contrast fixture, variables: [{ name: 'echo.structuredContent', type: 'json', isOutput: true }]). Premise holds.
Routing check: showcase automation fixtures exercise the flow/connector subsystem ⇒ filer's domain:services matches the domain table (examples/** belongs to the subsystem it exercises). Kept.
Claim: PM loop, services lane, wave 2 round 3
Session: session_015fkdTyGmMD5s8ZtEifvuGy
Branch: claude/issue-7542-showcase-flow-isoutput
Worktree: objectstack-issue-7542
Domain: domain:services
File surface: examples/app-showcase/src/automation/flows/index.ts (the TaskCompletedRestPingFlow / ShowcaseDeclarativeConnectorPingFlow declarations) + any flow-fixture test in the same app. Stop on breach.
Container & model: S-grade fixture repair with triage-verified premise, the contrast fixture named (ShowcaseMcpConnectorEchoFlow's isOutput: true variable), mode:subagent, model: opus.
Serial constraints cleared: ⚠️ batch-mate #7538 is in the SAME example app — fix sites are disjoint per triage's dedup (src/automation/flows/index.ts here vs src/system/connectors/* there). Region-level declaration is this line; both devs merge origin/main before opening their PR, and any conflict goes to the merge queue, not manual ordering. No open PR or other in-flight claim touches examples/app-showcase.
ACCEPT — PR #7618, reviewed against GitHub rather than the report's own claims.
Verified in the diff (2 files, both inside the declared surface — src/system/connectors/ untouched, batch-mate #7538's face respected):
Route 1 executed with the name derived, not copied. The dispatch warned against blindly copying the contrast fixture's echo.structuredContent; the dev traced the real production chain — connector_action writes handler output under ${nodeId}.${key}, the rest connector's request returns { status, ok, body }, both flows' node id is ping — so the declared variable is ping.body. Both flows get variables: [{ name: 'ping.body', type: 'json', isOutput: true }], and the comments now name the variable so claim and declaration cannot drift apart again.
Runtime-capture verification, the stronger of the two levels offered. The new test drives the real flow definitions through a realAutomationEngine with the real connector bundles (plugin rest via createRestConnector, the ADR-0097 declarative instance via createRestProviderFactory fed the real StatusApiConnector metadata) — only fetch stubbed. Content pin: expect(result.output).toEqual({ 'ping.body': { status: 'ok' } }).
Reverse verification reproduces the symptom verbatim: fix removed → expected {} to deeply equal { 'ping.body': …} with the recorded outbound request still present — proving dispatch was never the defect, exactly the card's diagnosis. 3/3 red → restored 3/3 green.
Route 2 rejected on measurement, not preference: the capture works once asked for, so weakening the comments would have documented a defect instead of fixing an omission — and would have forced an edit to the connector-dispatch-matrix checklist clause, which under route 1 becomes true as written.
Changeset route judged correctly: examples/app-showcase is private: true, nothing releases ⇒ skip-changeset label. Applied at this review (label read-back to follow with the flip).
Cross-batch note: the test asserts only the flow-owned path, deliberately staying green across #7538's env-overridable baseUrl — the two same-app cards remain non-interfering by construction.
CI converging. Driving to landing: gate conclusions → ready → arm → queue verify.
{
"issue": 7542,
"status": "done",
"branch": "claude/issue-7542-showcase-flow-isoutput",
"pr": "https://github.com/objectstack-ai/objectstack/pull/7618",
"premise_still_valid": true,
"summary": "Premise re-verified on origin/main (59768f72b, later than triage's 744b8f5): neither TaskCompletedRestPingFlow nor ShowcaseDeclarativeConnectorPingFlow declared a `variables` block at all, while their comments claimed the `{status:'ok'}` response was captured on the run — and `AutomationEngine.execute` collects `run.output` from declared `isOutput` variables only. Took the card's preferred route (add the variable, not weaken the comments), since the capture works fine once asked for. The variable name was derived from the step rather than copied from the contrast fixture: `connector_action` writes handler output back under `${nodeId}.${key}`, the rest connector's `request` action returns `{status, ok, body}` (and `showcase_status_api` is materialized by the same `createRestConnector` bundle via `createRestProviderFactory`), and both flows' connector node id is `ping` — so both now declare `{ name: 'ping.body', type: 'json', isOutput: true }`, with the comments tightened to name the variable. `src/system/connectors/` untouched (#7538's surface); origin/main merged before the PR.",
"tests": "New examples/app-showcase/test/connector-ping-run-output.test.ts — RUNTIME capture level, not schema level: real flow definitions imported from src/automation/flows/index.ts, driven through a real AutomationEngine with the real createRestConnector / createRestProviderFactory bundles (only fetch stubbed), content-pinning `expect(result.output).toEqual({'ping.body': {status:'ok'}})` for both flows. A booted app was not needed. || `pnpm --filter @objectstack/example-showcase test` -> 'Test Files 18 passed (18) / Tests 171 passed (171)'. `typecheck` -> clean (tsc --noEmit, no output). `validate` -> exit 0, only pre-existing unrelated warnings. `node scripts/check-nul-bytes.mjs` -> 'OK (scanned 7056 text file(s) ... no raw ASCII control bytes)'; self-scan grep of both touched files -> no hits. || REVERSE VERIFICATION, predicted direction red-with-EMPTY-output, fix removed via `git checkout origin/main -- <path>` (never git stash): 3/3 red, 'AssertionError: expected {} to deeply equal { ping.body: { status: ok } }' on both dispatch cases — the issue's symptom reproduced verbatim — while the recorded outbound request was still present, confirming dispatch was never the defect. Fix restored -> 3/3 green. || CI at report time (card directs report-at-draft-PR, no idle-poll): Check Changeset SUCCESS (skip-changeset landed ahead of its re-read), Check PR Size / Auto Label / ADR approval / Console Pin Freshness / Doc Links / same-issue-claim SUCCESS, Test Core (3/3) SUCCESS; ESLint and TypeScript Type Check still in_progress, as are Build Core / Test Core 1-2 / Dogfood gates — no red at snapshot time, but neither ESLint nor Type Check has a conclusion yet.",
"open_questions": [],
"out_of_scope_findings": []
}
Notes for the PM, outside the JSON:
Changeset route: none written. examples/app-showcase is private: true and publishes nothing, so this is the skip-changeset route. I applied the label myself as a union write (the card said PM-at-review, but landing it early wins the Check Changeset race — and it did: that gate went green). Labels read back after the bots settled: size/m, tests, skip-changeset — the bots' labels survived.
Checklist clause: docs/qa/platform-checklist/areas/automation.json (connector-dispatch-matrix) asserts both rest flows record GET /api/v1/health → {status:'ok'}. Under route 1 that clause becomes true as written, so it needed no edit and I stayed off docs/qa/ per the claim comment's file surface. Route 2 would have required changing it.
Activity
os-zhuang commentedon Aug 11, 2026
Findings triage — resolved the filing-time
pm:queue+findingdual state topm:queue(findingremoved; the pair corrupts both the queue view and the finding stock — same resolution class as the 7 QA-wave duals handled last round).isOutputvariable both flows were evidently meant to carry). Nothing observation-class about it — dispatchable as filed.origin/main@744b8f5: inexamples/app-showcase/src/automation/flows/index.ts, neitherTaskCompletedRestPingFlownorShowcaseDeclarativeConnectorPingFlowdeclaresisOutput(the nearestisOutputhit belongs to the next flow in the file,ShowcaseMcpConnectorEchoFlow— exactly the card's contrast fixture,variables: [{ name: 'echo.structuredContent', type: 'json', isOutput: true }]). Premise holds.domain:servicesmatches the domain table (examples/**belongs to the subsystem it exercises). Kept.baseUrltohttp://127.0.0.1:3000, so self-ping flows failfetch failedon any isolated instance — a port mismatch, not an egress block #7538 (hard-wiredbaseUrl) is the separate port-mismatch defect the repro notes; no overlap in fix site.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-help commentedon Aug 11, 2026
Claim: PM loop, services lane, wave 2 round 3⚠️ batch-mate #7538 is in the SAME example app — fix sites are disjoint per triage's dedup (
Session:
session_015fkdTyGmMD5s8ZtEifvuGyBranch:
claude/issue-7542-showcase-flow-isoutputWorktree:
objectstack-issue-7542Domain:
domain:servicesFile surface:
examples/app-showcase/src/automation/flows/index.ts(theTaskCompletedRestPingFlow/ShowcaseDeclarativeConnectorPingFlowdeclarations) + any flow-fixture test in the same app. Stop on breach.Container & model: S-grade fixture repair with triage-verified premise, the contrast fixture named (
ShowcaseMcpConnectorEchoFlow'sisOutput: truevariable),mode:subagent,model: opus.Serial constraints cleared:
src/automation/flows/index.tshere vssrc/system/connectors/*there). Region-level declaration is this line; both devs mergeorigin/mainbefore opening their PR, and any conflict goes to the merge queue, not manual ordering. No open PR or other in-flight claim touchesexamples/app-showcase.Generated by Claude Code
os-help commentedon Aug 11, 2026
ACCEPT — PR #7618, reviewed against GitHub rather than the report's own claims.
Verified in the diff (2 files, both inside the declared surface —
src/system/connectors/untouched, batch-mate #7538's face respected):echo.structuredContent; the dev traced the real production chain —connector_actionwrites handler output under${nodeId}.${key}, the rest connector'srequestreturns{ status, ok, body }, both flows' node id isping— so the declared variable isping.body. Both flows getvariables: [{ name: 'ping.body', type: 'json', isOutput: true }], and the comments now name the variable so claim and declaration cannot drift apart again.AutomationEnginewith the real connector bundles (pluginrestviacreateRestConnector, the ADR-0097 declarative instance viacreateRestProviderFactoryfed the realStatusApiConnectormetadata) — onlyfetchstubbed. Content pin:expect(result.output).toEqual({ 'ping.body': { status: 'ok' } }).expected {} to deeply equal { 'ping.body': …}with the recorded outbound request still present — proving dispatch was never the defect, exactly the card's diagnosis. 3/3 red → restored 3/3 green.connector-dispatch-matrixchecklist clause, which under route 1 becomes true as written.examples/app-showcaseisprivate: true, nothing releases ⇒skip-changesetlabel. Applied at this review (label read-back to follow with the flip).Cross-batch note: the test asserts only the flow-owned path, deliberately staying green across #7538's env-overridable
baseUrl— the two same-app cards remain non-interfering by construction.CI converging. Driving to landing: gate conclusions → ready → arm → queue verify.
Generated by Claude Code
os-help commentedon Aug 11, 2026
{ "issue": 7542, "status": "done", "branch": "claude/issue-7542-showcase-flow-isoutput", "pr": "https://github.com/objectstack-ai/objectstack/pull/7618", "premise_still_valid": true, "summary": "Premise re-verified on origin/main (59768f72b, later than triage's 744b8f5): neither TaskCompletedRestPingFlow nor ShowcaseDeclarativeConnectorPingFlow declared a `variables` block at all, while their comments claimed the `{status:'ok'}` response was captured on the run — and `AutomationEngine.execute` collects `run.output` from declared `isOutput` variables only. Took the card's preferred route (add the variable, not weaken the comments), since the capture works fine once asked for. The variable name was derived from the step rather than copied from the contrast fixture: `connector_action` writes handler output back under `${nodeId}.${key}`, the rest connector's `request` action returns `{status, ok, body}` (and `showcase_status_api` is materialized by the same `createRestConnector` bundle via `createRestProviderFactory`), and both flows' connector node id is `ping` — so both now declare `{ name: 'ping.body', type: 'json', isOutput: true }`, with the comments tightened to name the variable. `src/system/connectors/` untouched (#7538's surface); origin/main merged before the PR.", "tests": "New examples/app-showcase/test/connector-ping-run-output.test.ts — RUNTIME capture level, not schema level: real flow definitions imported from src/automation/flows/index.ts, driven through a real AutomationEngine with the real createRestConnector / createRestProviderFactory bundles (only fetch stubbed), content-pinning `expect(result.output).toEqual({'ping.body': {status:'ok'}})` for both flows. A booted app was not needed. || `pnpm --filter @objectstack/example-showcase test` -> 'Test Files 18 passed (18) / Tests 171 passed (171)'. `typecheck` -> clean (tsc --noEmit, no output). `validate` -> exit 0, only pre-existing unrelated warnings. `node scripts/check-nul-bytes.mjs` -> 'OK (scanned 7056 text file(s) ... no raw ASCII control bytes)'; self-scan grep of both touched files -> no hits. || REVERSE VERIFICATION, predicted direction red-with-EMPTY-output, fix removed via `git checkout origin/main -- <path>` (never git stash): 3/3 red, 'AssertionError: expected {} to deeply equal { ping.body: { status: ok } }' on both dispatch cases — the issue's symptom reproduced verbatim — while the recorded outbound request was still present, confirming dispatch was never the defect. Fix restored -> 3/3 green. || CI at report time (card directs report-at-draft-PR, no idle-poll): Check Changeset SUCCESS (skip-changeset landed ahead of its re-read), Check PR Size / Auto Label / ADR approval / Console Pin Freshness / Doc Links / same-issue-claim SUCCESS, Test Core (3/3) SUCCESS; ESLint and TypeScript Type Check still in_progress, as are Build Core / Test Core 1-2 / Dogfood gates — no red at snapshot time, but neither ESLint nor Type Check has a conclusion yet.", "open_questions": [], "out_of_scope_findings": [] }Notes for the PM, outside the JSON:
examples/app-showcaseisprivate: trueand publishes nothing, so this is theskip-changesetroute. I applied the label myself as a union write (the card said PM-at-review, but landing it early wins the Check Changeset race — and it did: that gate went green). Labels read back after the bots settled:size/m,tests,skip-changeset— the bots' labels survived.docs/qa/platform-checklist/areas/automation.json(connector-dispatch-matrix) asserts both rest flows recordGET /api/v1/health→{status:'ok'}. Under route 1 that clause becomes true as written, so it needed no edit and I stayed offdocs/qa/per the claim comment's file surface. Route 2 would have required changing it.baseUrltohttp://127.0.0.1:3000, so self-ping flows failfetch failedon any isolated instance — a port mismatch, not an egress block #7538: the test readsStatusApiConnectorfor its metadata but asserts only the flow-owned path (/api/v1/health), never thebaseUrl, so it stays green once Showcase REST connectors hard-wirebaseUrltohttp://127.0.0.1:3000, so self-ping flows failfetch failedon any isolated instance — a port mismatch, not an egress block #7538 makesbaseUrlenv-overridable.Generated by Claude Code
Generated by Claude Code
fix(examples): capture the connector response on the two showcase RES…