Conversation
…mpletion gate The gate required an edge on `completed` (or the `outcome-completed` special case #1477 added, which only helps when an outcome is literally NAMED "Completed"). The SDK has two correct shapes for a human task, and that gate accepts only one of them: * the base node's 1.0 definition — and every variant: quick-form, action-app, document-validation — declares one source handle, `completed`; * `outcomePorts: true` / `exposeError: true` select the base node's 1.1/1.2 definition, whose ONLY source handle is `outcome-{item.id}` repeated over the outcomes. There is no `completed` handle there, and an edge to one is refused by `uip maestro flow validate` as an undeclared source handle. So the second shape could not pass, and the task's `initial_prompt` asks for neither — it describes approve/reject review and a downstream log step. Which shape the agent picks decided the grade: `skill-flow-e2e-devcon-expense-approval` scored 1.0 when the agent wrote the first shape and 0.37 the next run when it wrote the second, with nothing in the stack changed between them (flow-builder-sdk#718; `outcomePorts` shipped 2026-08-19 and the SDK's HITL docs are byte-identical across the two SDK versions involved). What the gate means to assert is that the review CONTINUES somewhere, so it now asserts that: `completed`, or any `outcome-<id>` edge. Nothing wired at all is still a failure, and the message names what it found. The upstream doc gap is fixed separately (flow-builder-sdk#724): hitl.md now says outcomePorts REPLACES the completed exit, and `flow check` refuses an edge to a handle the selected definition does not declare. Verified: the old checker answers `FAIL: HITL completed handle must be wired` on an outcome-port flow, the new one accepts it and reports the exits it found. The fixture helper takes the node type, version and exit ports so both shapes are covered; a no-continuation case pins the refusal. 11 passed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @dmetzgar's task in 3m 13s —— View job PR Review: fix(maestro-flow/e2e): accept per-outcome exits in the devcon HITL completion gateSummaryFixes a flaky e2e grade caused by the DevCon expense-approval checker only accepting the Change-by-Change Review1.
|
| Area | Status | Notes |
|---|---|---|
| Frontmatter | N/A | No skill doc changes |
| E2E Tests | OK | Two new tests cover both the accept and reject paths for the new shape |
| Skill Body | N/A | No SKILL.md changes |
| References & Assets | N/A | No reference changes |
| Repo Hygiene | OK | Changes scoped to two test files, no secrets, no cross-skill deps |
Issues for Manual Review
- Comment verbosity (check_devcon_expense_approval.py:120-139): The 20-line rationale comment is protective but long. Whether to trim is an editorial call — it doesn't affect correctness. Could compress to ~8 lines (the two shapes + the one-sentence failure history) without losing the "don't revert this" signal.
Conclusion
Clean fix. The logic is correct, the edge cases are handled, backward compatibility is preserved via defaults, and both directions (accept + reject) are tested. No issues to block on.
|
Closing in favour of #3180, which fixes the same gate more thoroughly and from the right premise. Reconciliation measured and written up in #3180 (comment). The short version:
The one piece worth lifting from here is the fixture parameterisation ( The SDK half of flow-builder-sdk#718 is merged as flow-builder-sdk#724; the remaining SDK-side gap — the quick-form and action-app variants cannot express per-outcome handles at all — is being filed separately. |
The DevCon HITL completion gate accepted only one of two correct authoring shapes, so the grade turned on which one the agent happened to pick.
The two shapes
completed.outcomePorts: true/exposeError: trueselect the base node's 1.1/1.2 definition, whose only source handle isoutcome-{item.id}, repeated over the outcomes. There is nocompletedhandle there, and an edge to one is refused byuip maestro flow validateas an undeclared source handle.The gate required
completed, or theoutcome-completedspecial case #1477 added — which only helps when an outcome is literally named "Completed", so an Approve/Reject design can never satisfy it. The task'sinitial_promptasks for neither shape; it describes approve/reject review plus a downstream log step.What that cost
skill-flow-e2e-devcon-expense-approvalscored 1.0 when the agent authored the first shape and 0.37 the next run when it authored the second — with nothing in the stack changed in between.outcomePortsshipped 2026-08-19, and the SDK's HITL docs are byte-identical across the two SDK versions involved (git diff v3.31.2 v5.0.9 -- references/hitl.mdis empty). Details in flow-builder-sdk#718.In the earlier passing comparison run, v1 emitted
…quick-form@1.0and v2 the base…human-in-the-loop@1.0— both oncompleted. Neither agent entered the failing shape, so the gate had never been exercised against it.The change
The gate now asserts what it means to assert — that the review continues somewhere: an edge on
completed, or anyoutcome-<id>edge. Nothing wired at all is still a failure, and the message names what it found instead of naming one handle.The success line no longer claims "uses v1.0 schema … wires completed"; it reports the exits it saw. Nothing in the repo asserted that string.
Verification
Same fixture, both checkers:
_flow_docnow takesnode_type,type_versionandexit_ports, defaulting to exactly the shape every existing test used, so the two new cases — the outcome-ports shape, and a no-continuation flow that must still fail — sit alongside unchanged coverage. 11 passed.Upstream half
The doc gap that sent the agent down the unsupported path is fixed separately in flow-builder-sdk#724:
hitl.mdnow states thatoutcomePortsreplaces thecompletedexit and how to choose between the shapes, andflow checkgainedHITL_COMPLETED_PORT_GONEso the SDK stops emitting an edge the product rejects. The two changes are independent — neither waits on the other.🤖 Generated with Claude Code