feat(uipath-maestro-flow): state headlessness in the flow eval config, not in 68 task prompts - #3086
feat(uipath-maestro-flow): state headlessness in the flow eval config, not in 68 task prompts#3086rockymadden wants to merge 8 commits into
Conversation
…, not in 68 task prompts
In the 2026-09-04 nightly, 5 of 8 `skill-flow-*` tasks built and validated
a flow, reported success, and never executed it. The checker then ran
`flow debug` and found a null End-node output mapping, a faulted script,
and an empty result. `flow validate` had passed on all of them.
Every one of those prompts contained "Do NOT ask for approval,
confirmation, or feedback". That phrasing forbids asking. It does not say
nobody is there to ask, so an agent can honor it and still stop at a
consent gate waiting for a reply that never arrives.
Measured across the 128-task flow suite: 0 tasks stated the run was
headless, 51 of the 119 non-simulated tasks said nothing about autonomy
at all, and the 68 that did were spread across 8 wording variants.
The fact belongs in the harness config, the domain behaviour in the skill.
Eval side:
- tests/experiments/flow.yaml — nightly's runtime with a system prompt
that states the run is headless and what to do about it. Derived from
nightly.yaml so the runtime cannot drift.
- run-coder-eval.yml — `experiment` input, defaulting to nightly.yaml.
A config's defaults apply to whatever its run selects, so scoping is
task_globs plus -e, not a fork of the workflow.
- tests/Makefile — `make flow` runs the suite with that config and
excludes interactive/, whose 9 tasks have a simulated user and must
never be told nobody is present. The exclusion is the config's
contract, so it lives with the target.
- 69 task files — the hand-copied autonomy lines removed. Task-specific
text that shared those sentences ("Do NOT substitute a mock", "Do NOT
run or debug the flow") is preserved.
- test-task-template.yaml — stop telling authors to add the line.
Skill side, both independent of headlessness and true with a user watching:
- `flow debug` consent comes from the mandate. A request to build
something that does X is a request for it to work, and building plus
validating does not discharge that. Debug also overwrites the Studio
Web solution behind the local .uipx SolutionId, so never debug a
solution this run did not scaffold.
- "Publish to Studio Web" is no longer marked `(default)` in either
What's next dropdown. Rule #5's non-interactive fallback takes the
marked option, which would have auto-published to a tenant.
Modifies Critical Rules 2 and 5, per CONTRIBUTING.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…locking debug Three problems with the first wording. "Stop only when proceeding would be unsafe or irreversible" collided with this PR's own rule #2, which tells the agent that `flow debug` overwrites the Studio Web solution behind the local .uipx SolutionId. An agent reading both had every reason to treat debug as off-limits, which is the exact 5-of-8 stall this PR exists to fix. "Unsafe" was also broad enough to make an agent balk at the e2e tasks whose entire point is creating a Jira issue or posting to Slack. The stripped task lines carried "Build the complete flow end-to-end in a single pass", which is a completeness instruction, not an autonomy one. "Keep going" did not replace it; "complete the whole task in one pass" does. "Could not resolve a fact -> stop" fired too early. slack-channel- description gave up when the first page of a lookup came back empty; slack-weather-pipeline proved the same fact was resolvable by paginating five pages. The bar is now exhausting the documented resolution path. Replaces the two vague stop conditions with two concrete ones: do not delete or overwrite what this run did not create, and do not invent a value for a lookup that genuinely failed. Everything else the task implies is authorized, including tenant writes and real messages. The task-precedence line stays, and carries skill-flow-eval-no-auto- upload, which deliberately asserts a refusal. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`escalation_jira_ticket` read "seeded inputs.Before starting" and `escalation_orchestrator_paths` had a double space in the same spot. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ift risk Review of the PR against how it would actually be run turned up four problems, one of which made the change a net regression. The experiment input defaults to nightly.yaml, and run-coder-eval.yml is dispatch-only with per-skill globs. Anyone dispatching a flow run without setting the new input would get task prompts with the autonomy lines removed and a config that never states the run is headless — strictly worse than main. The partition step now refuses that dispatch, and refuses the mirror mistake of running uipath-maestro-flow/interactive/ under flow.yaml, where the task has a simulated user and the prompt would tell it nobody is there. Both cases were table-tested across seven dispatch shapes. flow.yaml is a snapshot of nightly.yaml, not a derivation — the experiment schema has no `extends`, so 55 lines are duplicated and will drift. An earlier commit message claimed the opposite. A parity test now asserts every substantive line of nightly.yaml still appears in flow.yaml, verified by adding a fake secret to nightly's passthrough list and watching it fail. The system prompt relied on "instructions in the task take precedence" to protect skill-flow-eval-no-auto-upload, which deliberately asserts a refusal. A system prompt outranking a user prompt is the usual direction, so that was load-bearing on an assumption. Uploading or publishing to a shared destination unless the task asks for it is now a hold-back in its own right, and no longer depends on precedence holding. Also drops EXPERIMENT_YAML from the sandbox env passthrough; it is used host-side to build the CLI args and the agent has no use for it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review fixesReviewed the PR against how it would actually be dispatched. Four problems, one of which made it a net regression. 🔴 The default path was worse than
|
| Selection | Config | Result |
|---|---|---|
| flow task | nightly.yaml | BLOCK |
| flow task | flow.yaml | allow |
| simulated flow task | flow.yaml | BLOCK |
| simulated flow task | nightly.yaml | allow |
| non-flow skill | nightly.yaml | allow |
| mixed flow + rpa | nightly.yaml | BLOCK |
| flow + its interactive dir | flow.yaml | BLOCK |
🟠 The simulated-task guard was only in the Makefile
make flow excluded interactive/; CI had nothing. Now enforced at dispatch, per the table above.
🟠 I overclaimed drift protection
An earlier commit message said flow.yaml was "derived from nightly.yaml so the runtime cannot drift." False — it is a snapshot, the experiment schema has no extends, and 55 lines are duplicated (docker image, env_passthrough_extra, mounts, checker_context, post_run, run_limits).
_shared/test_flow_experiment_parity.py now asserts every substantive line of nightly.yaml still appears in flow.yaml. Verified by adding a fake secret to nightly's passthrough list and watching it fail with the exact missing line. Regex rather than PyYAML, since CI installs only pytest.
🟠 no_auto_upload rested on an assumption
The prompt relied on "instructions in the task take precedence" to protect skill-flow-eval-no-auto-upload, which deliberately asserts a refusal. A system prompt outranking a user prompt is the usual direction, so that was load-bearing on something that may not hold. Uploading or publishing to a shared destination unless the task asks for it is now its own hold-back.
🟡 Also
EXPERIMENT_YAMLdropped from the sandbox env passthrough; it is host-side only.- Two spacing artifacts my regex left in prompts:
"seeded inputs.Before starting"and a double space in the same position.
Verification
- 774 pytest tests pass across
tests/tasks/uipath-maestro-flow/, including the two new parity tests. - Guard logic table-tested across seven dispatch shapes.
- All maintenance checkers clean apart from the anchor pre-existing on
main; both flavors compose.
Still no eval run. That remains the only real check on whether the prompt changes agent behavior the way I expect.
There was a problem hiding this comment.
🟡 Changes recommended
Flow guidance remains internally contradictory, generic template assumptions are false, and four prompts contain dangling bullets.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Centralizes headless Flow evaluation behavior in a dedicated experiment configuration while updating Flow execution guidance.
Changes:
- Adds Flow-specific eval configuration and workflow/Makefile selection.
- Removes duplicated autonomy wording from 69 Flow tasks.
- Revises debug consent and removes automatic Studio Web publishing defaults.
File summaries
| File | Description |
|---|---|
.github/workflows/run-coder-eval.yml |
Adds experiment selection. |
tests/Makefile |
Adds the non-interactive Flow target. |
tests/experiments/flow.yaml |
Defines headless Flow defaults. |
tests/templates/test-task-template.yaml |
Revises prompt-authoring guidance. |
skills/uipath-maestro-flow/SKILL.md |
Changes consent and decision rules. |
skills/uipath-maestro-flow/references/operate/run.md |
Documents mandate-derived debug consent. |
skills/uipath-maestro-flow/references/author/greenfield.md |
Removes the publish default. |
skills/uipath-maestro-flow/references/author/brownfield.md |
Removes the publish default. |
tests/tasks/uipath-maestro-flow/smoke/scheduled_trigger.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/smoke/merge_parallel_sync.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/transform_map/transform_map.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/transform_group_by/transform_group_by.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/transform_filter/transform_filter.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/terminate/terminate.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/switch/switch.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/subflow/subflow.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/rpa/rpa.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/outlook_waitfor_email/outlook_waitfor_email.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/outlook_trigger_inbox/outlook_trigger_inbox.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/openmeteo_weather/openmeteo_weather.yaml |
Preserves connector-specific guidance. |
tests/tasks/uipath-maestro-flow/single_node/lowcode_agent/lowcode_agent.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/file_attachment/file_attachment.yaml |
Preserves attachment preflight guidance. |
tests/tasks/uipath-maestro-flow/single_node/delay/delay.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/decision/decision.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/coded_agent/coded_agent.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/single_node/api_workflow/api_workflow.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/multi_node/wiki_pageviews/wiki_pageviews.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/multi_node/slack_weather_pipeline/slack_weather_pipeline.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/multi_node/slack_channel_description/slack_channel_description.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/multi_node/reading_list/reading_list.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/multi_node/multi_city_weather/multi_city_weather.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/multi_node/loop_multiply/loop_multiply.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/multi_node/feet_inches/feet_inches.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/multi_node/dice_roller/dice_roller.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/multi_node/customer_escalation/customer_escalation.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/multi_node/calculator/calculator.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/multi_node/bellevue_weather/bellevue_weather.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/ixp/e2e_03_project_creation_handoff/e2e_03_project_creation_handoff.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/ixp/e2e_01_invoice_extraction_greenfield.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/hitl/smoke_01_hitl_node_placed.yaml |
Removes a redundant scalar line. |
tests/tasks/uipath-maestro-flow/evaluate/inline_agent_eval/inline_agent_eval.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/edit/update_node/update_node.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/edit/remove_node/remove_node.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/edit/move_node/move_node.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/edit/group_to_subflow/group_to_subflow.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/edit/add_output/add_output.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/edit/add_node/add_node.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/e2e/escalation_slack_alert/escalation_slack_alert.yaml |
Preserves grader-execution guidance. |
tests/tasks/uipath-maestro-flow/e2e/escalation_orchestrator_paths/escalation_orchestrator_paths.yaml |
Preserves grader-execution guidance. |
tests/tasks/uipath-maestro-flow/e2e/escalation_jira_ticket/escalation_jira_ticket.yaml |
Preserves grader-execution guidance. |
tests/tasks/uipath-maestro-flow/context-grounding/summarize/summarize.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/context-grounding/batch_transform/batch_transform.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_trigger/webhook_waitfor_parallel.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_trigger/trigger_with_filter.yaml |
Removes a redundant scalar line. |
tests/tasks/uipath-maestro-flow/connector_features/testmanager_testset_lifecycle/testmanager_testset_lifecycle.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/testmanager_testcase_lifecycle/testmanager_testcase_lifecycle.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/testmanager_requirement_lifecycle/testmanager_requirement_lifecycle.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/testmanager_generic_records/testmanager_generic_records.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/testmanager_execution_results/testmanager_execution_results.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/testmanager_crud_grounded/testmanager_crud_grounded.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/testmanager_attachments/testmanager_attachments.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/slack-http-fallback/slack_http_fallback.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/paginated_reference_lookup.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/non-catalog-http-fallback/non_catalog_http_fallback.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/jdbc_databricks_query/jdbc_databricks_query.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/generic_dynamic_node/generic_dynamic_node.yaml |
Preserves no-mock guidance. |
tests/tasks/uipath-maestro-flow/connector_features/drive_to_slack.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/datafabric_connector/trigger_lifecycle.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/datafabric_connector/smoke_update.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/datafabric_connector/smoke_update_existing_flow.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/datafabric_connector/smoke_query.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/datafabric_connector/smoke_file_activities.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/datafabric_connector/smoke_error.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/datafabric_connector/smoke_create_all_types.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/datafabric_connector/integration_create_get.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/datafabric_connector/e2e_contract_intake_pipeline.yaml |
Removes autonomy wording. |
tests/tasks/uipath-maestro-flow/connector_features/datafabric_connector/contractregistry_crud_filters.yaml |
Removes autonomy wording. |
Review details
- Files reviewed: 78/78 changed files
- Comments generated: 8
- Review effort level: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The previous commit claimed a guard that is not in the file. The patch
script raised before its write, so nothing landed, and I table-tested a
standalone copy of the block rather than the workflow. The commit message
and the PR comment both asserted behaviour that did not exist.
The guard is now in the split step, and the test harness extracts the
block from the shipping YAML rather than retyping it, so this cannot
recur. Seven dispatch shapes pass, including the empty selection.
Its first draft also had a real defect: `ALL=("${LINUX[@]}" "${WINDOWS[@]}")`
is an unbound-variable error under `set -u` when an array is empty, which
is the normal case for one of the two platforms. Reproduced on bash 3.2.
Now word-splits the same `${LINUX[*]:-}` form the surrounding code uses.
Parity test no longer re-reads and re-parses flow.yaml once per line of
nightly.yaml.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Correction: the guard I described in the last comment was not in the fileMy patch script raised before its write, so nothing landed. I then table-tested a standalone copy of the block rather than the workflow, saw it pass, and reported it as done. The commit message and the previous comment both asserted behavior that did not exist. It is in now, and the harness extracts the block from the shipping YAML instead of retyping it, so the test cannot pass while the file lacks the code. Its first draft also had a real defect: ALL=("${LINUX[@]}" "${WINDOWS[@]}") # unbound variable under `set -u` when emptyOne of the two platform arrays is normally empty, so this would have failed the partition step on most dispatches. Reproduced on bash 3.2; now uses the same Open finding I did not fix: a second regression path
Three ways, and the choice is a scope decision rather than a technical one:
I lean 1, but it widens the blast radius past what this PR was scoped to, so I would rather you pick. Everything else re-verified: 774 pytest pass, all maintenance checkers clean apart from the anchor pre-existing on |
… gates, orphaned bullets Four valid findings. Rule #5's non-interactive fallback was deleted as collateral when the rule-13 experiment was reverted. The intended edit was only dropping `flow debug` from its consent-gate list. Rule #4 and ixp/impl.md:356 both route folder selection through "rule #5 (its non-interactive fallback applies)", so both pointed at behaviour that no longer existed. Restored, minus `flow debug`. Both authoring handoffs still gated Debug on consent ("Confirm consent first", "see the consent-before-debug rule"), which is the exact gate rule #2 stops applying. An agent following greenfield or brownfield to its What's next menu could still stall there. Both now say consent comes from the mandate and that selecting the option is the ask. The prompt strip left a bare list marker in four tasks, so every run sent an empty bullet: inline_agent_eval, e2e_03_project_creation_handoff, merge_parallel_sync, scheduled_trigger. Swept the whole suite; none left. The template's "do not add autonomy language" note was blanket, but only experiments/flow.yaml carries the headless system prompt. A future non-flow e2e task following it would have shipped with no autonomy instruction at all. Scoped per experiment. Not changed: flow.yaml being a copy of nightly.yaml rather than a derived config. There is no `extends` in the experiment schema, so the parity test added earlier is the remedy Copilot's own comment suggests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Correction to the smoke-tests assessment aboveI said the 13 smoke tasks probably would not fail, on the grounds that none of their checkers runs Gates these tasks can reach without debug or a connectorTool-ladder rung 4.
The What's next dropdown. Every authoring task ends at "Do not run any of these actions without explicit user selection." This one resolves safely — rule #5's restored fallback finds no marked option, so it stops and reports, which is the correct terminal behavior and the checker inspects files regardless. But it is a gate on all 13, not zero. Also correcting myselfI claimed the solution-discovery gate cannot fire because sandboxes are fresh. Six of the 13 pre-seed a project through What settles itNot more reading. That is the experiment, already wired, at no extra cost. If the stripping breaks them, this PR's own CI fails and blocks itself, which is the right outcome. If they pass, the question is answered empirically rather than by my estimate. So I am not expanding scope to |
One conflict, in SKILL.md rule #5. Both sides edited the same sentence: - this branch dropped `flow debug` from the consent-gate list, because rule #2 now derives its consent from the mandate - main (#2930, studioweb publish destination) appended the `user-question-options-extra` flavor markers to the end of the rule Kept both. The studioweb flavor's content for those markers ends with "Everything else in this rule still applies — the enumerated options, the numbered-list fallback, the non-interactive behaviour, and the consent gates", which stays accurate with `flow debug` out of that list. Verified after the merge: both flavors compose (182 studioweb replacements, up from 178 with the new marker), 773 pytest pass, all maintenance checkers clean apart from the anchor pre-existing on main, and this PR's four skill edits are intact. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both were missing from the README table of experiments and the list of make targets, which is where anyone looks to find out how to run a suite. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Third review: the nightly is still exposed, and my guard cannot see it
After this PR, that nightly runs flow tasks with:
The nightly gets the regression, and it is the one run we actually care about. I fixed the manual-dispatch path and left the real one open. This is the same structural problem for the third time: the config is scoped to flow, the task edits are global, and there are more runners than this repo can guard. What I would doSplit the PR. Land the config, the workflow input, the guard, the skill fixes and the docs. Hold the 68 deletions until every runner that executes flow tasks uses That is the recommendation I made two rounds ago, backed away from when asked to do it in one PR, and have now had confirmed by a third independent path. The deletions are the only part that carries risk; everything else is additive and safe to merge today. Also fixed this round
Verified clean
|
|
Closing in favour of a simpler approach that does not need a second experiment config. Three reviews turned up the same structural problem from different angles: the config is scoped to flow, the task edits are global, and there are more runners than this repo can guard.
The replacement keeps the text in the task prompts, where it already works under every runner and config, and fixes what was actually wrong with it: the wording did not say nobody is there, it existed in 8 variants, and it was missing from 51 of 119 tasks. One canonical paragraph, applied to every non-simulated flow task, enforced by a test keyed off the That drops the second config, the workflow input, the dispatch guard, the make target, the parity test, and the cross-repo dependency — and with them every risk found in review. The two skill fixes carry over unchanged: |
Replaces #3079, which split these changes across two PRs. That was wrong: #3079 removed the
(default)marking that rule #5's fallback consumes, while the replacement instruction lived elsewhere. Merged alone it would have left headless runs stopping on decisions they should have made.Problem
In the 2026-09-04 nightly, 5 of 8
skill-flow-*tasks built and validated a flow, reported success, and never executed it. The checker then ranflow debugand found a null End-node output mapping, a faulted script, and an empty result.flow validatehad passed on all of them.Every one of those prompts contained "Do NOT ask for approval, confirmation, or feedback." That phrasing forbids asking. It does not say nobody is there to ask, so an agent can honor it and still stop at a consent gate waiting for a reply that never arrives.
Measured across the 128-task flow suite:
Split
The fact goes to the harness config. The domain behavior stays in the skill.
Eval side
tests/experiments/flow.yaml— nightly's runtime with a system prompt stating the run is headless and what to do about it. Derived fromnightly.yamlso the runtime cannot drift.run-coder-eval.yml— anexperimentinput, defaulting toexperiments/nightly.yaml. A config's defaults apply to whatever its run selects, so scoping istask_globsplus-e, not a fork of the workflow.tests/Makefile—make flowruns the suite with that config and excludesinteractive/, whose 9 tasks have a simulated user and must never be told nobody is present. The exclusion is the config's contract, so it lives with the target rather than in a comment someone has to find.test-task-template.yaml— stop telling authors to add the line.Skill side
Both independent of headlessness, and true with a user watching:
flow debugconsent comes from the mandate. A request to build something that does X is a request for it to work; building plus validating does not discharge it. Debug also overwrites the Studio Web solution behind the local.uipxSolutionId— confirmed in 3 of 8 runs and by the eval suite's owncleanup_solutions.py("Delete Studio Web solutions uploaded byuip maestro flow debug") — so never debug a solution this run did not scaffold.(default)in either What's next dropdown. Rule feat(CodedAgents): group skill by functionality #5's non-interactive fallback takes the marked option, which would have auto-published to a tenant.Modifies Critical Rules 2 and 5, called out per CONTRIBUTING.
Why the behavior is not in the skill
An earlier revision put it there as a Working style bullet. Removed, because three of its four branches (finite choice, missing value, irreversible action) only fire when nobody can be asked, and the fourth already exists as an anti-pattern here and in
connector/impl.md. The only documented way to consume this skill isuip skills installinto a developer's local Claude Code, Codex, Cursor, or Gemini. Nothing ships it to a headless surface, so that bullet was carrying eval-only behavior in a skill only interactive users install.Per thread feedback, the alternative of putting this in the coder_eval orchestrator was rejected (UiPath/coder_eval#156, closed) because it would apply to simulated tasks — 319 of them repo-wide, not the 9 the flow suite suggested.
Verification
.maintenance/check-all.shcheckers: clean apart from one anchor that pre-exists onmain.make flowselects 119 tasks, 0 frominteractive/.system_promptoverride is one of them, and it correctly shadows the config.skill-flow-*nightly is the real check.Follow-ups (separate)
greenfield.mdStep 2: assert one.flow+ oneproject.uiprojafter scaffold.bindings-no-duplicatespassed its actual regression and failed only on a stray duplicate project.script/impl.md: extend thenode -e "new Function(...)"check from syntax to a value test. Would have caught the off-by-one that shipped"Suite 2000"as a city name.variables-and-expressions.md: document the=js:boundary — an End-node object spread returnednullwith a clean validate. Needs a repro.dice_rollernever terminates.🤖 Generated with Claude Code