fix(maestro-case): close the eleven faults found by the RetailAccountOpening evaluation runs - #2553
fix(maestro-case): close the eleven faults found by the RetailAccountOpening evaluation runs#2553roberts-cliff wants to merge 4 commits into
Conversation
…Opening runs
Two independent end-to-end builds of the same 8-stage/20-task SDD failed
in opposite directions: one was refused at BPMN conversion, the other was
accepted and launched an instance that reported Running with no incidents
while never executing a single stage task. Postmortem findings S1-S8, I1
and the skills-side halves of the shared items are addressed here.
Verification gates that did not exist
planning.md artifact-existence gate -- both tasks/tasks.md and
tasks/registry-resolved.json must be on disk before
Phase 2. One run planned entirely in memory and wrote
neither; nothing downstream noticed, because validate
and the Step 12 checks read caseplan.json, never the
planning trail.
planning.md one-T-entry-per-declaration gate, with range headings
called out as a hard failure. The other run emitted 106
mandated entries as 7 range headings ("## T41-T60:
Tasks") and still produced a Valid caseplan.
phased- liveness check after a debug instance launches. Poll
execution.md element-executions for a stage or task element; trigger
and case-started elements complete on a dead case too.
If none appear, report the run as failed.
Placeholder semantics -- the cause of the silently dead case
placeholder- position risk is now a mandatory classification. A
tasks.md placeholder on a required, case-gating task is not a
warning, it is a build that cannot work, and must be
reported under HIGH before publish.
Also documented: placeholders discard any literal
demo-mode outputs the SDD supplied (identityValid =
js:(true) and friends), which is what made that case
unable to satisfy any stage exit; and a cross-task
reference into a placeholder can never resolve, so the
rule is emitted ungated rather than degraded to
=js:false, which silently asserts "never".
Contradictions and underdetermined guidance
global-vars the manual-trigger serviceType instruction directly
contradicted triggers/manual/impl-json.md for the same
node. global-vars was the stale side; corrected, with
the prior guidance called out so nobody reinstates it.
registry- "exact name matches exist, declared folder has none" now
discovery.md resolves to unresolved rather than an improvised
tiebreak. The two runs met this on identical input and
answered differently -- 44 candidates, one picked
most-recently-modified, the other declared it unresolved.
SKILL.md Rule 17 gains a non-interactive default (placeholders,
never inline create, always disclosed) so unattended
runs stop inventing one.
SKILL.md Rule 2 gains a precedence rule for self-contradictory
SDDs: per-task detail beats the Section 4 rollup, but an
identity disagreement is a design question, not a
formatting slip.
sla/ task-scoped SLA has no schema target. Silently widening
impl-json.md it to the stage changes when the clock starts and what
it covers; both runs did that without saying so.
Known platform defects, so agents stop rediscovering them
phased- BPMN conversion throws "Cannot read properties of
execution.md undefined (reading 'get')" whenever more than one stage
carries a non-empty escalationRule. validate reports the
same file Valid. Confirmed across both builds and four
isolation methods. Documented with the instruction not
to silently strip escalations to get past it.
case- element-executions and cursors added as the real health
commands.md checks, with the note that get and incidents both report
healthy on a dead instance and that cursors returns
PIMS-400006 where they say nothing. instance cancel can
return 500; orchestrator jobs stop --strategy Kill is
the working fallback.
Rules 8 and 12 gain pointers so the position-risk and liveness contracts
are reachable from SKILL.md rather than only from references.
Not addressed here (CLI-side, separate PRs): the conversion crash itself,
the tasks describe customData casing bug, the static and misleading
"Check authentication and case file" guidance, and a conversion dry-run
for validate.
Refs: postmortem at sandbox/POSTMORTEM-RetailAccountOpening.md
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Claude finished @roberts-cliff's task in 4m 14s —— View job PR Review: fix(maestro-case) — close eleven postmortem faults
SummaryDocs-only PR closing 11 faults surfaced by two independent end-to-end RetailAccountOpening evaluation runs. Adds new gates and classifications to the maestro-case skill (placeholder position risk, liveness check, range-heading prohibition, artifact-existence gate), corrects a stale Change-by-Change Review1.
|
| Area | Status | Notes |
|---|---|---|
| Frontmatter | OK | No frontmatter changes — existing name/description unaffected |
| E2E Tests | Note | No new tests for new maestro-case behavior (Medium) |
| Skill Body | OK | Critical rules updated correctly with proper cross-references |
| References & Assets | OK | All 7 reference files are internally consistent; links verified; no duplication |
| Repo Hygiene | OK | No secrets, no cross-skill imports, changes scoped to one skill + 3 related test trims |
Issues for Manual Review
- CLI command accuracy: The
uip orchestrator jobs stop <instance-id> --strategy Killcommand and theuip maestro case instance element-executions/cursorscommands are documented from observed behavior — reviewer should confirm these are stable CLI surfaces, not internal/experimental. conditionExpressionomission semantics: The new cross-task-reference rule prescribes omittingconditionExpressionfrom a rule rather than falsifying it. Whether the schema/engine treats a missingconditionExpressionas "ungated" (always true) vs invalid should be verified against the platform behavior.- Test regression risk: The
diagnose_bindings_not_imported_integration.yamlchange removes the seeded fixture, changing it from an inspection task to a reasoning task. If the test's value was in verifying the agent actually reads the workspace, this is a coverage reduction.
Conclusion
Clean, well-structured PR. Every new section follows the reference-pointer discipline (detail in one authoritative file, brief routing summary + cross-reference elsewhere). The corrections are grounded in observed evaluation failures with specific instance IDs and reproduction evidence. The global-vars serviceType fix is verified against the manual trigger plugin. No issues at High or above. The only gap is the absence of new test tasks for the planning gates — not blocking given these are docs-only changes to an existing skill with extensive test coverage.
Recommendation: Approve.
`uip orchestrator jobs stop` does not exist -- `or` is the only Orchestrator top-level prefix, so the verb is `uip or jobs stop`. The postmortem wrote it loosely and the doc change copied it through; the repo's verb checker caught all three occurrences as blocking. Confirmed against the catalog (`or jobs stop`) and the live CLI, which documents exactly the behaviour we rely on: "With a single key: respects --strategy (SoftStop or Kill)." Worth noting the checker earned its keep here -- the guidance would have told an agent to run a command that does not exist, at the moment it was already dealing with a stuck instance. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two faults the second pair of evaluation runs surfaced, both squarely ours. P7 -- escalationRule.action.type accepts only "notification" Rule 21 lists the SLA response categories as notify-only / start-task / enter-stage / exit-stage / exit-case. Read quickly, those look like values for escalationRule[].action.type. They are not: the runtime schema rejects everything but "notification" with Invalid input: expected "notification" Both runs authored "enter-stage" / "exit-case" there and had to re-model after validate rejected the case. The SLA plugin already says the clock is not the response, but neither Rule 21 nor case-schema.md stated the restriction where an agent reading about responses would see it. Both now say it plainly, and point at the sla-status-change condition rule as the mechanism for every non-notify response. S9 -- concurrent builds from one SDD overwrite each other Planning artifacts live in tasks/ next to sdd.md, so every solution built from that SDD writes the same two files. Two concurrent runs were given distinct solution names on the assumption that would isolate them; it does not, because the artifacts are not namespaced by solution. They overwrote each other's tasks.md and registry-resolved.json mid-build and neither noticed until a harness file-change notification surfaced it. planning.md now states that tasks/ is keyed to the SDD rather than the solution, and that a pre-existing tasks/ not written by this run is a hard stop. Building two variants of one SDD needs two working directories, each with its own copy of sdd.md. Refs: postmortem §4.2 P7, §4.3 S9. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rtem-faults # Conflicts: # skills/uipath-maestro-case/SKILL.md # skills/uipath-maestro-case/references/phased-execution.md
Closes the skills-repo faults found by two independent end-to-end builds of the same 8-stage / 20-task SDD (
RetailAccountOpening) against a live tenant. Full write-up:sandbox/POSTMORTEM-RetailAccountOpening.md.Why this matters
The two runs failed in opposite directions, and the pair is the finding:
caseplan.json, then a hard crash in BPMN conversion. Loud.RAO-30390989, reportedLatestRunStatus: RunningwithIncidents: null, and never executed a single stage task for 40+ minutes.Run A's mode is the dangerous one. Its cause was a placeholder sitting on the required first task of the first stage — and nothing in the skill treated that differently from a placeholder on an optional side path.
What changed
Gates that did not exist
planning.mdvalidateand the Step 12 checks readcaseplan.json, never the planning trail.planning.md## T<n>:heading per SDD declaration; range headings are a hard failure. Run B emitted 106 mandated entries as 7 ranges (## T41-T60: Tasks) and still produced aValidcaseplan.phased-execution.mdelement-executionsfor a stage/task element. Trigger and case-started elements complete on a dead case too.Placeholder semantics — the cause of the silently dead case
identityValid = js:(true)), which is precisely what left run A unable to satisfy any stage exit. Must be surfaced, not silently taken.<-/$xrefreference into a placeholder can never resolve. The rule is now emitted ungated rather than degraded to=js:false— a false gate silently asserts "never", which is how four of run A's conditions made Stage 1 permanently un-exitable.Contradictions and underdetermined guidance
global-varsvstriggers/manualgave opposite instructions on manual-triggerserviceTypefor the same node.global-varswas stale; corrected, with the old guidance called out so it doesn't get reinstated.Known platform defects documented, so agents stop rediscovering them
Cannot read properties of undefined (reading 'get')whenever more than one stage carries a non-emptyescalationRule.validatereports the same fileValid. Confirmed across both builds and four isolation methods. Documented with an instruction not to silently strip escalations to get past it.element-executionsandcursorsadded as the real health checks, with the note thatgetandincidentsboth report healthy on a dead instance whilecursorsreturnsPIMS-400006.instance cancelcan return500;orchestrator jobs stop --strategy Killis the working fallback.Added after the runs C/D re-evaluation
Two further builds from the v1 SDD were run against the patched skill (
871cb7922/1a2a8edaaat 11:53/12:02; runs began 12:05). They validated two of the fixes and surfaced two new faults, now also in this PR.Fix validation — the reason to have confidence in the rest
tasks.md; B collapsed 106 entries into 7 range headingsRunninginstance## HIGH — Dead case (Rule 8 / placeholder position risk)is the first entry inbuild-issues.md, before publishTheir build-issues predicts run A's exact failure mode unprompted: "even if debug had succeeded, the instance would report Running/no-incidents forever without executing anything."
P7 —
escalationRule.action.typeaccepts only"notification"Rule 21 lists SLA responses as
notify-only/start-task/enter-stage/exit-stage/exit-case. Read quickly those look likeaction.typevalues; the schema rejects everything but"notification"withInvalid input: expected "notification". Both runs authored"enter-stage"/"exit-case"there and had to re-model. Rule 21 andcase-schema.md§6 now state the restriction where an agent reading about responses will see it, and point atsla-status-changeas the mechanism.S9 — concurrent builds from one SDD overwrite each other
tasks/sits next tosdd.md, so every solution built from that SDD writes the same two files. The two runs were given distinct solution names on the assumption that isolates them — it does not, because the artifacts aren't namespaced by solution. They clobbered each other'stasks.mdandregistry-resolved.jsonmid-build.planning.mdnow saystasks/is keyed to the SDD, and that a pre-existingtasks/not written by this run is a hard stop.One fix that did not bind, deliberately left open
Given identical input and the patched skill, the two runs still diverged on the connector-identity contradiction: one placeholdered everything, the other bound live Outlook 365 and HTTP Webhook connections that would have made real outbound calls on debug. Rule 2's precedence text covers this case and the second run simply didn't follow it. Prose is not enough for anything with a side-effect blast radius — tracked as postmortem action item 21 (a mechanical check refusing to bind a connection whose connector key disagrees with the SDD's declared system), not attempted here.
Not in this PR
CLI-side, separate: the conversion crash itself, the
tasks describecustomDatacasing bug, the static"Check authentication and case file"guidance, and a conversion dry-run forvalidate.Validation
0 broken links across the skill; all new cross-reference anchors resolve;
check-skill-status.py,check-skills-sh.pyandvalidate-skill-descriptions.shall pass.Docs-only — no task YAMLs, no behavior code.
🤖 Generated with Claude Code