fix(uipath-maestro-flow): derive flow debug consent from the mandate, unmark the publish default - #3079
fix(uipath-maestro-flow): derive flow debug consent from the mandate, unmark the publish default#3079rockymadden wants to merge 4 commits into
flow debug consent from the mandate, unmark the publish default#3079Conversation
Review fixes pushedSelf-review found the first cut both wrong and too expensive. All 9 findings addressed. 🔴 CorrectnessC1 — the
The old text called the run "disposable" and exempt from the no-tenant-writes line. Debug now requires two tests, either failing is a Stop:
C2 — the read test misread two node shapes.
Exactly the right split: the 4 that needed a feedback loop get one, the HITL flow that hung the checker does not. C3 — detection was not evaluable. It required knowing the run is single-turn. Absence of a structured-question tool is sufficient; the conjunct is gone. 🟠 Cost and structureM2 — SKILL.md is always loaded. First cut: 21,655 → 28,376 bytes (+31%, ~1,700 tokens on every invocation, for a mode most runs are not in). Now +5% (22,745). The doctrine lives in M1 — violated M3 — body order. New top-level 🟡 Minorm1 router row added · m2 precedence now adjacent to each prohibition · m3 one consistent test (the exemption language is gone) · m4 dropdowns now state "Never mark an option in this table as a default" positively, so a future editor cannot re-add it by accident · m5 advisory criterion on Verification
Known gap
|
| Do not run any option without explicit user selection. No newline at end of file | ||
| Do not run any option without explicit user selection. | ||
|
|
||
| > **Never mark an option in this table as a default** — every one is a tenant write, and a marked default is what a non-interactive run takes. **No user?** Stop: report the completed edit and end the turn ([non-interactive.md](../shared/non-interactive.md)). No newline at end of file |
There was a problem hiding this comment.
Remove the never mark option comment.
|
|
||
| Do not run any of these actions without explicit user selection. Once the user picks an option, read [operate/CAPABILITY.md](../operate/CAPABILITY.md) and follow that capability's flow — do not run operate commands from inside this doc. | ||
|
|
||
| > **Never mark an option in this table as a default** — every one is a tenant write, and a marked default is what a non-interactive run takes. **No user?** Stop: report the completed build and end the turn ([non-interactive.md](../shared/non-interactive.md)). |
There was a problem hiding this comment.
Remove the comment about never mark an option.
| - **Cancel** — they meant to test something else (e.g., `flow debug`). | ||
| 3. **Wait for an explicit decision.** Do not infer one from context, prior commands, or comments in the project. | ||
|
|
||
| > **No user?** Stop, and it stays a Stop — the overwrite is recoverable only through the browser, by the user, after the fact. Do everything the eval needs that does not depend on the upload, then report it blocked and name the two unblocking moves (upload, or supply `--solution-id` / `--project-id`). `flow debug` performs this same Studio Web write, so it inherits this rule ([non-interactive.md](../shared/non-interactive.md)). |
There was a problem hiding this comment.
Do we really need the studio web details? Probably not. Just say plainly without details. Also, the flags and examples you cite are coupling to things that can drift. Consider and revise for maintainability.
There was a problem hiding this comment.
Rewritten plain. Dropped the Studio Web recovery mechanics and the --solution-id / --project-id flags. Now states the Stop, defers to the options already listed above it, and notes that flow debug performs the same write so it inherits the rule.
|
|
||
| 1. **Use `--output json`; prefer `--output-filter` for extraction.** Filters are global and run against the `Data` envelope, so expressions start at `Data` without a `Data.` prefix. Registry search returns a flat PascalCase array (`NodeType`, `DisplayName`, `Description`, `AvailableOnTenant`), not `Data.Nodes` or lowercase fields. Example: `uip maestro flow registry search <keyword> --output json --output-filter "[*].{NodeType:NodeType,DisplayName:DisplayName,Description:Description,AvailableOnTenant:AvailableOnTenant}"`. With `--local`, omit `AvailableOnTenant`. Use `python3 -c` or `jq` only after verifying shape and when JMESPath cannot express the transform. See [cli-conventions.md §3](references/shared/cli-conventions.md#3-prefer---output-filter-for-extraction). | ||
| 2. **Do not run `flow debug` without explicit user consent.** It executes the flow for real (sends emails, posts messages, calls APIs). | ||
| 2. **Do not run `flow debug` without explicit user consent.** It executes the flow for real (sends emails, posts messages, calls APIs). Non-interactively, consent is decided by rule #13's two tests, not by asking — see [shared/non-interactive.md](references/shared/non-interactive.md#flow-debug-without-a-user). |
There was a problem hiding this comment.
See if we can express this without the rule ref for future mutation concerns (numbers changing).
There was a problem hiding this comment.
Now links the reference doc instead of naming a rule number.
| 5. **Always present finite decisions as a dropdown with a final "Something else" escape hatch.** Whenever the skill needs a decision (which solution, publish vs debug vs deploy, which connector, trigger type, or resource to bind, etc.), ask with the enumerated choices plus **"Something else"** last for free-form input; never ask open-ended in chat when a finite set of sensible defaults exists. If the user picks "Something else", parse their answer and continue. No structured-question facility on the harness → ask in chat as a numbered list with "Something else" last. Non-interactively (CI/headless, no user available) → take the marked recommended option, proceed, and record the decision prominently in the final report; if none is recommended, stop and report the open decision instead of guessing. Consent gates (`flow debug`, destructive operations) are never auto-answered — in non-interactive mode, stop and report the blocked step. These fallbacks define "ask the user" / "confirm with the user" wherever this skill's references require it. | ||
| <!--skill-flavor:user-question-options-extra:start--> | ||
| <!--skill-flavor:user-question-options-extra:end--> | ||
| 5. **Always present finite decisions as a dropdown with a final "Something else" escape hatch.** Whenever the skill needs a decision (which solution, publish vs debug vs deploy, which connector, trigger type, or resource to bind, etc.), ask with the enumerated choices plus **"Something else"** last for free-form input; never ask open-ended in chat when a finite set of sensible defaults exists. If the user picks "Something else", parse their answer and continue. No structured-question facility on the harness → ask in chat as a numbered list with "Something else" last. **With no user available, rule #13 governs** — it outranks any absolute prohibition worded in a reference doc. |
There was a problem hiding this comment.
See if we can express the same without citing the number which might change. Long term drift and maint concerns.
There was a problem hiding this comment.
Same, links instead of numbering. All four rule-number references this PR introduced are gone. Left the pre-existing ones elsewhere alone as unrelated.
| 10. **Batch independent tool calls and chain dependent CLI calls.** A typical greenfield build is three turns: T1 scaffold, pull the registry, and add CLI-owned nodes in one chained `Bash`, alongside independent registry/file reads; T2 read the scaffold while editing/adding the End node and edges; T3 chain configure, validate, and format. Split only when later work depends on stdout or a mutation. See [author/greenfield.md — Three-turn execution map](references/author/greenfield.md#three-turn-execution-map). | ||
| 11. **Cross-node bindings in `=js:` require `$vars.`** Use `=js:$vars.<nodeId>.output...`; bare `=js:<nodeId>.output...` resolves to `undefined`. See [variables-and-expressions.md — IS Activity Inputs Require `=js:`](references/shared/variables-and-expressions.md#is-activity-inputs-require-js-critical). | ||
| 12. **Node and edge IDs must begin with a letter.** Use descriptive camelCase node IDs and `edge_<sourceNodeId>_<sourcePort>_<targetNodeId>_<targetPort>` edge IDs. Reserve UUIDs for the top-level flow `id` and `entryPointId`. | ||
| 13. **With no user available, classify the decision — never stall on it.** Non-interactive when the harness exposes no structured-question tool, the prompt forecloses asking ("do not ask for approval", "single pass", "full autonomy"), or the run is CI / a scheduled job / an eval harness. Every "ask the user" in this skill then resolves to one of three outcomes: **Proceed** (marked default or one viable candidate, no write outside the working tree), **Assume** (supply the most defensible value, keep building, record it), **Stop** (irreversible, externally visible, or a fact you could not resolve — finish everything else first, then report it). Assume is the default for build-time decisions; a flow plus stated assumptions beats a blocked turn. Never downgrade a Stop to a guess — a display name written where a resolved ID belongs passes `flow validate` and faults at runtime. Per-site classification, the `flow debug` provenance and side-effect tests, and the required report shape: [shared/non-interactive.md](references/shared/non-interactive.md). |
There was a problem hiding this comment.
If you can do so without losing effectiveness, remove the specific examples that might drift and cause maint issues.
There was a problem hiding this comment.
Dropped. Detection now reads "harness exposes no structured-question tool, the prompt forecloses asking, or the run is unattended". The phrasings stay in the reference doc, where drift is cheap and they are not loaded on every invocation.
| weight: 5.0 | ||
| pass_threshold: 1.0 | ||
|
|
||
| # This flow is all-read (manual-mode HTTP GET, script, decision, end) and the |
There was a problem hiding this comment.
Far too many comments. I think this should be removed as part of this PR.
There was a problem hiding this comment.
Reverted the whole criterion, not just the comments. You were right to ask why it was in the PR at all: eval-suite work belongs in the follow-up that aligns prompts with checkers, and a weight-0 advisory cannot fail, so it was observability rather than a test. tests/ is untouched by this PR now.
Narration stripRan every added line through "does this change what the agent does?" and deleted what failed. Cut
Kept, because the reason is the instruction
Also
Numbers
Re-ran the embedded checker against all 8 nightly |
… unmark the publish default Two defects, both consequences of rule #5 rather than gaps in it. Rule #5 classes `flow debug` as a consent gate that is never auto-answered. In the 2026-09-04 nightly, 5 of 8 `skill-flow-*` tasks therefore validated their flow, reported success, and never executed it. The checker then ran debug and found a null End-node output mapping, a faulted script, and an empty result. `flow validate` had passed on all of them. Consent for debug is not a question that needs a live user. It comes from what was asked for: a request to build something that does X is a request for it to work, and building plus validating does not discharge that. Rule #2 now says so, rule #5 defers to it, and run.md matches. Added the one guardrail debug genuinely needs: it overwrites the Studio Web solution matching the local `.uipx` SolutionId, so never debug a solution this run did not scaffold. Separately, rule #5's non-interactive fallback takes the marked recommended option, and the What's next dropdown marked "Publish to Studio Web" as the default. A headless run would auto-publish to the tenant. Dropped the marking in both greenfield and brownfield; nothing else in either table is marked, so the fallback now falls through to stop-and-report. Modifies Critical Rules 2 and 5, per CONTRIBUTING. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1f33674 to
eff59ec
Compare
flow debug consent from the mandate, unmark the publish default
Rewrote the branch: 18 files → 4The original premise was wrong, so I reset to What was wrong. I built a "no user available" doctrine (new 6.4 KB reference doc, 17 per-site clauses, a Proceed/Assume/Stop vocabulary, a python side-effect checker) on the claim that the skill had no defined behavior when nobody can answer a question. It did. Rule #5 on
That last clause already applied rule #5 to every gate by default. My 17 clauses restated a rule that was already in force. I had also conflated two different states under one label: genuinely headless (CI, cron, eval harness) and a present user who said "don't ask me." The second is not a deadlock. That user reads the report and answers next turn. The deadlock I was solving only exists in the first case, which rule #5 already covered. What survives. Two real bugs, neither needing a new concept:
Dropped: Known consequence. Without the Assume-over-Stop default, a headless run still stops on an unresolvable reference. That is what |
The behaviour was the tail of rule #5, whose headline is about dropdown menus, 61% into the file and 574 characters into the rule. An agent scanning headlines for "no user, what now?" does not match on "Always present finite decisions as a dropdown". It was also wrong after this PR's own change. Rule #5 said take the marked recommended option, and dropping the two `(default)` markings left exactly one marked option in the whole skill, so every finite decision fell to stop-and-report. That is the opposite of what a headless run should do with a choice it can make. Rule #13 now covers all four cases the skill actually hits, and is self-sufficient: it states detection and behaviour, so it holds whether or not the harness ever announces the mode. Rule #5 keeps the ask mechanism and points at it. - finite choice -> best option, not only a marked one - missing value -> most defensible one, keep building - irreversible or externally visible -> do not, finish the rest first - unresolved fact -> stop on that field, never a display name or alias Also drops the two `rule #2` citations this PR had added, in SKILL.md and run.md, in favour of naming the rule. Appending #13 renumbers nothing, so the cross-references in other docs are untouched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Headless behavior is now a rule of its own, and self-sufficientTwo changes, both from reviewing where the instruction lived and what it said. It was in the wrong placeThe behavior was the tail of rule #5, whose headline is "Always present finite decisions as a dropdown with a final Something else escape hatch." That put it 61% into the file and 574 characters into the rule. An agent scanning rule headlines for "no user, what now?" does not match on a rule about dropdown menus. Moving it up the file was the wrong fix: renumbering costs ~24 cross-references across 8 files, and a new top-level section violates the body order in It was also wrong, because of this PRRule #5 said take the marked recommended option. Dropping the two Rule #13Covers the four cases the skill actually hits, and states detection as well as behavior, so it holds whether or not the harness ever announces the mode:
Every decision, assumption and blocked step goes in the final report. Rule #5 keeps the ask mechanism and points at #13. That last row is the pathology in 3 of the 8 nightly failures: AlsoDropped the two Scope4 files, 6 insertions, 5 deletions. SKILL.md 21,655 → 22,817 bytes (+5.4%), which is the honest cost of the skill owning this behavior in prose rather than deferring it.
|
…the file As Critical Rule #13 it sat at line 88, past the capability list, the 13-row router, and 12 other rules. Every observed run happened to read the whole file first, so read order was not the live problem, but a rule that changes how rules 1-12 and every reference doc behave should not be stated after all of them. Working style is the right home on the merits, not just position: rules 1-12 are `.flow` mechanics (node ownership, `=js:` prefixes, ID formats), while headless is an operating mode, which is what that section is for. It now sits at line 14, fifteen lines ahead of the first link in the file, so no reference can be followed before it is read. Chose this over making it Critical Rule #1, which would renumber the list and break 29 `rule #N` citations across 7 files. Links fixed as a result: - Rule #5 pointed at "the headless rule below"; now links up to [Working style](#working-style). - The bullet said `flow debug` "is governed by its own rule above"; that rule is now below it, so it names the section instead of a direction. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Headless rule moved above every link in the fileWas Critical Rule #13 at line 88 — past the capability list, the 13-row router, and 12 other rules. Now the first bullet of Why Working style and not Critical Rule #1Rules 1–12 are Making it rule #1 would have renumbered the list and broken 29 On the read-order argumentWorth recording that this did not fire in the nightly. All 8 runs read SKILL.md in full as their first action, before any reference: Moved it anyway, for the ordering-of-meaning reason rather than the read-order one: a rule that changes how everything below it behaves should not be stated after all of it. The read-order case is a robustness argument for other harnesses and future readers, not an observed failure. Links fixed
Verification
4 files, 6 insertions, 5 deletions. SKILL.md 21,655 → 22,858 (+5.6%). |
|
Context update: the companion harness PR (UiPath/coder_eval#156) is closed, per thread feedback.
This PR is option 1, so it stands unchanged and is now load-bearing rather than complementary. The Working style bullet already states detection and behavior, so it does not depend on any harness announcement:
The declaration of the fact moves to No change to this one. |
… eval system prompt The bullet told the skill what to do when no user is present. Three of its four branches (finite choice, missing value, irreversible action) only fire when nobody can be asked, and the fourth — never write a display name where a resolved ID belongs — already exists as an anti-pattern here and in connector/impl.md. No user only happens headless, and the only documented way to consume this skill is `uip skills install` into a developer's local Claude Code, Codex, Cursor, or Gemini. Nothing ships it to a headless surface, so the bullet was carrying eval-only behaviour in a skill that only interactive users install. It moves to the flow experiment's system prompt. What remains here has independent justification and applies with or without a user watching: `flow debug` consent comes from the mandate, and "Publish to Studio Web" is no longer marked as a default that rule #5's fallback would auto-fire. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Superseded by a single PR that carries these changes plus the eval-config work they depend on. Splitting them was wrong. This PR removed the The surviving changes here ( Review history worth keeping: the rule-number drift, the eval-suite change that did not belong, the narration cuts, and the |
Replaces the original scope of this PR. See the history-rewrite comment below for why.
Two defects, both consequences of rule #5 rather than gaps in it
1.
flow debugis classed as a consent gate that is never auto-answered.In the 2026-09-04 nightly, 5 of 8
skill-flow-*tasks validated their flow, reported success, and never executed it. The checker then ran debug and found a null End-node output mapping, a faulted script, and an empty result.flow validatepassed on all of them.Consent for debug is not a question that needs a live user. It comes from what was asked for: a request to build something that does X is a request for it to work, and building plus validating does not discharge that. Rule #2 now says so, rule #5 defers to it,
run.mdmatches.Added the one guardrail debug genuinely needs: it overwrites the Studio Web solution matching 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.2. The marked default is a tenant write.
Rule #5's non-interactive fallback takes the marked recommended option. The What's next dropdown marked Publish to Studio Web
(default). A headless run would auto-publish to the tenant. Marking dropped in both greenfield and brownfield; nothing else in either table is marked, so the fallback now falls through to stop-and-report.Scope
4 files, 5 insertions, 5 deletions. SKILL.md +596 bytes (+2.8%).
Modifies Critical Rules 2 and 5, called out per CONTRIBUTING.
Verification
.maintenance/check-all.shclean apart from one anchor that pre-exists onmain.skill-flow-*nightly is the real check.Follow-ups (separate PRs)
flow debugand a prompt that never asks the agent to. Align them.greenfield.mdStep 2: assert one.flow+ oneproject.uiprojafter scaffold.skill-flow-bindings-no-duplicatespassed its actual regression and failed only because a stray duplicate project confused the checker glob.script/impl.md: extend the existingnode -e "new Function(...)"syntax check to a value test against real upstream shape. Would have caught the off-by-one inskill-flow-slack-weather-pipelinethat shipped"Suite 2000"as a city name.variables-and-expressions.md: document the=js:expression boundary. An End-node mapping using object spread returnednullwith a clean validate. Needs a repro first.dice_rollerpicks a HITL quick-form to "display" a value, so the flow never terminates and debug times out. Node-selection guidance, not a consent problem.🤖 Generated with Claude Code