diff --git a/CODEOWNERS b/CODEOWNERS index 12944016d2..d7069c6cbe 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -73,6 +73,14 @@ # Planner skill (PDD → SDD design + multi-skill task planning) /skills/uipath-planner/ @RaduAna-Maria @abhiram-vad /tests/tasks/uipath-planner/ @RaduAna-Maria @abhiram-vad +# Case-design evals migrated from uipath-maestro-case (planner-sole-SDD-author) — case owners stay reviewers +/tests/tasks/uipath-planner/_shared/ @RaduAna-Maria @abhiram-vad @charlesliu9 @song-zhao-25 @jundayin +/tests/tasks/uipath-planner/case_design_interview/ @RaduAna-Maria @abhiram-vad @charlesliu9 @song-zhao-25 @jundayin +/tests/tasks/uipath-planner/case_design_loan/ @RaduAna-Maria @abhiram-vad @charlesliu9 @song-zhao-25 @jundayin +/tests/tasks/uipath-planner/case_finalize_draft/ @RaduAna-Maria @abhiram-vad @charlesliu9 @song-zhao-25 @jundayin +/tests/tasks/uipath-planner/case_finalize_draft_loan/ @RaduAna-Maria @abhiram-vad @charlesliu9 @song-zhao-25 @jundayin +/tests/tasks/uipath-planner/case_finalize_draft_picker/ @RaduAna-Maria @abhiram-vad @charlesliu9 @song-zhao-25 @jundayin +/tests/tasks/uipath-planner/case_finalize_draft_reject/ @RaduAna-Maria @abhiram-vad @charlesliu9 @song-zhao-25 @jundayin # Solution skill (uip solution lifecycle) /skills/uipath-solution/ @UiPath/team-merlot @UiPath/team-orange diff --git a/skills/uipath-maestro-case/SKILL.md b/skills/uipath-maestro-case/SKILL.md index fe80f5863d..f081986e14 100644 --- a/skills/uipath-maestro-case/SKILL.md +++ b/skills/uipath-maestro-case/SKILL.md @@ -1,6 +1,6 @@ --- name: uipath-maestro-case -description: "Always invoke for UiPath Maestro Case Management work: `caseplan.json`, `sdd.md`, `sdd.draft.md`, case-management SDD finalization, or greenfield case design when no SDD exists. Produces tasks.md and authors or edits caseplan.json directly with Write/Edit. For .xaml→uipath-rpa, .flow→uipath-maestro-flow, .bpmn→uipath-maestro-bpmn. For PDD→SDD or explicit cross-product planning, suggest `uipath-planner` in text only; never auto-invoke it." +description: "Always invoke for UiPath Maestro Case Management build work: `caseplan.json`, `sdd.md`, or building/creating a case when no SDD exists yet (the design is then delegated at runtime to uipath-planner, the sole case-SDD author). Produces tasks.md and authors or edits caseplan.json directly with Write/Edit. For .xaml→uipath-rpa, .flow→uipath-maestro-flow, .bpmn→uipath-maestro-bpmn. For standalone case SDD design, case `sdd.draft.md` finalization, PDD→SDD, or cross-product planning→uipath-planner." allowed-tools: Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion, TodoWrite, Agent --- @@ -10,14 +10,14 @@ Builds UiPath Case Management definitions from `sdd.md`. Generates `tasks.md` pl > **Authoring invariant:** Never use mutating `uip maestro case` commands (`cases|stages|tasks|*-conditions ... add|update|remove`, including `tasks add-connector`) or explore them via `--help`. Use the CLI only for scaffolding, metadata reads, validation/debug, runtime operations, and solution sync/upload; consult [case-commands.md](references/case-commands.md) only when exact syntax is needed. CLI availability or a final `validate` requirement does not override this rule. -When `sdd.md` is absent, **Phase 0** designs the case by best assumption from the request and documents, sweeps for other paths beyond the primary flow, confirms it in ONE SDD-shaped Case Review that mirrors the full design document in scan-friendly sections (case snapshot, data contract, primary and secondary stages/tasks, activation modes, task classification rationale, other paths, rules/tiers, resources, assumptions, and review flags), then starts the build with a template-complete `sdd.md` written alongside as a reference artifact. When `sdd.draft.md` is present and the user asks to finalize it, stay in this skill: read the draft as the settled case design, normalize it to the Case Management SDD template, and do not hand off to `uipath-planner`. Complex / multi-product cases may still be designed with the same workflow; suggest `uipath-planner` only when the user explicitly requests planning across products. +When `sdd.md` is absent, the case design is **delegated to `uipath-planner`, run as a subagent** — the sole author of case SDDs. The subagent runs the planner's Case Design Lane best-assumption (Listen → full design-time tenant resolution → Sketch → finalization checks), **writes `sdd.md`** at the working root, and returns the Case Review packet plus a resolution ledger. This skill then presents that Case Review to the user as the single confirmation (with the Rule 11 build options), reads `sdd.md` as the sole input (Rule 2), and builds. If the planner skill is unavailable, degrade gracefully: ask the user for an `sdd.md` and stop (Rule 15). Case draft finalization (`sdd.draft.md` → `sdd.md`) is delegated the same way. -**Scope:** two journeys — **greenfield** (build a new case from `sdd.md`, user-provided or Phase 0-generated) and **brownfield** (targeted edits to an existing `caseplan.json` — see [references/brownfield.md](references/brownfield.md)). Editing a case that also lives in Studio Web? Brownfield pulls the current server state first (`uip solution download` / `solution projects resync`) so re-publish can't silently clobber server-side changes — see [brownfield.md § Pull latest first](references/brownfield.md#pull-latest-first-before-editing). +**Scope:** two journeys — **greenfield** (build a new case from `sdd.md`, user-provided or planner-designed) and **brownfield** (targeted edits to an existing `caseplan.json` — see [references/brownfield.md](references/brownfield.md)). Editing a case that also lives in Studio Web? Brownfield pulls the current server state first (`uip solution download` / `solution projects resync`) so re-publish can't silently clobber server-side changes — see [brownfield.md § Pull latest first](references/brownfield.md#pull-latest-first-before-editing). ## When to Use This Skill - User provides `sdd.md` and wants Case Management project built -- User asks to create new case management project but has no `sdd.md` (Phase 0 interview generates one) +- User asks to create new case management project but has no `sdd.md` (design is delegated to `uipath-planner` at runtime; this skill consumes the confirmed design and builds) - User asks to create new case management project or definition - User asks to generate implementation tasks from `sdd.md` or convert spec to plan - User asks to edit, modify, or update an existing `caseplan.json` (add/remove a stage or task, change a condition, swap a trigger) — targeted edits skip planning; see [references/brownfield.md](references/brownfield.md) @@ -28,23 +28,23 @@ When `sdd.md` is absent, **Phase 0** designs the case by best assumption from th ## Critical Rules -1. **Phase 0 best-assumption design when `sdd.md` absent.** Listen and ground, then decide every open field per the assumption playbook — inform, don't interrogate: every assumption, override, and resource decision is disclosed in the single confirmation's `Decisions I made` block. The confirmation is an SDD-shaped **Case Review** that shows the same design surface the user would inspect in `sdd.md`, but as reviewable tables and grouped bullets: case snapshot, data contract, primary and secondary stages/tasks, activation modes, task classification rationale, other paths, rules/tiers, resources, assumptions, and review flags. It must be complete enough to approve without opening `sdd.md`; do not defer a missing section by saying it will be in the document. This structured Case Review is the only valid plan-first approval surface for Phase 0; a generic "Build Plan" / "Approve this plan" checkpoint does not count, and a user "Yes" to that checkpoint is not a Build answer. Question budget: one clarifying call (only for an empty request, contradictory inputs, user-requested questions, or no source signal for other paths) plus ONE confirmation ([phase-0-interview.md § Confirm](references/phase-0-interview.md#confirm--the-single-checkpoint)). If `sdd.draft.md` exists and the user asks to finalize it, use the direct draft-resumption path in this skill: read the draft and SDD template, render the final `sdd.md` from the Case Management template, do not spawn subagents, do not preload planning/plugin references, and never delegate to `uipath-planner`. On a Build answer, render `sdd.md` from the in-memory model batched with the first build actions — the file MUST pass the template-conformance gate in `phase-0-interview.md`; a summary SDD is invalid even if `caseplan.json` later validates. Explicit sign-off requests add one approval prompt; design-only requests save `sdd.md` and stop; draft requests save `sdd.draft.md` and stop. When the prompt explicitly says to get/save a draft and stop, that request is already the save instruction: show the Case Review, write `sdd.draft.md`, and stop without asking for another approval. When the prompt explicitly asks to produce `sdd.md` plus `tasks/tasks.md` and stop before `caseplan.json`, use the bounded no-build fast path in `phase-0-interview.md`: after the Case Review, write the full-template `sdd.md`, create `tasks/`, write compact `tasks/tasks.md`, and stop; do not read planning/plugin references, tenant discovery sources, or the full SDD finalization checklist. Never overwrite an existing `sdd.md`. -2. **sdd.md is sole input post-Phase-0 — across sessions.** When user-provided, or in any later session, re-run, or staleness recovery (context compaction), trust `sdd.md` as written; the skill does not validate or gap-fill it. Within the session that just confirmed the design, the in-memory model that rendered `sdd.md` is the same content and drives the build directly ([phase-0-interview.md § Build start](references/phase-0-interview.md#build-start--sdd-written-alongside-the-build)) — do not re-read the just-written file. If a build-phase ambiguity arises, use AskUserQuestion — never infer silently. -3. **PHASE 1 HARD GATE — fresh registry before planning, pulled at most once per session.** Run `uip login status --output json`, then `uip maestro case registry pull`, before cache inspection, carryover reuse, resource resolution, or any Phase 1 artifact write — **same-session fast path:** when Phase 0's pull already succeeded in THIS session and `sdd.md` was just rendered from the confirmed in-memory model, reuse that cache and skip the re-pull. Any doubt runs the gate in full: user-provided SDD, cross-session resume, context compaction, a Phase 0 pull that failed or never ran, or missing cache files. **Plan-only exception:** if the user explicitly asks to stop at `sdd.md`/`sdd.draft.md`/`tasks.md` and not create `caseplan.json`, do not run tenant registry, connection, schema, or user-discovery commands; preserve concrete intended resource/system names, mark identities `resolve at build`, and report that resource wiring is deferred to the later build run. Trust the SDD as written; the pull refreshes the local discovery cache and does not validate or override the SDD. **Cache-state rule:** before a successful pull (this session), a missing cache directory/file is a failed refresh precondition — never a zero-match result. Only after a successful pull may an empty exact-name match set (or a still-absent type index) enter the normal empty-lookup flow. Login/pull failure → surface it and stop Phase 1. Discovery reads `~/.uip/case-resources/-index.json` directly because `registry search` has known gaps (esp. action-apps). Phase 0 pulls lazily only for build runs: the same login/pull chain starts in the background only when the case first shows tenant-bound work and a later build may need identities, followed by one light name-match pass — no schema discovery, no resource prompts; unclear items defer to this gate as `resolve at build`. See [references/registry-discovery.md](references/registry-discovery.md). +1. **Design delegation when `sdd.md` absent — one subagent, one Case Review, then build.** Spawn the `uipath-planner` subagent per the Rule 15 contract; it writes `sdd.md` and returns the Case Review + resolution ledger. Present the returned Case Review to the user VERBATIM in structure — it is the only valid plan-first approval surface: an SDD-shaped review (case snapshot, data contract, primary and secondary stages/tasks, activation modes, task classification rationale, other paths, rules/tiers, resources with design-time resolutions, assumptions, and review flags), complete enough to approve without opening `sdd.md`. A generic "Build Plan" / "Approve this plan" checkpoint does not count. Ask ONE AskUserQuestion with the Build options (fold in the Rule 11 build-review preference: `Build it — straight through` / `Build it — pause at the build preview` / `Change something`; relabel `Build despite N flagged items — straight through` when the review carries ⚠ flags). `Change something` or free-text corrections → re-delegate as a targeted edit ("edit `sdd.md`: ") and re-show only the changed review sections. On a Build answer, proceed: `uip solution init ` + Phase 1 planning (Rule 3 verify-only path; persist the returned ledger per Rule 9). Explicit sign-off requests add one approval prompt. Design-only and draft requests belong to the planner end-to-end (suggest invoking it; this skill builds only). When the prompt explicitly asks to produce `sdd.md` plus `tasks/tasks.md` and stop before `caseplan.json`, delegate the same way, then after the Build/Save answer create `tasks/` and write compact `tasks/tasks.md` (planning.md § compact no-build shape) — do not read plugin references or run tenant discovery in that run. If `sdd.draft.md` exists and the user asks to finalize it, delegate to the planner subagent (draft-finalization fast path, target basename `sdd.md`). Never overwrite an existing `sdd.md`. +2. **sdd.md is sole input post-design — across sessions.** When user-provided, or in any later session, re-run, or staleness recovery (context compaction), trust `sdd.md` as written; the skill does not validate or gap-fill it. After a delegated design, read the planner-written `sdd.md` ONCE and plan from it — the design model lives in the subagent and does not cross back; the file plus the returned Case Review and ledger are the whole contract. If a build-phase ambiguity arises, use AskUserQuestion — never infer silently. +3. **PHASE 1 HARD GATE — fresh registry before planning, pulled at most once per session; verify-only when the design already resolved.** Run `uip login status --output json`, then `uip maestro case registry pull`, before cache inspection, carryover reuse, resource resolution, or any Phase 1 artifact write — **same-session fast path:** when the planner subagent's report says its registry pull succeeded in THIS session (Rule 15 — the cache at `~/.uip/case-resources/` is machine-global, so the subagent's pull is this session's pull) and it just wrote `sdd.md`, reuse that cache and skip the re-pull. **Verify-only planning:** with the planner's resolution ledger in hand (same session), Phase 1 skips discovery entirely — it persists the ledger to `tasks/registry-resolved.json` (Rule 9 shape, verbatim), spot-verifies entries against the session cache, executes recorded gate decisions (Rule 17), and re-resolves ONLY entries that are stale or missing. Any doubt runs the gate in full: user-provided SDD, cross-session resume, context compaction, a design-lane pull that failed or never ran, or missing cache files. **Plan-only exception:** if the user explicitly asks to stop at `sdd.md`/`sdd.draft.md`/`tasks.md` and not create `caseplan.json`, do not run tenant registry, connection, schema, or user-discovery commands; preserve concrete intended resource/system names, mark identities `resolve at build`, and report that resource wiring is deferred to the later build run. Trust the SDD as written; the pull refreshes the local discovery cache and does not validate or override the SDD. **Cache-state rule:** before a successful pull (this session), a missing cache directory/file is a failed refresh precondition — never a zero-match result. Only after a successful pull may an empty exact-name match set (or a still-absent type index) enter the normal empty-lookup flow. Login/pull failure → surface it and stop Phase 1. Discovery reads `~/.uip/case-resources/-index.json` directly because `registry search` has known gaps (esp. action-apps). The planner subagent (Rule 15) owns design-time resolution: it starts the login/pull chain lazily when the case first shows tenant-bound work, runs full identity resolution non-interactively (`resolve at build` on ambiguity), and returns the outcomes in the resolution ledger — no schema discovery there; schemas stay a Phase 2/3 concern. See [references/registry-discovery.md](references/registry-discovery.md). 4. **`--output json` on every parsed read.** 5. **Follow plugin per node type.** Open matching `planning.md` during planning + `impl-json.md` during execution. Never guess JSON shapes from memory. 6. **`tasks.md` declarative and lossless only.** No shell commands inside. Field names use plain identifiers (e.g., `type:`, `displayName:`, `lane:`), not CLI flag syntax. One T-entry per sdd.md declaration — every stage, task, trigger, condition, SLA rule, **variable, and argument** gets own T-number, even when value looks like default (`current-stage-entered`, `case-entered`, `exit-only`, `is-interrupting: false`, `runOnlyOnce: true`, `marks-stage-complete: true`). Never group, never silently omit. Preserve every stage/task/SLA `Design Rationale` and condition routing/activation rationale as `rationale:` on the matching T-entry; rationale is reviewer/audit context and never changes the executable JSON shape. Preserve every SDD Inputs row with its declared binding mode and value. A JSON object literal stays literal through both handoffs: record the exact JSON in `tasks.md`, then write either the native object or its JSON-encoded string to `input.value`; never add `=js:` or `=jsonString:` unless the SDD itself explicitly uses that prefix. Project every task/rule Outputs table row through the common grammar in [`plugins/variables/io-binding/planning.md`](references/plugins/variables/io-binding/planning.md#sdd-outputs-table-to-tasksmd-projection-mandatory), then preserve each resulting `outputs:` item **with its operator and both operands unchanged**. SDD Outputs rows require `->` or `=`; a bare `tasks.md` output is generated only from resolved-schema discovery and is never authored as an SDD row. SDD table placeholders such as a `—` Field are not operands and never appear in `tasks.md`. In particular, `greeting -> greeting` is NOT equivalent to schema-discovered bare `greeting`: the former extracts into the predeclared case variable and requires `originalVar`; the latter auto-mints a task-local output. Never simplify an equal-name `->` row. **When an sdd.md row's format is unrecognized, ambiguous, or cannot be categorized — invoke AskUserQuestion before skipping. Silent omission is forbidden.** Always regenerate from scratch (greenfield/planning only — brownfield targeted edits mutate in place and preserve IDs; see [references/brownfield.md](references/brownfield.md)). **Every §4.6 task T-entry carries its own `activation-mode:` and `entry-rule:` lines — a separate §4.7 `rule-type:` entry does not satisfy this.** **Every task T-entry heading quotes the task's display name** in the exact form `## T: Add task "" to ""` (e.g. `## T08: Add wait-for-timer task "First Step" to "Process"`) — an unquoted or reworded heading (e.g. `## T08: Task First Step`) breaks plan addressability and fails plan validators even when `caseplan.json` itself is correct. See [`references/planning.md` §4.0](references/planning.md) and the [Plan-shape gate](references/planning.md#step-5--finalize-tasksmd-auto-proceed-to-phase-2). 7. **`tasks.md` gate — auto-approved by default, opt-in stop.** Phase 1 auto-proceeds into Phase 2 Prototyping with no AskUserQuestion sign-off; treat the plan as approved. **Stop after `tasks.md` only when the request explicitly asked for a plan-only / review-first run** (e.g. "just the plan", "Phase 1 only", "stop after tasks.md for review", "don't build the case yet") — then report the plan and do NOT proceed to Phase 2. Re-read `tasks.md` before executing. 8. **Unresolved resource → placeholder, never fabricate IDs.** Keep `` markers in `tasks.md`. Placeholder **task**: node with `type` + `displayName` + structural fields, `data: {}`; conditions still reference the TaskId. Placeholder **event trigger**: node with render fields + `data.uipath: { serviceType: "Intsvc.EventTrigger" }` only (no other `data.uipath` keys); `entry-points.json` entry appended. No trigger-edge is created (Rule 20). See [references/placeholder-tasks.md](references/placeholder-tasks.md) and [references/plugins/triggers/event/impl-json.md § Placeholder fallback](references/plugins/triggers/event/impl-json.md). -9. **Persist every registry resolution to `registry-resolved.json`** — one object per task with exact keys `stage`, `task`, `taskType`, `cacheFile`, `searchQuery`, `matches`, `selected`, and `rationale` (plus resolved I/O/review metadata when applicable). `stage` + `task` associate the audit entry to one SDD declaration; `cacheFile` is the basename actually searched; `matches` is the full exact-name match set from the cache refreshed in Rule 3, not a summary. Use the authoritative SDD fields as the search and selection contract; record `selected` from that match set, or `null` after a genuine empty lookup. +9. **Persist every registry resolution to `registry-resolved.json`** — one object per task with exact keys `stage`, `task`, `taskType`, `cacheFile`, `searchQuery`, `matches`, `selected`, and `rationale` (plus resolved I/O/review metadata, and `gateDecision` when the design-time gate ruled on the resource). `stage` + `task` associate the audit entry to one SDD declaration; `cacheFile` is the basename actually searched; `matches` is the full exact-name match set from the cache refreshed in Rule 3, not a summary. Use the authoritative SDD fields as the search and selection contract; record `selected` from that match set, or `null` after a genuine empty lookup. **Same-session delegated design:** the planner's resolution ledger already carries this exact shape — persist it verbatim as the file's initial content, then verify/extend per Rule 3. 10. **Cross-task refs:** plan as `"Stage Name"."Task Name".output_name`. Resolve both whole-value `<-` and in-expression `$xref` through the common output-reference-ID algorithm in [`plugins/variables/io-binding/impl-json.md`](references/plugins/variables/io-binding/impl-json.md#output-reference-id-authoritative): use the source output's `.id`; only a custom `=` output, which intentionally has no `.id`, resolves through its verified root companion's `.id`. Never use a reassigned output's `.var` as the source reference ID — it points at the target Case variable and can differ from the collision-safe source `.id`. Discover output names via `uip maestro case spec` (connector tasks) or `uip maestro case tasks describe` (non-connector tasks) — never fabricate. **Inside** a larger `=js:` expression (composite payload, condition, SLA), use the in-expression marker `vars.$xref('Stage','Task','output')` instead — resolved at Step 11.5. See [references/bindings-and-expressions.md](references/bindings-and-expressions.md) and [`plugins/variables/io-binding/impl-json.md`](references/plugins/variables/io-binding/impl-json.md). -11. **Build-review preference decides the Phase 2 → Phase 3 boundary — captured ONCE, up front, never asked mid-build.** Capture it at journey start: greenfield-with-interview folds it into the single confirmation's Build options (`Build it — straight through` / `Build it — pause at the build preview` — [phase-0-interview.md § Confirm](references/phase-0-interview.md#confirm--the-single-checkpoint)); greenfield-with-provided-SDD asks it once right after the roadmap; non-interactive runs and resumed runs with no recorded preference default to **straight-through** (no mid-build publish — Phase 6 stays the only publish point and stays gated). At the boundary, always run `validate --skeleton` (structural checks only) and print the counts summary — advisory, never halt on its errors. Then: **straight-through** → continue into Phase 3 with no prompt, the summary line doubling as the milestone narration; **pause-at-preview** → follow the publish-for-review contract in [`references/phased-execution.md`](references/phased-execution.md) (AskUserQuestion `Publish for review` / `Skip publish and continue` / `Abort`; on publish, print `DesignerUrl` as plain text BEFORE the follow-up prompt — never only inside the question body). Hard stops that are NEVER bypassed regardless of preference: Phase 4 retry exhaustion (`Retry with fix` / `Pause for manual edit` / `Abort`), Phase 5 entry (`Run debug session` / `Skip to Publish`), and Phase 6 entry (`Publish to Studio Web` / `Done`). Full contract in [`references/phased-execution.md`](references/phased-execution.md). +11. **Build-review preference decides the Phase 2 → Phase 3 boundary — captured ONCE, up front, never asked mid-build.** Capture it at journey start: greenfield-with-delegated-design folds it into the planner Case Review's Build options (`Build it — straight through` / `Build it — pause at the build preview` — Rule 15); greenfield-with-provided-SDD asks it once right after the roadmap; non-interactive runs and resumed runs with no recorded preference default to **straight-through** (no mid-build publish — Phase 6 stays the only publish point and stays gated). At the boundary, always run `validate --skeleton` (structural checks only) and print the counts summary — advisory, never halt on its errors. Then: **straight-through** → continue into Phase 3 with no prompt, the summary line doubling as the milestone narration; **pause-at-preview** → follow the publish-for-review contract in [`references/phased-execution.md`](references/phased-execution.md) (AskUserQuestion `Publish for review` / `Skip publish and continue` / `Abort`; on publish, print `DesignerUrl` as plain text BEFORE the follow-up prompt — never only inside the question body). Hard stops that are NEVER bypassed regardless of preference: Phase 4 retry exhaustion (`Retry with fix` / `Pause for manual edit` / `Abort`), Phase 5 entry (`Run debug session` / `Skip to Publish`), and Phase 6 entry (`Publish to Studio Web` / `Done`). Full contract in [`references/phased-execution.md`](references/phased-execution.md). 12. **Never run `uip maestro case debug` automatically.** Executes case for real — emails, messages, API calls. Explicit user consent only. 13. **All skill artifacts: Read + Write/Edit only.** Applies to `caseplan.json`, `sdd.md`, `sdd.draft.md`, `tasks.md`, `tasks/registry-resolved.json`, `tasks/trigger-spec-cache.json`, `tasks/spec-cache..json`, `bindings_v2.json`, `id-map.json`, `entry-points.json`, `build-issues.md`. No `python`, `node`, `jq`, `sed`, `awk`, or scripts that open/parse/modify/save these files. **Specifically forbidden** (common slip): `node -e "...fs.writeFileSync..."`, `node -e "...fs.readFileSync..."`, `node -e "..." > `, `jq '...' > `, `python -c "...open(...,'w')..."`, `sed -i`, `awk -i inplace`, or any shell redirection (`>`, `>>`, `| tee`) onto a skill artifact regardless of interpreter. **Writing a helper script under `/tmp` or anywhere else to assemble a skill artifact is also forbidden** — the build-assembler pattern (`/tmp/build-caseplan.js`, `/tmp/gen-tasks.py`, etc.) is the same Rule 13 violation as inline `node -e`, regardless of "mechanical copy" or "avoid Read+Write churn" framing. If `caseplan.json` exceeds ~30KB and a single Write feels too large, split into the Phase-2-skeleton-then-Phase-3-fill cadence (per [case-editing-operations.md § Per-section batch write contract](references/case-editing-operations.md#per-section-batch-write-contract--canonical)) — never via helper script. **The `node -e ... fs.*` ban is not scoped to the artifact list — it applies to ALL file reads in this skill, including resource cache reads from `~/.uip/case-resources/`. Use `cat ... | python3 -c "..."` or the `Read` tool for cache lookups.** Bash subprocesses OK ONLY for UUID v4 generation (`node -e "console.log(crypto.randomUUID())"` for `operate.json.projectId` and `entry-points.json` `uniqueId` — subprocess MUST NOT `require('fs')` or use redirection), CLI metadata fetches, validate, debug, and solution scaffold/upload. **Prefixed IDs (`Stage_`, `t`, `Rule_`, etc.) are picked inline by the agent — no subprocess.** See [references/case-editing-operations.md § Tool usage](references/case-editing-operations.md#tool-usage--mandatory). 14. **Resolved resources must be runnable, and sidecar parity is an unconditional Phase 3 exit check.** Before Phase 4, run Step 12 Checks 7, 9, and 11 even when publish, debug, and `uip solution resources refresh` are skipped. A task with a non-null `selected` entry in `tasks/registry-resolved.json` MUST NOT be emitted as a placeholder: it must remain present with `data.name` and `data.folderPath` bound to complete root bindings, its resource must project into `bindings_v2.json.resources[]`, and its binding pair's `resourceKey` must be self-consistent with its own `name`/`folderPath` defaults (Check 11) — never a copied tenant identity/UUID. `uip maestro case validate` success does not substitute for these checks. On a mismatch, repair the named task/binding or regenerate the sidecar once as applicable, then re-check; halt before Phase 4 if any of these checks still fails. Repeat Check 7 before every `resources refresh`. Always run `resources refresh` before `uip solution upload` or `uip maestro case debug` so Studio Web can resolve dependencies. -15. **Never auto-invoke `uipath-planner`.** If the user asks for planning across products, print a plain-text suggestion of the skill name; the user re-invokes it manually. No tool-call cross-skill handoff. +15. **Design delegation contract — `uipath-planner` runs as a subagent and writes the SDD.** When `sdd.md` is absent at the resolved path (or the user asks to finalize a case `sdd.draft.md`), spawn ONE subagent (Agent tool) whose prompt carries: the user's request + document paths VERBATIM, the resolved working directory, and the instruction to follow the `uipath-planner` Case Design Lane end-to-end in delegated subagent mode — design best-assumption (no user available in a subagent), resolve tenant identities at design time, write `sdd.md` at the working root (never overwrite an existing one), and return the complete Case Review packet + `Decisions I made` + ⚠ flags + the resolution ledger as one fenced JSON block. Delegate immediately on detection — before reading this skill's references, hunting the filesystem for templates, or running tenant commands. The subagent's report drives Rule 1's user confirmation; a report missing the Case Review or the ledger → re-ask the subagent once, then fall back to reading `sdd.md` and running Phase 1's full discovery gate. **Receipt spot-check (one Grep, always):** the written `sdd.md` must contain the four blueprint headings (`## Section 1: Case Definition` through `## Section 4: Integrations`). A freeform/summary SDD → re-delegate ONCE naming the template conformance gate; if it comes back non-conformant again, surface it to the user instead of building on it. **Degraded path:** if `uipath-planner` (or the Agent tool) is unavailable in this environment, say so in one line, ask the user to provide an `sdd.md` (or approve building from a design they paste), and stop — never improvise an interview, never fabricate an SDD. Cross-product planning beyond the case (multi-project solutions) also routes to `uipath-planner` — suggest it in text when the user's ask exceeds a single case build. 16. **Caseplan task `type` enum is closed — 9 values, schema-kebab.** Any task node written into `caseplan.json` MUST have `type` exactly one of: `process` | `agent` | `rpa` | `action` | `api-workflow` | `case-management` | `execute-connector-activity` | `wait-for-connector` | `wait-for-timer`. **Never** write the plugin folder name (`connector-activity`, `connector-trigger`) or the CLI `--type` flag value into the JSON node — those name the planning artifacts, not the schema. Never write `external-agent`, `external-workflow`, `document-extraction`, `flow-process`, `wait-for-event`, or any hallucinated value — there is no plugin to back them. `external-agent`, `external-workflow`, `document-extraction`, and `flow-process` are **not supported yet**. See [references/case-schema.md § Task type](references/case-schema.md) and the Plugin Index naming-asymmetry table below. -17. **Empty registry lookup → AskUserQuestion BEFORE any placeholder fallback.** When a planning-phase lookup returns 0 matches, present AskUserQuestion per lookup-batch (one prompt, not per-task) BEFORE any placeholder T-entry or per-plugin Unresolved Fallback, with options: (a) `Force pull and re-resolve` — loops back for still-empty; (b) `Use placeholders for all`; (c) `Create missing resources inline` — shown ONLY when ≥1 still-empty is creatable (an `agent` or an `api-workflow`) AND the CLI supports `registry --local`. **Create covers agents and API workflows only, gate-selected only** (never from SDD content alone; agent → `uipath-agents`, api-workflow → `uipath-api-workflow`); unselected + non-creatable empties (regular RPA process, action, case-management, connectors, agentic processes) → placeholder; the option is suppressed when `--local` is absent. Do NOT pre-judge via resource-name heuristics — the user's call. The gate and Select **group empties by `(name, type)`** (one row per resource, usages listed — non-creatable ones show only at the gate, annotated `placeholder only`); create-selected resources merge or split at [registry-discovery § 1c](references/registry-discovery.md#1c--dedup-the-selected-builds-one-resource-per-name-and-type) by I/O (identical-I/O usages → one build; differing → later renamed, anchor keeps the name; the SDD cell is updated only with user permission — never non-interactively). Placeholder fallback is valid only after `Use placeholders for all`. Build/register/verify mechanics live in [references/registry-discovery.md § Create-on-Missing](references/registry-discovery.md#create-on-missing-build-and-rediscovery) (gate detail: [§ MUST Confirm](references/registry-discovery.md#must-confirm-before-placeholder-fallback)). +17. **Empty registry lookup → AskUserQuestion BEFORE any placeholder fallback — unless the design-time gate already ruled.** When the same-session resolution ledger carries a `gateDecision` for the resource (`resolve-at-build` → placeholder; `create-during-build` → the inline-create flow below; `pick:` → bind that entry), execute it without re-asking — the gate ran once, at the planner's Case Review. Otherwise, when a planning-phase lookup returns 0 matches, present AskUserQuestion per lookup-batch (one prompt, not per-task) BEFORE any placeholder T-entry or per-plugin Unresolved Fallback, with options: (a) `Force pull and re-resolve` — loops back for still-empty; (b) `Use placeholders for all`; (c) `Create missing resources inline` — shown ONLY when ≥1 still-empty is creatable (an `agent` or an `api-workflow`) AND the CLI supports `registry --local`. **Create covers agents and API workflows only, gate-selected only** (never from SDD content alone; agent → `uipath-agents`, api-workflow → `uipath-api-workflow`); unselected + non-creatable empties (regular RPA process, action, case-management, connectors, agentic processes) → placeholder; the option is suppressed when `--local` is absent. Do NOT pre-judge via resource-name heuristics — the user's call. The gate and Select **group empties by `(name, type)`** (one row per resource, usages listed — non-creatable ones show only at the gate, annotated `placeholder only`); create-selected resources merge or split at [registry-discovery § 1c](references/registry-discovery.md#1c--dedup-the-selected-builds-one-resource-per-name-and-type) by I/O (identical-I/O usages → one build; differing → later renamed, anchor keeps the name; the SDD cell is updated only with user permission — never non-interactively). Placeholder fallback is valid only after `Use placeholders for all`. Build/register/verify mechanics live in [references/registry-discovery.md § Create-on-Missing](references/registry-discovery.md#create-on-missing-build-and-rediscovery) (gate detail: [§ MUST Confirm](references/registry-discovery.md#must-confirm-before-placeholder-fallback)). 18. **Layout state lives in top-level `layout`, not on the node/edge.** Do NOT emit node-level `position`, `style`, `measured`, `width`, `height`, `zIndex`. Do NOT compute stage `position.x = 100 + count * 500`. Do NOT emit edge `data.waypoints`. Emit top-level `layout: {}` (empty object) — FE auto-layouts on canvas load. The frontend's `transformCaseInMemoryJsonToDiskJson` strips these fields anyway when round-tripping through canvas; emitting them is harmless on read but wastes tokens. See [`references/case-editing-operations.md`](references/case-editing-operations.md). 19. **Generated output IDs use one global namespace.** Run [Step 12 Check 8](references/implementation.md#step-12--end-of-phase-3-validator-pass) once at Phase 3 exit; it is the mandatory uniqueness check. Do not enter Phase 4 until it passes, and do not substitute `uip maestro case validate` for it. 20. **Edges retired — `schema.edges` stays `[]`.** Never author a `TriggerEdge`/`Edge` object, for any node. Stage-to-stage flow is condition-driven (target stage's `entryConditions`, plus source `exitConditions` when it diverges); case start is the first stage's `case-entered` entry condition, not a Trigger→stage edge. FE auto-derives canvas connectors from conditions. Edge shapes exist only as a read-only appendix in [references/case-schema.md § Appendix](references/case-schema.md#appendix--edge-shapes-read-only--never-author) for reading canvas-round-tripped files. @@ -56,8 +56,8 @@ When `sdd.md` is absent, **Phase 0** designs the case by best assumption from th | Condition | Journey | |---|---| -| New case, or `sdd.md` provided, or no `caseplan.json` yet, or user asks to (re)build from a spec | **Greenfield** — Phase 0→6 below | -| `caseplan.json` exists AND intent is a targeted edit ("add a stage", "remove task X", "change a condition", "swap the trigger") | **Brownfield** — skip Phase 0→6, go to [references/brownfield.md](references/brownfield.md) | +| New case, or `sdd.md` provided, or no `caseplan.json` yet, or user asks to (re)build from a spec | **Greenfield** — design delegation + Phases 1→6 below | +| `caseplan.json` exists AND intent is a targeted edit ("add a stage", "remove task X", "change a condition", "swap the trigger") | **Brownfield** — skip delegation and Phases 1→6, go to [references/brownfield.md](references/brownfield.md) | Brownfield bypasses planning, prototyping, and their hard stops; it still honors the debug-consent gate (Rule 12) and reuses the Phase 5 / Phase 6 contracts. @@ -75,11 +75,11 @@ Keep the roadmap to five lines or fewer. Print it once per invocation; do not re ## Workflow -Decisions are front-loaded; the build runs unattended to the debug gate. **Phase 0** (best-assumption design → one confirmation, only when sdd.md absent; the Build answer is the consent — `sdd.md` renders alongside the first build actions, and an extra approval prompt exists only for explicit sign-off requests) → **Phase 1 Planning** (auto-proceed from the in-memory model; stop for review only when the request asks) → **Phase 2 Prototyping** (placeholder; Phase 2 → 3 pauses only when the up-front build-review preference chose the preview — Rule 11) → **Phase 3 Implementation** (no stop) → **Phase 4 Validate** (retry-cap stop on 3rd failure) → **Phase 5 Debug** (Run vs Skip-to-Publish stop — never bypassed) → **Phase 6 Publish** (Publish vs Done stop — never bypassed). +Decisions are front-loaded; the build runs unattended to the debug gate. **Design delegation** (a `uipath-planner` subagent writes `sdd.md` and returns the Case Review, only when sdd.md absent; this skill shows the review and the Build answer is the consent — the build starts with `uip solution init` + Phase 1, and an extra approval prompt exists only for explicit sign-off requests) → **Phase 1 Planning** (auto-proceed from the in-memory model; stop for review only when the request asks) → **Phase 2 Prototyping** (placeholder; Phase 2 → 3 pauses only when the up-front build-review preference chose the preview — Rule 11) → **Phase 3 Implementation** (no stop) → **Phase 4 Validate** (retry-cap stop on 3rd failure) → **Phase 5 Debug** (Run vs Skip-to-Publish stop — never bypassed) → **Phase 6 Publish** (Publish vs Done stop — never bypassed). ### Kickoff — set dev expectations first -Before any planning or build work, present the flow once so the dev knows the steps and where they'll be asked to decide. Emit the matching block below verbatim in tone (adjust wording to fit context; keep the checkpoint markers). Present ONCE per run — at Phase 0 start if the interview runs, else at Phase 1 start. Allow-listed standalone text block (Anti-patterns token cap); do not repeat it at later phases. +Before any planning or build work, present the flow once so the dev knows the steps and where they'll be asked to decide. Emit the matching block below verbatim in tone (adjust wording to fit context; keep the checkpoint markers). Present ONCE per run — at delegation start if the design delegation runs, else at Phase 1 start. Allow-listed standalone text block (Anti-patterns token cap); do not repeat it at later phases. **Greenfield** (building a new case): @@ -91,23 +91,23 @@ Before any planning or build work, present the flow once so the dev knows the st > - **Debug** (optional) — **you choose** whether to run the case for real (live emails / API calls). > - **Publish** (optional) — **you choose** whether to upload to Studio Web. -When Phase 0 runs, prefix one line: "First I'll design the case from what you've given me and show one SDD-shaped review packet with the case snapshot, data, primary and secondary stages, task classification rationale, other paths, rules/resources, and every decision I made — one confirmation, then I build; the full design doc (`sdd.md`) is saved alongside for reference." +When the design delegation runs, prefix one line: "First I'll design the case from what you've given me — checking your UiPath tenant along the way — and show one review packet with the case snapshot, data, primary and secondary stages, task classification rationale, other paths, rules/resources, and every decision made — one confirmation, then I build; the full design doc (`sdd.md`) is saved alongside for reference." (The design itself runs through the planner lane per Rule 15 — user-facing language never mentions the delegation.) **Brownfield** (editing an existing case): present the short version at entry — see [references/brownfield.md](references/brownfield.md). -### Phase 0 — Interview (conditional) +### Design delegation (conditional) -Triggered when `sdd.md` absent at resolved path. Read [references/phase-0-interview.md](references/phase-0-interview.md) for the flow (listen and ground → best-assumption sketch with mandatory other-path sweep → single SDD-shaped Case Review with data, primary and secondary stages/tasks, task classification rationale, rules, resources, other paths considered, and every decision disclosed → build start with a template-complete `sdd.md` written alongside), resumption, and the on-request HTML preview. Produces: +Triggered when `sdd.md` absent at resolved path (strict binary trigger: an `.md` at the resolved path whose basename contains `sdd` counts — a non-`sdd.md` basename is copied to `./sdd.md` and delegation is skipped; if the prompt names no `.md`, the default candidate is `./sdd.md`). Spawn the `uipath-planner` subagent per Rule 15; it designs best-assumption, writes `sdd.md`, and returns the Case Review + resolution ledger. Then run Rule 1's confirmation on the returned review before any build action. -> **Read budget for Phase 0.** Read `phase-0-interview.md`, `references/sdd-generation-rules.md` (the mental model + task-type reasoning the assumptions rely on), and `assets/templates/sdd-template.md` to begin. Read these independent references in parallel. Do NOT read `references/planning.md` or plugin planning/implementation references before the Phase 0 Case Review is approved, even when the user also requested `tasks.md`; planning starts after approval. Do NOT preload plugin `impl-json.md` files — those are needed only in Phase 2/3 and pulled in just-in-time per T-entry. **No-build design+plan budget:** when the same request explicitly asks for `sdd.md` plus `tasks/tasks.md` and says to stop before `caseplan.json`, use the compact no-build plan contract in `phase-0-interview.md`; if the request already says to produce those artifacts and stop, write them right after the Case Review without a second approval prompt. Do not open `planning.md`, plugin planning docs, schemas, registry, connections, or user lookup in that run. **Draft finalization budget:** when `sdd.draft.md` exists and the user asks to finalize it without building, read only the draft, `phase-0-interview.md` resumption/gate text, and `assets/templates/sdd-template.md`; write `sdd.md` directly after the gate. +> **Read budget for the delegation window.** Do NOT read `references/planning.md` or plugin planning/implementation references before the Case Review is approved, even when the user also requested `tasks.md`; planning starts after approval. Do NOT preload plugin `impl-json.md` files — those are needed only in Phase 2/3 and pulled in just-in-time per T-entry. **No-build design+plan budget:** when the request explicitly asks for `sdd.md` plus `tasks/tasks.md` and says to stop before `caseplan.json`, write both right after the approved Case Review without a second approval prompt (compact no-build shape — [references/planning.md § Step 3](references/planning.md)); do not open plugin planning docs, schemas, registry, connections, or user lookup in that run. -> **Light tenant grounding — requirement-driven.** No tenant work up front. For build runs, start the background login + registry chain only when the case first shows tenant-bound work, per [phase-0-interview.md § Tenant grounding](references/phase-0-interview.md#tenant-grounding--requirement-driven-one-light-pass-no-questions); then ONE parallel name-match pass at confirmation time (parallel read-only lookups when ≥ 4 items), joining the chain without ever delaying the confirmation. Single confident matches adopt silently; everything else is `resolve at build` — no schema discovery, no resource prompts in Phase 0. Explicit plan-only/no-build runs skip tenant grounding entirely and defer identities to the later build run. Phase 1 resolves authoritatively, reusing this session's successful pull (Rule 3 fast path). +Produces: -- `sdd.md` — rendered from the confirmed in-memory model against `assets/templates/sdd-template.md`, batched with the first build actions (design-only requests save it and stop) -- `sdd-viewer.html` — optional, rendered from `assets/templates/sdd-viewer.html` on explicit request only; Phase 1 ignores it -- `sdd.draft.md` — only on an explicit draft request; `tasks/registry-resolved.json` is written by Phase 1, not Phase 0 +- `sdd.md` — written by the planner subagent (template-conformant, gate-passed, `Status: ready`); design-only/draft requests belong to the planner invoked directly — this skill builds only +- `sdd-viewer.html` — optional, on explicit request only; owned by `uipath-planner` (its viewer template + Case Design Lane § HTML preview). Phase 1 ignores it +- `tasks/registry-resolved.json` — written by Phase 1 (seeded verbatim from the subagent's returned ledger, Rule 9) -If `sdd.md` already exists: skip Phase 0, hand to Phase 1 unchanged. +If `sdd.md` already exists: skip delegation, hand to Phase 1 unchanged. If `uipath-planner` is unavailable: degraded path per Rule 15 — ask for an `sdd.md` and stop. ### Phase 1 — Planning @@ -166,7 +166,7 @@ Completion report + **HARD STOP** AskUserQuestion (Step 13): `Run debug session` | I need to... | Read | |---|---| -| Generate sdd.md interactively when none provided | [references/phase-0-interview.md](references/phase-0-interview.md) | +| Design a case when no sdd.md exists | Delegate to `uipath-planner` (Rule 15 + § Design delegation) | | Plan tasks from sdd.md | [references/planning.md](references/planning.md) | | Execute tasks.md into a case | [references/implementation.md](references/implementation.md) | | Edit an existing caseplan.json (targeted edits) | [references/brownfield.md](references/brownfield.md) | @@ -234,11 +234,12 @@ Completion report + **HARD STOP** AskUserQuestion (Step 13): `Run debug session` ## Anti-patterns - **Do NOT leave a regular stage without an entry condition.** With edges retired (Rule 20), stage entry conditions are the sole reachability contract. Every regular stage needs ≥1 `stage-entry-conditions` rule naming a reachable predecessor; the first stage carries `case-entered`. A stage with no entry condition is orphaned and unreachable. -- **Do NOT substitute a generic build plan for Phase 0 confirmation.** For a new case without an SDD, project/workspace "plan first" rules are satisfied by the SDD-shaped Case Review: case snapshot, data contract, one stages list showing primary and secondary stages, activation modes (`sequential`, `parallel`, `event-driven`, `adhoc`, `fan-in`, `conditional-gate`), task classification rationale, **Other Paths Considered**, rules/tiers, resources, decisions, and review flags. A "Build Plan" / "Approve this plan" list of stages, artifact names, registry steps, output folders, validation commands, or placeholder caveats must not be used as the approval gate, and a user "Yes" to it must not create files. -- **Do NOT start Phase 1 planning before Phase 0 approval.** If the user asks for both a new design and `tasks.md`, the first stop is still the SDD-shaped Case Review. Read planning/plugin references and write `tasks.md` only after the Case Review is approved. +- **Do NOT substitute a generic build plan for the design confirmation.** For a new case without an SDD, project/workspace "plan first" rules are satisfied by the planner's SDD-shaped Case Review (section list in Rule 1). A "Build Plan" / "Approve this plan" list of stages, artifact names, registry steps, output folders, validation commands, or placeholder caveats must not be used as the approval gate, and a user "Yes" to it must not create files. + +- **Do NOT start Phase 1 planning before the Case Review is approved.** If the user asks for both a new design and `tasks.md`, the first stop is still the delegated design's SDD-shaped Case Review. Read planning/plugin references and write `tasks.md` only after the Case Review is approved. - **Do NOT ship a summary `sdd.md`.** The written SDD must preserve the template's title, table of contents, Section 1/2/3/4 headings, case metadata/triggers/variables, one full stage block per stage, one full task block per task, personas/app views, and integrations. A valid `caseplan.json` does not prove the SDD followed the template. -- **Do NOT plan only the primary flow.** Phase 0 must sweep for **Other Paths Considered** before confirmation: rework, rejection, withdrawal/cancellation, SLA escalation, external-system failure, manual override, optional side work, and alternate terminal outcomes. Model clear signals by assumption; ask one bounded question only when the source has no signal at all. -- **Do NOT validate after each T-entry.** Intermediate states expected invalid. Run `validate` once at end of Phase 2 (informational) and once in Phase 4 (authoritative). +- **Do NOT plan only the primary flow.** The delegated design must sweep for **Other Paths Considered** before confirmation: rework, rejection, withdrawal/cancellation, SLA escalation, external-system failure, manual override, optional side work, and alternate terminal outcomes. A hand-back without that sweep is incomplete — send it back through the lane, do not patch it silently. +- **Do NOT validate after each T-entry, and NEVER re-validate without an intervening edit.** Intermediate states expected invalid. Run `validate` once at end of Phase 2 (informational) and once in Phase 4 (authoritative); each Phase 4 retry MUST be preceded by a fix edit — validate → validate with no edit in between is a defect (see [references/phased-execution.md § Validate-loop guard](references/phased-execution.md#validate-loop-guard--no-re-validate-without-an-intervening-edit)). - **`tasks.md` (Phase 1) uses per-section batched Edit-append — NOT per-T-entry, NOT one mega-Write.** One Read + N Edit-appends per section (§4.2.1 vars, §4.3 triggers, §4.4 stages, §4.6 tasks, §4.7 conditions, §4.8 SLA). No re-Read between sibling Edits. **HARD CAP:** after §4.0a Step 1 Seed Write (<1KB header), single Write of whole `tasks.md` is FORBIDDEN regardless of size. Single Edit-append payload >30KB also FORBIDDEN — split per section even if cumulative payload exceeds 30KB. A 96KB tasks.md Write costs ~360s in one turn (20% of session); section-batched Edit-appends spread across ~7 turns of ~50s. TaskUpdate per T-entry preserves audit trail. Recovery on interruption: re-Read `tasks.md`, resume from next un-applied T-entry. See [planning.md § 4.0a](references/planning.md). - **`caseplan.json` (Phase 2 + 3) uses per-section batched writes — NOT per-T-entry.** One Read at section entry + one validate at section end. Tool primitive scales with section size: **<10 T-entries** → N Edits (one per T-entry, no re-Read between siblings); **≥10 T-entries** → may use single whole-section Write covering the section's nodes array at once, AFTER composing complete section state in reasoning. Untouched siblings (other sections, root fields) MUST be preserved verbatim from the Read — drop nothing. TaskUpdate per T-entry preserves audit trail regardless of write granularity. CLI-gated sections (Phase 2 §4.6 non-connector `tasks describe`, Phase 3 §9.7 connector `case spec`) use gather-then-write. Recovery on interruption: re-Read both files, resume from next un-applied T-entry. Full contract in [case-editing-operations.md § Per-section batch write contract](references/case-editing-operations.md#per-section-batch-write-contract--canonical) and [implementation.md § Per-plugin execution](references/implementation.md). - **Do NOT emit standalone text-only assistant turns between tool calls.** Status/progress text MUST share its turn with the next `tool_use` (text block + tool_use block in the same assistant content array). Standalone narration turns each pay full inference latency + prompt cache replay (~5s + ~250K cache-read tokens per turn) for no incremental progress. Cap inline status to ≤1 sentence / ~20 tokens. Per-T-entry audit lives in TaskUpdate, NOT in narration. @@ -254,7 +255,7 @@ Completion report + **HARD STOP** AskUserQuestion (Step 13): `Run debug session` - **Case file is flat at `//caseplan.json` — never under `content/`.** `content/` is the packed `.nupkg` layout (`package-descriptor.json`), not on-disk. Never `mkdir content` or author the root caseplan via `uip maestro case cases add` — write `caseplan.json` directly ([impl-json.md](references/plugins/case/impl-json.md)). - **Do NOT fabricate expression syntax for conditional SLA rules.** Describe condition in natural language; execution phase determines exact form. - **Do NOT place `tasks/` inside the solution or project directory.** `tasks/` (and its `tasks.md`, `registry-resolved.json`) lives next to `sdd.md` at the working root — NOT inside `/` or `//`. The case file path (`//caseplan.json`) does NOT root the planning artifacts; they track `sdd.md`, not `caseplan.json`. -- **Do NOT invoke other skills automatically — except the inline-create path.** If case needs a regular RPA process / action / child case / connector / agentic process that doesn't exist, emit placeholder task (Rule 8) and list missing resources in completion report; on-demand creation of those kinds is a future milestone. **Exception (agent + API workflow):** when the user picks `Create` at the Rule 17 gate, the skill builds the missing agent / API workflow inline by spawning a sub-agent that invokes `uipath-agents` (agent) or `uipath-api-workflow` (API workflow) — gate-selected only, never from SDD content alone. The `uipath-planner` handoff stays plain-text (Rule 15). -- **Do NOT spawn subagents for draft finalization or plan-only document generation.** Subagents are allowed only for the explicit inline-create build path after the Rule 17 gate. +- **Do NOT invoke other skills automatically — except the design delegation (Rule 15) and the inline-create path.** If case needs a regular RPA process / action / child case / connector / agentic process that doesn't exist, emit placeholder task (Rule 8) and list missing resources in completion report; on-demand creation of those kinds is a future milestone. **Exception (agent + API workflow):** when the user picks `Create` at the Rule 17 gate, the skill builds the missing agent / API workflow inline by spawning a sub-agent that invokes `uipath-agents` (agent) or `uipath-api-workflow` (API workflow) — gate-selected only, never from SDD content alone. Design delegation to `uipath-planner` is the sanctioned runtime handoff (Rule 15) and degrades gracefully when the planner is absent. +- **Subagents are allowed for exactly two purposes:** the Rule 15 design delegation (one `uipath-planner` subagent that writes `sdd.md` and returns the Case Review + ledger — this covers greenfield design AND draft finalization) and the inline-create build path after the Rule 17 gate. Never spawn subagents for anything else. > **Trouble?** Use `/uipath-feedback` to send report. diff --git a/skills/uipath-maestro-case/assets/templates/sdd-template.md b/skills/uipath-maestro-case/assets/templates/sdd-template.md deleted file mode 100644 index e0aebbd9fb..0000000000 --- a/skills/uipath-maestro-case/assets/templates/sdd-template.md +++ /dev/null @@ -1,674 +0,0 @@ -# SDD Template — Case Definition Blueprint -# Purpose: Defines the output format for sdd.md — a case definition blueprint -# that a developer can directly implement in the UiPath Case Designer. - ---- - -## Instructions for SDD Generation - -You are generating an **SDD — a case definition blueprint** (NOT a traditional -solution design document). Every section maps directly to what the UiPath Case -Designer actually consumes. A developer reading this document should be able to -build the case in the Case Designer without guessing. - -**Inputs:** -- Phase 0 interview answers (free-text + AskUserQuestion picks) — primary source -- This template — defines the output structure -- See [references/case-schema.md](../../references/case-schema.md) for the JSON schema reference (types, rules, SLA model) - -**Optional enrichment sources:** -- CLI registry cache at `~/.uip/case-resources/` (deployed processes, connectors, action apps from the user's tenant — flat `-index.json` files per resource type, populated by `uip maestro case registry pull`) -- IS connector cache at `~/.uipath/cache/integrationservice//` (`connections.json`, `activities.json`) for connection + operation metadata - -**Output:** `sdd.md` - -### Key Rules - -1. **SLA placement and response:** SLA is supported on the **case**, on **stages**, and on **`action` tasks only**. Do NOT put SLA on `process`, `agent`, `rpa`, `api-workflow`, `wait-for-timer`, `wait-for-connector`, `execute-connector-activity`, or `case-management` tasks. Separate the SLA clock from its response: notify-only stays in escalation actions; every other response (`start-task`, `enter-stage`, `exit-stage`, `exit-case`) is explicit in the SLA Response Map, with its own interrupting decision. - -2. **No skip conditions:** Stage skip conditions are NOT supported in the schema. Do not generate them. Use task-level `shouldRunOnlyOnce` for re-entry behavior. - -3. **Rule types:** Use only actual rule types from the schema: - - `case-entered` — case has been created/entered - - `selected-stage-completed` — a specific stage has completed - - `selected-stage-exited` — a specific stage has exited (not necessarily completed) - - `selected-tasks-completed` — specific tasks have completed - - `current-stage-entered` — the current stage has been entered - - `required-stages-completed` — all required stages completed - - `required-tasks-completed` — all required tasks in stage completed - - `wait-for-connector` — an Integration Service event received - - `adhoc` — ad-hoc / manually triggered task entry - - `runs-sequentially` — runs sequentially - - `user-selected-stage` - target of an upstream `wait-for-user` exit - - `sla-status-change` — a referenced case/stage SLA changed status (stage entry for an `enter-stage` response, task entry for `start-task`; 2 args for a breach, 3 for at-risk — see the reference contract under Stage Entry Conditions) - -4. **Exit conditions:** Every exit condition MUST specify: - - **Exit Type:** `exit-only` | `return-to-origin` | `wait-for-user` - - **Marks Stage Complete:** Yes | No - These are separate concepts. A stage can exit without completing (exit-only + No). - - **WHEN ↔ Marks Complete pairing (hard constraint — schema-enforced; applies identically to STAGE exit and CASE exit):** - - *Stage exit:* - - `Marks Stage Complete: Yes` → WHEN MUST be `required-tasks-completed` (typical) or `wait-for-connector` (stage completes when the bound connector event arrives). **NEVER** `required-stages-completed` or `selected-tasks-completed(...)`. - - `Marks Stage Complete: No` (routing / divergent exits) → WHEN may be `selected-tasks-completed("TaskA")`, `wait-for-connector`, etc. - - Same stage may carry one completion exit (`Yes` + `required-tasks-completed` / `wait-for-connector`) plus zero or more routing exits (`No` + `selected-tasks-completed` / `wait-for-connector`). - - `return-to-origin` is a completion exit: use `Marks Stage Complete: Yes` with `required-tasks-completed` (or `wait-for-connector`). Never pair it with `No` + `selected-tasks-completed`. - - *Case exit (preferred pattern: one row, `Yes` + `required-stages-completed`):* - - `Marks Case Complete: Yes` → WHEN MUST be `required-stages-completed` or `wait-for-connector`. **NEVER** `selected-stage-completed(...)` / `selected-stage-exited(...)`. - - `Marks Case Complete: No` (case exits without closing — rare) → WHEN may be `selected-stage-completed(...)`, `selected-stage-exited(...)`, or `wait-for-connector`. - -5. **Descriptions and rationale are mandatory:** Every case, stage, and task MUST have a prose description. Every stage/task and configured case/stage SLA MUST also preserve a concrete Design Rationale explaining the selected kind/type, activation/sequencing, and routing/threshold choices. No empty or placeholder descriptions/rationales. - -6. **Entry/exit conditions use WHEN + IF format:** - - **WHEN** = the rule type (event that triggers evaluation, e.g., `selected-stage-completed("Intake")`) - - **IF** = the optional `conditionExpression` (JavaScript expression evaluated against case variables, e.g., `applicationStatus == "Approved"`). To gate on an upstream task's output without a middle case variable, embed `vars.$xref('Stage','Task','output')` directly in the IF expression — see [bindings-and-expressions.md § In-expression references](../../references/bindings-and-expressions.md#in-expression-references-varsxref). - - **Display Name** (optional) = human-readable label for the condition row. Leave blank (`—`) to let the skill default it: entry/task-entry conditions → `Entry Rule {N}`; stage-exit/case-exit conditions → `Complete Rule {N}` when Marks Complete is `Yes`, `Exit Rule {N}` when `No`. `N` is the 1-based index within the same label kind in the stage / task / case container. Set a value only to override the default. - - **`wait-for-connector` WHEN** binds an Integration Service connector event. Name it inline in the WHEN cell (e.g. `wait-for-connector (Outlook "Email Received", Inbox)`) AND add a **Connector Rule Detail** block under the condition table. Applies to stage-entry, stage-exit, case-exit, and task-entry conditions. The IF cell is then an optional `=js:` gate on **case state** (`=js:vars.X`); the event payload is NOT directly accessible (no `event` namespace). **In-rule event-payload gating is NOT supported at runtime** — same-rule extract-then-gate (`response.X -> caseVar` on outputs + `=js:vars.caseVar` in IF) does not work; the case-backend evaluates the gate before the extract runs. To condition on the event payload, extract `response.field -> caseVar` on the connector rule and place the case-state gate on the DOWNSTREAM stage-entry / task-entry condition (where the extract has already populated the case var). - - **Connector Rule Detail block** — reproduce under any condition table whose WHEN is `wait-for-connector`: - ```markdown - **Connector Rule Detail:** - - Connector: {e.g., Microsoft Outlook 365} - - Connection: {instance name, or "Tenant default"} - - Event: {e.g., Email Received} - - Filter: {filter in business terms, or "—"} - - Event Parameters: {name=value pairs, e.g., parentFolderId="Inbox"; or "—"} - - **Connector Rule Outputs:** *(optional — omit when the rule is gate-only; target case variable MUST exist in the Case Variables table)* - - | Field | Binding / Value | - |-------|------------------| - | {schema field name, e.g., response.subject} | -> {case variable that receives this value} | - | — | {case variable} = {literal, =js:expression, or =js:vars.X.Y for dotted access} | - ``` - -7. **Task types — this skill generates 9 of the CLI's 10 task types. Choose based on WHAT THE TASK DOES, not its surface label.** The 10th CLI type, `external-agent`, has no generation plugin here — model it as `api-workflow` / `execute-connector-activity` instead (see below). Values like `connector-activity` or `wait-for-event` are not CLI task types at all. Emitting anything outside these 9 breaks downstream JSON generation. Consider all 9 for every task: - - `action` — a human must review, approve, or make a judgment call. The task PAUSES for a person. - - `agent` — AI reasoning: classification, criteria application, document analysis, risk assessment, triage. Use for any semi-structured reasoning. - - `process` — deterministic multi-step BPMN: routing, orchestration, batch processing, report generation. No judgment (human or AI). - - `rpa` — UI automation for legacy systems without APIs. An attended or unattended robot drives a desktop/web app. - - `api-workflow` — structured API call with defined I/O. System-to-system. - - `wait-for-timer` — waits for a duration, date, or schedule. - - `wait-for-connector` — waits for an Integration Service event from an external system (in-stage trigger). - - `execute-connector-activity` — executes a pre-built IS connector operation. Prefer over `api-workflow` when a connector exists. - - `case-management` — starts a child case with its own lifecycle. - - **A well-designed SDD uses a MIX of types.** If all tasks are `action`, the SDD is wrong — most processes have automated steps. If no tasks are `agent`, consider whether any task involves classification, criteria application, or document analysis. - - **Externally-hosted AI agents** (CrewAI, Salesforce Einstein, Databricks, LangChain, etc.) have no first-class type in this skill. Model them as `api-workflow` (system-to-system invocation) or `execute-connector-activity` if a connector exists. Do not invent `external-agent`. - -### Naming Conventions - -- **Case names:** PascalCase (e.g., `MortgageLoanOrigination`) -- **Case identifier prefix:** UPPER, 2-4 characters (e.g., `MLO`) -- **Variable names:** camelCase (e.g., `applicationStatus`, `loanAmount`) -- **Workflows/Processes:** PascalCase (e.g., `ValidateEligibility`) -- **Entity names:** PascalCase (e.g., `LoanApplication`) -- **Entity fields:** camelCase (e.g., `applicantName`) -- **Case Designer display names:** stages, tasks, condition rule names, SLA rule titles, and escalation titles use only letters, numbers, spaces, hyphen (`-`), and underscore (`_`). Do not generate colons, periods, slashes, backslashes, quotes, parentheses, ampersands, commas, semicolons, emoji, or other symbols. Normalize unsafe display punctuation to spaces, collapse spaces, and disclose any changed display names in the Case Review. -- **External lookup names:** do not normalize deployed resource names, connector names, Action App titles, API/process/agent names, queue names, or bucket names used for tenant lookup. Keep a separate safe Case Designer display name when an external lookup name contains punctuation. - -### Output Structure - -The rendered `sdd.md` must preserve this structure. Do not replace it with a summary, build plan, source trace, or abbreviated stage/task list; every section and every modeled stage/task detail block below is part of the authoring contract. - -The generated SDD must start with: - -1. **Title** — `# SDD — {Case Name}` -2. **Subtitle** — Case Definition Blueprint blurb -3. **(optional) Version / Change Log** — a single blockquote under the subtitle when the SDD is revised: `> **Version: vN** — `. Use it to record material build-driven corrections (e.g. "rebound `caseId` to `=metadata.ExternalId` — the workflow does not return it") so a reader/coding-agent sees the rationale, not just the result. Omit on a first draft. -4. **Table of Contents** — Numbered list with markdown anchor links. Use plain numbered list items with links, NOT headings (no `###`). Format: - ```markdown - ## Table of Contents - - 1. [Case Definition](#section-1-case-definition) — Metadata, SLA, Triggers, Exit Conditions, Variables - 2. [Stages & Tasks](#section-2-stages--tasks) - - [Stage 1: {Name}](#stage-1-{slug}) — {N} tasks - - [Stage 2: {Name}](#stage-2-{slug}) — {N} tasks - ... - 3. [Personas & App Views](#section-3-personas--app-views) — {N} Personas, Process App Views - 4. [Integrations](#section-4-integrations) — IS Connectors, API Workflows, Agents, Processes & RPA, Child Cases, External Agents - ``` - Anchor slugs must match the actual heading text: lowercase, spaces→hyphens, strip special chars (e.g., `### Stage 1: Request Intake & Triage` → `#stage-1-request-intake--triage`). - -### Output Rules (applies to every section of the rendered SDD) - -- The SDD is a standalone developer artifact. It must NOT reference its own generation sources. Forbidden phrases anywhere in the output: `interview answers`, `from cache`, `from the registry`, `from state.*`, `REVIEW:`, `wiki/`, `PDD`, `pdd.md`, or any chain-of-thought explanation of how a value was derived. -- State every fact directly. If mock substitution is permitted, say "Mock Connector substitution is permitted until a live connection is provisioned" — do not attribute the decision to a generation source. -- Unknown values render as `—`, not as REVIEW markers. Review items belong in the Phase 0 round-4 summary or post-build loop, not in the document body. -- **Express author intent, not skill implementation.** The SDD describes the business case; the skill is responsible for translating that into the plan and the JSON. The author should not need to know how the skill internally builds anything. Prose in Descriptions, subtitles, and any narrative cells MUST follow these rules: - - **No explanatory Notes about column semantics or skill internals.** Forbidden: `> **Note:**` blocks (or any prose) that justify why a row is shaped a certain way using skill vocabulary — e.g., "this Variable has no `sourceTriggers` because its producer is a task," or "the `->` operator captures the response field into the case variable." The columns and operator notation are the agreed authoring shapes; the skill's validator enforces correctness. Authors do not document their own conformance. - - **No raw structured formats inline.** Forbidden: `FilterTree` JSON, payload schema JSON, expression-language ASTs, `=jsonString:` blobs, or other plugin-internal data shapes embedded in the SDD body. Filters, payloads, and expressions belong as plain English. The skill builds the structured form. Canonical filter expression: - ``` - **Filter:** Subject contains "urgent" AND From is "alice@example.com". - ``` - The wait-for-connector / connector-activity plugin builds the FilterTree from this prose, validates the field/operator pair against the trigger spec, and AskUserQuestion's if a clause is unsupported. - - **No skill-internal vocabulary in prose.** Forbidden in any narrative cell: `Pattern C`, `bridge`, `companion`, `inputOutputs[]`, `=jsonString:`, `groupOperator`, `essentialConfiguration`, `savedFilterTrees`, `dispatcher`, `Phase 2 validator`, `Phase 3 dispatcher`, `Q10 II`, `Finding #N`, `io-binding`, `aliased into`, `aliased from`, `aliased back into`, `reassign`, `originalVar`, `auto-mint`. These are internal terms used inside the skill's references — not the author's vocabulary. Describe outcomes in business terms instead. Examples: - - **Bad:** `Slack message timestamp aliased into the messageTs Variable.` - - **Good:** `Slack message timestamp.` (the Binding column already declares the wiring visually) - - **Bad:** `INVALID (Finding #6): In-argument with event-trigger source — Dispatcher must reject.` - - **Good:** `Subject sourced from the trigger. (Misclassified: trigger-sourced rows are Variables, not In-arguments.)` - - **What stays:** column headers (`sourceTriggers`, `sourceFields`, `Category`, etc.), the `->` operator in Outputs Binding cells (extract), the `=` operator in Outputs Binding cells (set/compute/copy), and `=vars.X` / `=metadata.X` / `=js:(...)` expressions in Input Binding cells and IF columns. These are the *agreed authoring shapes*, not skill internals. - ---- - -## Section 1: Case Definition - -**Purpose:** Top-level case configuration — what appears at the root of the case plan. This section defines the case identity, SLA, triggers, exit conditions, and the complete variable inventory. - -### Case Metadata - -| Property | Value | -|----------|-------| -| Case Name | {PascalCase name} | -| Case Description | {2-3 sentence description of what the case manages} | -| Case Identifier | Type: {constant \| external}. Constant → Prefix: {2-4 char UPPER prefix}. External → Source: {=vars. \| =js:`expression`} | -| Case-Level SLA | {count} {unit: min/h/d/w/m} | -| SLA Type | {time-based \| condition-based} | -| SLA Title | {non-empty title, no `:`; omit this row when `Case-Level SLA` is `—`} | -| Case App | {Enabled \| Disabled} — whether the in-product Case App UI is on (`caseAppEnabled`; default Disabled) | -| Task-output passing | {Direct \| Shared} — `caseDirectlyPassTaskOutputs` (Direct = a task's outputs flow straight to downstream tasks; default Direct) | -| Case Identifier source | {`=metadata.ExternalId` (platform-generated — the default) \| custom} — what every `caseId` task input binds to | - -> **Case App validation contract:** Stage names must be non-empty, unique, and safe for Case Designer display. Task names and condition display names must be safe. Every SLA rule and escalation needs a non-empty, target-unique safe title/display name. Safe display characters are letters, numbers, spaces, hyphen, and underscore. SLA durations must be positive; minute-based SLAs must be 15–1000 minutes. Non-default SLA rows need an expression; escalations need a recipient, and at-risk escalations need a percentage. - -### Case-Level SLA Escalation Rules - -**Design Rationale:** {Why this target, at-risk threshold, recipients, and breach behavior fit the case requirement; name any stage entered through `sla-status-change` and whether that response interrupts active work.} - -| SLA Status | Threshold | Action | Display Name | -|------------|-----------|--------|--------------| -| At-Risk | {percentage}% of SLA duration | {Notify: recipient or group} | {escalation title, root-unique, no `:`} | -| Breached | 100% of SLA duration | {Notify: recipient or group} | {escalation title, root-unique, no `:`} | - -> `Display Name` is what a `sla-status-change` entry references. `—` → `Escalation Rule {N}`, valid only when nothing references that escalation. - -### SLA Response Map - -> **Required whenever any SLA is configured** (case, stage, or `action` task) — one row per `(Scope, SLA, Status)`. This table is the single place breach and at-risk behavior is decided; never leave the response implied by SLA duration text or by an escalation's wording. Omit the whole section only when no SLA exists anywhere in the case. - -| Scope | SLA | Status | Response | Target | Interrupting | Rationale | -|-------|-----|--------|----------|--------|--------------|-----------| -| {case \| stage: `` \| task: ``} | {SLA Title} | {At-Risk \| Breached} | {notify-only \| start-task \| enter-stage \| exit-stage \| exit-case} | {`—` for notify-only; task name for start-task; stage name for enter-stage; exit row ref for exit-stage/exit-case} | {`—` for notify-only and for every start-task; Yes \| No otherwise} | {why this response fits the source} | - -> **Choosing the `Response`** — read it off the source, never off the SLA's scope: -> -> | Response | Source says | Where it lands | -> |---|---|---| -> | `notify-only` | notify / alert / email / page someone | escalation `Action` row above — no stage, no task, no entry condition | -> | `start-task` | follow-up work inside the **same** breached stage (reminder, reassignment, manager check, extra approval) — "as part of the review", "the reviewer keeps working and also does X" | the follow-up task in that stage, carrying `sla-status-change` in its own **`Entry Condition:`** block against that stage's own SLA. **No new stage, and no Stage Entry Conditions row** — a stage-entry rule re-enters the stage and re-runs its other tasks. | -> | `enter-stage` | a separate lane owns it — ownership change, "hand it to", "escalate into ``", recovery, visible lifecycle step | the destination stage's Stage Entry Conditions row | -> | `exit-stage` | the breached stage should end, fail, or route away | that stage's Stage Exit Conditions row | -> | `exit-case` | the case should close, cancel, fail, or reach an alternate terminal outcome | a §1.4a Case Exit Conditions row | -> -> **`start-task` vs `enter-stage` turns on WHERE the work lives, not on whether it interrupts** — `enter-stage` can itself be `Interrupting: No`, so "the team keeps working" does not choose between them. A named **task** ("raise a Senior Assessor Check approval") never justifies a new stage: if the `Target` you are about to write is a task name rather than a lane the source describes in its own right, the response is `start-task`, and the task goes in the breached stage. -> -> **Default:** absent a stated response, both statuses are `notify-only` — `Target` and `Interrupting` are `—`. Do NOT invent a stage, task, or routing change for an SLA the source only asks to notify about. -> -> **`Interrupting` is a separate decision from scope.** `Yes` when the response stops, pauses, takes over, or reroutes the active work; `No` when the response runs alongside it (parallel oversight). A case-scope SLA does not imply `Yes`. When the response produces a **Stage** Entry Conditions row (`enter-stage`), the value here MUST match that row's `Interrupting` cell. A **`start-task`** response is always `—`: the rule lives in the follow-up task's own `Entry Condition:` block, which has no `Interrupting` column because a task entry interrupts nothing. -> -> **A row whose `Response` is not `notify-only` MUST have a matching rule elsewhere in this SDD** — a `sla-status-change` row in a task's **`Entry Condition:`** block for `start-task`, a `sla-status-change` **Stage Entry Conditions** row for `enter-stage`, a stage-exit row, or a §1.4a case-exit row. A `start-task`/`enter-stage` row with no `sla-status-change` entry anywhere is a blocking render error, and so is an `sla-status-change` entry — task or stage scope — with no row here. - -### Variable SLA Rules - -> Include this table only if SLA Type is `condition-based`. Each row defines an expression-keyed SLA override; the time-based default lives in the Case Metadata `Case-Level SLA` cell above. FE persists `slaRules[]` with non-empty `conditionExpression` per row (PO.Frontend `CaseManagementSlaProperties.tsx`). - -| Expression | SLA | Unit | Display Name | -|------------|-----|------|--------------| -| {conditionExpression evaluated against case variables} | {count} | {h \| d \| w \| m} | {non-empty root-unique title without `:`} | - -### Case Triggers - -> Variable mapping (which trigger payload field populates which case variable) is declared in the **Case Variables** table below via `sourceTriggers` / `sourceFields` columns — NOT here. This table just identifies and configures each trigger. - -| T# | Trigger Type | Source | Configuration | -|----|-------------|--------|---------------| -| T02 | {Manual \| Intsvc.EventTrigger \| Intsvc.TimerTrigger} | {source system, connector, or "Manual"} | {see Configuration rules below} | - -> Number triggers sequentially starting at T02 (T01 is reserved for the case file). The T-number is referenced by Case Variables rows whose value comes from this trigger's payload. -> -> `Manual` is author shorthand — a manual trigger has **no** `serviceType` in the generated JSON (the CLI serviceType enum is `None` / `Intsvc.EventTrigger` / `Intsvc.TimerTrigger`; never write `serviceType: "Manual"`). - -**Configuration column — write user-specified intent only:** - -| Trigger type | What to write | -|---|---| -| Event trigger | The operation in business terms (e.g., `Calendar created`, `Email received`, `Record created`). For tenant case-entity / business data-object starts, preserve the object name in Source (e.g., `expense_requests`) and write the business event in Configuration (e.g., `Record created`). Append a filter expression if the user wants filtering (e.g., `Email received in Inbox; filter: subject contains "URGENT"`). Append a required event-param value only when the user supplies it explicitly (e.g., `Email received in folder ""`). | -| Timer trigger | Cycle or duration (e.g., `every 24 hours`, `daily at 09:00 UTC`). | -| Manual | `N/A` or omit. | - -DO NOT include in Configuration: -- CLI enum values like `CALENDAR_CREATED` or `createdRecord` (the skill resolves these from the IS connector cache at planning time). -- Default modes like `polling` vs `webhook` (the skill defaults; the user only overrides when they care). -- Meta notes like `No required event parameters` or `No user filter` (absence is the default; the skill discovers required params at `case spec` time). -- Connector activity slug, HTTP method, or any spec-discovered detail. - -> **Tenant object starts are still event triggers.** If the user says a case starts -> when a tenant case-entity / data-object record is created, author -> `Intsvc.EventTrigger` with that object name as Source. Do NOT downgrade to -> `Manual` just because the eval sandbox or current tenant may not have the -> object provisioned. Planning/implementation preserve unresolved event triggers -> as placeholders. - -### Case Exit Conditions - -> **WHEN ↔ Marks Case Complete pairing is a schema constraint (see Key Rule 4):** `Yes` row MUST use `required-stages-completed` (preferred) or `wait-for-connector`; `No` row MAY use `selected-stage-completed(...)` / `selected-stage-exited(...)` / `wait-for-connector`. Mixing `Yes` with a `selected-*` rule is invalid. - -| WHEN | IF | THEN | Marks Case Complete | Display Name | -|------|-----|------|---------------------|--------------| -| {`required-stages-completed` for Yes; `selected-stage-completed("StageName")` or other rule for No} | {conditionExpression, or "—" if none} | Case exited | {Yes \| No} | {optional label, or "—" → defaults to `Complete Rule {N}` (Marks Complete = Yes) / `Exit Rule {N}` (No)} | - -> If `WHEN` is `wait-for-connector`, add a **Connector Rule Detail** block under this table (see Key Rule 6) — it binds the IS connector event the rule waits for. - -### Case Variables - -> This table holds **only**: `In` / `Out` arguments; trigger-payload `Variable`s (`sourceTriggers` + `sourceFields`); and case-level state read by a condition (`IF`) or consumed in **≥ 2 places**. An input that is simply one upstream task's output is **referenced directly** — whole-value `<- "Stage"."Task".out`, or in-expression `vars.$xref('Stage','Task','out')` — and is **NOT** a row here (the emitting task self-declares the output and is its own producer). Minting a row to relay one task's output into one downstream consumer is the **case-var relay anti-pattern**: declare a row for an output only to rename it, set a custom `Default` / `Type` / `Description`, or expose it as case-level state read in multiple places. Every row's `Category` column is REQUIRED — drives classification at build time. Inference from other columns is no longer supported. -> -> For worked patterns by use case (single-trigger, multi-trigger, In / Out / Variable, task-local-only via direct xref), see [`sdd-template-examples.md`](sdd-template-examples.md). - -| Name | Category | Type | sourceTriggers | sourceFields | Default | Description | -|------|----------|------|----------------|--------------|---------|-------------| -| {camelCase name} | {In \| Out \| Variable} | {string \| integer \| float \| double \| boolean \| datetime \| date \| jsonSchema \| file} | {`Variable`: single `T` or CSV when multiple triggers feed the same slot. `In`: optional single `T` selecting the bound trigger (blank = primary trigger; never CSV). Empty for pure state / Out-args} | {single payload path when one trigger; keyed `T: ; T: ` when multiple triggers; empty on `In` rows} | {default value or empty} | {what this variable represents} | - -**Category semantics (author-facing summary; canonical definition in [`global-vars/impl-json.md` § Pattern shapes by category](../../references/plugins/variables/global-vars/impl-json.md)):** - -- **`In`** — formal case argument supplied at case start by an external caller (manual trigger via API) OR initialized from `Default` (event / timer triggers, which have no caller). Works with any trigger type. By default an In-arg binds to the primary trigger (T02); to bind it to a specific trigger, put that trigger's single `T` in `sourceTriggers` (one only, never a CSV). `sourceFields` stays empty for `In` rows. For event-trigger-payload-extraction (where the value comes from the event's payload), use `Variable` with `sourceTriggers` + `sourceFields` (Use Case 2) instead — that's a different operation. **File-type In-args:** the runtime caller must pre-create the JobAttachment (`POST /odata/Attachments`, then `PUT` the bytes to the returned blob URI) and pass the resulting `{ID, FullName, MimeType, Metadata}` record as the In-arg value plus the attachment ID in `StartProcessDto.Attachments[]`. The Maestro Studio Web "Start case" dialog handles this automatically when the user picks a file; programmatic callers must do it themselves. -- **`Out`** — formal case argument returned to the caller at case end. Value comes from a task's Outputs row that targets this Name (the producer) OR from a `Default` value if no task fires. `sourceTriggers` MUST be empty (direction mismatch — values flow case→caller, not trigger→case). -- **`Variable`** — case-internal state. May be populated by one trigger's payload (single T-number in `sourceTriggers` + single path in `sourceFields`), by multiple triggers' payloads sharing the same slot (CSV in `sourceTriggers` + keyed `T: ` format in `sourceFields`), by a task output (use `->` operator in that task's Outputs table — same Name on both sides drives the wiring), or initialized via `Default` only. - -**`sourceFields` notation:** - -- **Single-trigger:** bare payload path. Examples: `response.subject`, `response.user.id`, `Error.code`. -- **Multi-trigger:** keyed format `T: ; T: ` — every T-number listed in `sourceTriggers` MUST have a matching path entry in `sourceFields` (strict, no defaults). Example: `T02: response.user; T03: response.initiator`. Same Variable Name maps to different payload fields per trigger; whichever trigger fires writes its extracted value to the shared variable slot. - -Paths support dot-path nesting (e.g., `response.user.email`); array indexing (`items[0]`) not supported in v1. - -**Out-arg producer rule (validated at end of Phase 3):** - -Every `Out` row must have at least one of: -1. A `Default` value (the fallback returned when no task fires) -2. A task whose `Outputs` table includes a row that targets this Out-arg's Name via `-> {name}` or `{name} = {expression}` - -If neither holds, the io-binding validator surfaces the misalignment. - -**Examples:** - -| Name | Category | Type | sourceTriggers | sourceFields | Default | Description | -|------|----------|------|----------------|--------------|---------|-------------| -| caseStatus | Variable | string | | | "Open" | Pure case state, initialized at case start | -| subject | Variable | string | T02 | response.subject | | Populated by event trigger payload at trigger fire | -| caseStarter | Variable | string | T02, T03 | T02: response.user; T03: response.initiator | | Shared slot — whichever trigger fires populates it | -| applicantName | In | string | | | | Formal In-arg supplied by API caller; blank sourceTriggers → bound to primary trigger | -| reviewerNote | In | string | T03 | | | In-arg bound to the T03 trigger (single T-number; sourceFields stays empty) | -| finalDecision | Out | string | | | "Pending" | Out-arg; producer is "Approve Decision" task; "Pending" returned if no task fires | -| reviewCount | Variable | integer | | | 0 | Counter incremented by tasks via `=` operator | - ---- - -## Section 2: Stages & Tasks - -**Purpose:** The case plan — every stage as a self-contained subsection with its own entry/exit conditions, SLA, and task definitions with inline I/O bindings. Stages use the single node type `case-management:Stage`; a secondary stage is distinguished by `data.stageType: "secondary"` (a primary stage omits `stageType`). - -**I/O bindings — how the Inputs / Outputs tables drive task wiring:** - -- **Inputs `Binding` column** = the value that feeds this task input at runtime. Accepts a case-variable reference (`=vars.X` — top-level only, no dotted access), a JS expression for dotted/metadata/computed forms (`=js:vars.X.Y`, `=js:metadata.X`, `=js:(...)`), or a literal value (`"50"`, `0`, `true`). The skill translates SDD `=metadata.X` to `=js:metadata.X` at impl time; for dotted case-var access, write `=js:vars.X.Y` directly per [bindings-and-expressions.md § Two evaluator paths](../../references/bindings-and-expressions.md#two-evaluator-paths). -- **Outputs `Binding / Value` column** uses one of two operators: - - **`-> caseVar`** (extract): the value at the runtime path in the `Field` column is extracted into the named case variable. `Field` is the **full runtime path relative to the task's root scope** — write `response.status` for a connector payload field, `Action` for an action task's top-level output, `Error.code` for a nested error sub-field, etc. The skill emits `source: "="` verbatim; no envelope inference. - - **`caseVar = `** (set / compute / copy): the case variable is assigned the result of the expression at task completion. The `Field` column is `—` for `=` rows. Expression can be a literal (`"InReview"`, `5`), a computed value (`=js:(vars.count + 1)`), a top-level case-var copy (`=vars.X`), or a sub-field copy via JS eval (`=js:vars.X.Y`). -- **In-expression upstream reference (`vars.$xref(...)`)** — inside ANY `=js:` expression (a composite input payload, a computed `=` output, an IF `conditionExpression`, an SLA expression), reference another task's output directly with `vars.$xref('Stage Name','Task Name','output_name')` instead of routing it through a "middle" case variable. Single quotes only. The skill resolves it to the source output's runtime reference ID at build time. Use this whenever a case variable would exist only to carry one task's output into a downstream expression. When the output IS the entire input value (not part of a larger expression), use the whole-value `<- "Stage"."Task".output` form instead. See [bindings-and-expressions.md § In-expression references](../../references/bindings-and-expressions.md#in-expression-references-varsxref). - -- **Case identity — bind `caseId` to `=metadata.ExternalId`.** The case external id is platform-generated (constant prefix or external expression) and exposed as `metadata.ExternalId`; it is NOT a task output. Every task input named `caseId` binds to `=metadata.ExternalId`. **Never** author a `-> caseId` extraction on a workflow whose result has no `caseId` key — it resolves to runtime null. (`Action` is the conventional top-level output field of an `action` task — its button result — captured via `Action -> `.) - -**Authoring rules:** - -- Every target case variable on the left side of `->` or `=` MUST appear in the Case Variables table. The Outputs table doesn't declare new variables — it wires existing ones. -- Per task: each target case variable appears in at most one Outputs row. No double-binding. -- `->` rows require a non-empty `Field` column containing the full runtime path. `=` rows have `Field` as `—`. - -**Examples (in any task's Outputs table):** - -``` -| Field | Binding / Value | -|------------------|-------------------------------------------| -| response.status | -> sendStatus | ← connector payload field → vars.sendStatus -| Error | -> sendError | ← top-level Error sibling → vars.sendError -| Action | -> userDecision | ← action task top-level output → vars.userDecision -| — | caseStatus = "InReview" | ← set caseStatus literally -| — | reviewCount = =js:vars.reviewCount + 1 | ← increment counter -| — | summary = =vars.response.message.text | ← copy another variable's sub-field -``` - -The runtime engine resolves the binding when the task completes, writing the resolved value into the named case variable's slot. - -> Repeat the following structure for each stage in the case plan. Number stages sequentially. - ---- - -### Stage {N}: {Stage Name} - -> **Heading form:** a **primary** stage uses `### Stage {N}: {Stage Name}` (N = main-flow sequence number); a **secondary** stage uses `### Secondary Stage: {Stage Name}` instead (no number). Both render a `case-management:Stage` node — the kind is set by the `**Stage Kind:**` field below. - -**Type:** Stage -**Stage Kind:** {primary \| secondary} _(secondary stages use the `### Secondary Stage:` heading AND set `secondary`; primary stages use `### Stage {N}:` and OMIT this line — default = primary)_ -**Design Rationale:** {Why this stage is primary/secondary and why its entry/exit behavior fits. For a global-event secondary stage, name the event and explain that one interrupting entry replaces per-primary-stage tasks/exits.} -**Description:** {Prose description of what this stage accomplishes in the case lifecycle} -**Required for Case Completion:** {Yes \| No} -**Interrupting:** Yes _(secondary stages only — i.e. Stage Kind: secondary; omit for primary)_ - -#### Stage Entry Conditions - -> **Valid WHEN rule types for stage entry (strict subset of Key Rule 3):** `case-entered` (first stage of the case — no target), `selected-stage-completed("StageName")`, `selected-stage-exited("StageName")`, `user-selected-stage` (target of an upstream `wait-for-user` exit — no target; stage opts into the picker by declaring this rule), `wait-for-connector` (external/global event interrupt), `sla-status-change("","")` for a breach / `sla-status-change("","","")` for at-risk (the **`enter-stage`** SLA response — see the reference contract below). Other rule types from Key Rule 3 are NOT valid here. A `start-task` response does NOT belong in this table: it is a Task Entry Condition on the follow-up task. -> -> **Interrupting column:** `Yes` lets the condition fire while another stage is active and interrupt it. Use `Yes` on every secondary-stage entry row, with one carve-out: an `sla-status-change` row whose response is parallel oversight (the breached work keeps running) is `No`, and its lane still stays secondary with `Required for case completion: No`. Otherwise use `No` only for normal entry on regular stages; if the work should not interrupt and is not that SLA carve-out, it is not a secondary stage. -> -> Each row is a separate entry condition. List multiple rows when a stage can be entered through more than one path (e.g., normal completion of an upstream stage AND an interrupting connector event). - -| WHEN | IF | Interrupting | Display Name | -|------|-----|-------------|--------------| -| {one of: `case-entered` \| `selected-stage-completed("StageName")` \| `selected-stage-exited("StageName")` \| `user-selected-stage` \| `wait-for-connector` \| `sla-status-change("","")` \| `sla-status-change("","","")`} | {conditionExpression, or "—" if none} | {Yes \| No} | {optional label, or "—" → defaults to `Entry Rule {N}`} | - -> If `WHEN` is `wait-for-connector`, add a **Connector Rule Detail** block under this table (see Key Rule 6). -> -> A global `wait-for-connector` / graph-changing `sla-status-change` entry on an interrupting secondary stage applies regardless of which primary stage is active. Do not repeat the event as a task or exit rule on every primary stage. An `sla-status-change` row here is always the `enter-stage` response — it routes the case to *this* stage; a non-interrupting (parallel oversight) response uses `Interrupting: No`. A `start-task` response never appears here. -> -> **`sla-status-change` reference contract.** Every arg used must be declared in this SDD — the rule has no duration of its own. `` is `root` (case-level SLA; reserved token) or the SLA-owning stage name, and scopes the lookups to that target's tables: `` is its `SLA Title` cell (or a Variable SLA Rules `Display Name`). **Arg count carries the status:** two args is a **Breached** rule — a breach references the SLA alone and needs no escalation to exist; three args is an **At-Risk** rule, where `` is one of that same SLA's escalation `Display Name`s with At-Risk status. Use one row per status. Phase 1 resolves the SLA to `slaId`, and the escalation (at-risk only) to `escalationId`; a reference that does not resolve is a blocking error. Adding an escalation to a breach row silently converts it to at-risk — never do it to make a reference "complete". Examples: `sla-status-change("root","Application SLA")` (breach), `sla-status-change("root","Application SLA","Application SLA at risk")` (at-risk). - -#### Stage Exit Conditions - -> **WHEN ↔ Marks Stage Complete pairing is a schema constraint (see Key Rule 4):** `Yes` row MUST use `required-tasks-completed` (or `required-stages-completed`); `No` row MAY use `selected-tasks-completed(...)`. Mixing is invalid. -> Completion (`Yes`) and routing (`No`) rows share this one table. **Regular stage-to-stage routing is expressed by the destination stages' Entry Conditions** (`selected-stage-completed("This Stage")` / `selected-stage-exited("This Stage")`) — one stage can fan out to N stages, each declaring it as their entry trigger. `return-to-origin` returns to the origin stage automatically. -> **Canonical return shape:** `return-to-origin` requires `required-tasks-completed` (or `wait-for-connector`) + `Marks Stage Complete: Yes`. It is not a `No` + `selected-tasks-completed` routing row. -> **Exception carve-out:** to route this stage INTO a decision/signal-routed exception lane, add a gated divert row here — `Marks Stage Complete: No`, `selected-tasks-completed("")`, `IF =js:( === )`, `exit-only`, with `exitToStageId` → the secondary stage — AND gate this stage's `Yes` completion row with the inverse `IF`. The lane returns via `return-to-origin`. Omitting the divert row → dual-fire or deadlock. See sdd-generation-rules § Logical integrity step 5. - -| WHEN | IF | Exit Type | Marks Stage Complete | Display Name | -|------|-----|-----------|---------------------|--------------| -| {`required-tasks-completed` or `wait-for-connector` for Yes; `selected-tasks-completed("TaskName")` or `wait-for-connector` for No} | {conditionExpression, or "—" if none} | {exit-only \| return-to-origin \| wait-for-user} | {Yes \| No} | {optional label, or "—" → defaults to `Complete Rule {N}` (Marks Complete = Yes) / `Exit Rule {N}` (No)} | - -> If `WHEN` is `wait-for-connector`, add a **Connector Rule Detail** block under this table (see Key Rule 6). - -#### Stage SLA - -> Stage SLA supports the same conditional + default `slaRules[]` model as the case root. For `condition-based`, keep the default row below and add one or more Stage Variable SLA Rules before it. - -**Design Rationale:** {Why this target, duration, at-risk threshold, recipients, and breach behavior fit the stage requirement; name any escalation stage entered through `sla-status-change`. If the response is local to this stage (`start-task`), say so and name the follow-up task that carries the rule — a task entry has no interrupting decision.} -**SLA Type:** {time-based | condition-based} -**SLA Title:** {non-empty stage-unique title, no `:`} - -| SLA | Unit | At-Risk | At-Risk Action | At-Risk Display Name | Breach Action | Breach Display Name | -|-----|------|---------|----------------|----------------------|---------------|---------------------| -| {count} | {min \| h \| d \| w \| m} | {percentage}% | {Notify: recipient or specific action} | {escalation title, stage-unique, no `:`} | {Notify: recipient or specific action} | {escalation title, stage-unique, no `:`} | - -##### Stage Variable SLA Rules - -> Include only for a condition-based Stage SLA. Each row is written before that stage's trailing `=js:true` default. - -| Expression | SLA | Unit | Display Name | -|------------|-----|------|--------------| -| {conditionExpression evaluated against case variables} | {count} | {min \| h \| d \| w \| m} | {non-empty stage-unique title without `:`} | - -#### Tasks - -> Tasks are listed in the order provided by the source spec / interview answers. Do not add, split, merge, or rename tasks; do not infer new tasks from context. - -| # | Task Name | Type | Activation Mode | Starts When | Required | Run Only Once | Persona | SLA | -|---|-----------|------|-----------------|-------------|----------|---------------|---------|-----| -| 1 | {task name} | {action \| process \| agent \| rpa \| api-workflow \| wait-for-timer \| wait-for-connector \| execute-connector-activity \| case-management} | {sequential \| parallel \| event-triggered \| adhoc \| fan-in \| conditional-gate} | {e.g. "sequential group: A → B → C", "stage enters", "after A+B", "connector event"} | {Yes \| No} | {Yes \| No} | {persona name or "—"} | {count unit or "—" (only for action tasks)} | - -> After the summary table, provide a detailed subsection for each task. -> Primary-stage task headings use `##### Task {N}.{M}: {Task Name}`. Secondary-stage task headings use `##### Task S{K}.{M}: {Task Name}` where `K` is the secondary-stage order. Do not use lettered prefixes such as `R.1`, `W.1`, `CC.1`, or `ESC.1`. - ---- - -##### Task {N}.{M}: {Task Name} - -**Type:** {exact task type from schema} -**Activation Mode:** {sequential | parallel | event-triggered | adhoc | fan-in | conditional-gate} -**Design Rationale:** {Why this task type fits the actor/work and why this activation mode fits. For a sequential task, name the stated order/dependency; for a parallel task, state why it is independent.} -**Description:** {What this task does and why it exists in the case plan} - -**Entry Condition:** - -> **Valid WHEN rule types for task entry (strict subset of Key Rule 3):** `current-stage-entered` (fires when the containing stage is entered; use for ungated event/condition-driven tasks, not for the first task in a sequential run), `selected-tasks-completed("TaskA", "TaskB")` (explicit sibling gate, fan-in, branch convergence, or non-immediate dependency), `wait-for-connector` (waits for a connector event), `adhoc` (user-triggered from the case app — task does not auto-start; task-entry only; set `Required: No`; does not determine task type), `runs-sequentially` (sequential ordering within the stage; parallel task sets remain allowed, and the entry rule—not lane placement—carries the sequencing intent), `sla-status-change("","")` for a breach / `sla-status-change("","","")` for at-risk (the **`start-task` SLA response** — this task fires on the SLA event itself; reference the containing stage's own SLA, or `root` for a case-scoped response). Other rule types from Key Rule 3 are NOT valid here. -> -> Each row is a separate entry condition. List multiple rows when a task can be entered through more than one path. Author a `current-stage-entered` row for any ungated task — including connector tasks (`execute-connector-activity`, `wait-for-connector`) — that should start when its stage is entered. -> -> **Sequential normalization:** when the requirement states order/dependency (`then`, `after`, `before`, `in order`, or an upstream prerequisite), write `runs-sequentially` as the only Entry Condition row on every task in that run, including the first task. Do not turn an explicitly ordered run into parallel stage-start tasks merely because no data binding is present. Use `current-stage-entered` in parallel only for explicitly independent work; use `selected-tasks-completed` for fan-in or a non-immediate dependency. - -| WHEN | IF | Display Name | -|------|-----|--------------| -| {one of: `current-stage-entered` \| `selected-tasks-completed("TaskA", "TaskB")` \| `wait-for-connector` \| `adhoc` \| `runs-sequentially` \| `sla-status-change("","")` \| `sla-status-change("","","")`} | {conditionExpression, or "—" if none} | {optional label, or "—" → defaults to `Entry Rule {N}`} | - -> If `WHEN` is `wait-for-connector`, add a **Connector Rule Detail** block under this table (see Key Rule 6). - -**Task envelope** - -> Render the heading above exactly, with no colon. Every task includes this block after the Entry Condition table. - -| Required | Run Only Once | Skip Condition | -|----------|---------------|----------------| -| {Yes \| No} | {Yes \| No} | {`=js:` expression that skips the task when truthy, or `—`} | - -> `Required: Yes` means the task counts toward the stage's `required-tasks-completed` exit — **at least one task per stage MUST be `Required: Yes`**, or the stage can never complete. `Run Only Once` is a re-entry decision, not a task-type default: use `No` for request/review/decision/validation tasks that must rerun after corrections or resubmission; use `Yes` only for immutable setup or a documented re-evaluate-existing-fact return. `Skip Condition` is the task-level `skipCondition` envelope field (sibling of `data`); use it for "run this task only when X" gating that is not expressible as a task-entry `IF`. - ---- - -###### Action Task Detail (type: `action`) - -> Use this block for every task of type `action`. The action plugin authors action tasks ONLY from a deployed Action App registered in `action-apps-index.json`; inline JSON-Schema HITL forms are not authored by the skill (an unresolved app falls back to a Rule-8 placeholder). - -**HITL Implementation:** Action App: {the concrete intended `deploymentTitle`. REQUIRED and NEVER ``: use the selected registry entry's canonical title when resolved; otherwise retain the user-requested title so Phase 1 can repeat discovery from this SDD alone.} -**Action App ID:** {`actionAppId` — concrete deployment id, or `` when no live app was selected} -**Deployment Folder:** {`deploymentFolder.fullyQualifiedName`, or `` when Action App ID is unresolved} -**actionType:** {the dispatch code the app's code-behind switches on — e.g., `GRNConfirmation`, `ApLeadApproval`. **A recognised code is REQUIRED; passing a human display name instead fails result mapping at runtime.** `—` only when the app is not a code-switched app.} -**Recipient:** {typed prefix only: `Role:` \| `User:` \| `UserGroup:` \| `Email:` \| `Expression:=vars.`} -**Priority:** {Low \| Medium \| High \| Critical} · **Task Title:** {one-line Action Center prompt} · **Labels:** {csv or `—`} - -> The Action App title carries portable intent; `Action App ID` carries resolution status. A concrete ID plus the exact folder locates the deployed app, while an unresolved ID plus the intended title lets Phase 1 repeat discovery without `tasks/registry-resolved.json`. `actionType` is the human-decision app's behaviour selector — treat it as a closed enum sourced from the app, not a free-text label. - -**Input Schema:** - -| Field | Type | Binding | Required | -|-------|------|---------|----------| -| {field name} | {String \| Number \| Boolean \| Date \| ...} | {case variable} | {Yes \| No} | - -**Output Schema:** - -| Field | Binding / Value | -|-------|------------------| -| {schema field name} | -> {case variable that receives this value} | -| — | {case variable} = {literal, =js:expression, or =js:vars.X.Y for dotted access} | - -> The `Field` column is the schema field name from the action's response (or `—` for `=` rows). The `Binding / Value` column uses `-> caseVar` for extraction or `caseVar = expression` for set / compute / copy. Target case variable MUST exist in Case Variables table. - -**Actions:** - -| Button | Maps To | Behavior | -|--------|---------|----------| -| {button label, e.g., "Approve"} | {variable = value, e.g., reviewDecision = "Approved"} | {Complete task \| Complete task and set variables \| ...} | - ---- - -###### Connector Task Detail (type: `wait-for-connector` or `execute-connector-activity`) - -> Use this block for connector-based tasks. Connection + Auth are **tenant-authoritative** and come from the Integration Service CLI cache, not from the user spec: -> - **Connection** ← `~/.uipath/cache/integrationservice/{connectorKey}/connections.json` — the `name` (and optional `id`) of the default or first enabled entry. -> - **Auth Method** ← `~/.uipath/cache/integrationservice/connectors.json` — the connector's `defaultAuthenticationType`. -> - **Operation** ← `~/.uipath/cache/integrationservice/{connectorKey}/activities.json` for the display/operation name; `~/.uip/case-resources/typecache-activities-index.json` (or `typecache-triggers-index.json` for events) for I/O schemas — each is a flat JSON array of activities, filter by connector + operation name. -> - **Account/Endpoint is not stored** in the compact cache. Render `—` unless the user spec supplies it explicitly. -> If a cache is unavailable or no enabled connection is found, render `—` rather than inventing values. - -**Connector:** {connector name from Integration Service, e.g., "Salesforce"} · **Connector Key:** {`connectorKey`, e.g. `salesforce`} -**Connection:** {connection instance `name` from `connections.json`, e.g., "Salesforce-Prod" — or "Tenant default" when `isDefault: true`} · **Connection ID:** {`connectionId` — concrete, or ``} -**Activity Type ID:** {`activityTypeId` from the typecache} · **Service Type:** {`serviceType`, e.g. `Intsvc.WaitForEvent`} -**Auth Method:** {`defaultAuthenticationType` from `connectors.json`, e.g., OAuth2 \| API Key \| Basic \| Service Account} -**Account / Endpoint:** {explicit endpoint if supplied — or "—" (not stored in the CLI cache)} -**Operation:** {`displayName` / `operation` from `activities.json`} -**Trigger / Event:** {trigger display name for `wait-for-connector`, or "—" for `execute-connector-activity`} - -> `Connection ID` + `Activity Type ID` are the concrete identities Phase 1 binds — without them the connector cannot resolve at build time; surface them here so the SDD is replicable standalone (missing either → `` + a high review item). - -**Inputs:** - -| Field | Type | Binding | -|-------|------|---------| -| {field name} | {type} | {`=vars.X`, `=metadata.X`, `=js:(...)`, or literal} | - -**Outputs:** - -| Field | Binding / Value | -|-------|------------------| -| {schema field name} | -> {case variable that receives this value} | -| — | {case variable} = {literal, =js:expression, or =js:vars.X.Y for dotted access} | - -> Target case variable MUST exist in Case Variables table. See Section 2 I/O bindings explainer for `->` vs `=` operator semantics. - ---- - -###### Timer Task Detail (type: `wait-for-timer`) - -> Use this block for timer-based wait tasks. - -**Timer:** {timeDuration \| timeDate \| timeCycle} -**Value:** {ISO 8601 expression, e.g., "PT24H" for 24 hours, "P3D" for 3 days, or a variable expression} - ---- - -###### Child Case Task Detail (type: `case-management`) - -> Use this block for tasks that spawn a child case. - -**Child Case:** {the concrete intended child-case resource `name`. REQUIRED and NEVER ``: use the selected registry entry's canonical name when resolved; otherwise retain the user-requested name so Phase 1 can repeat discovery from this SDD alone.} -**Folder Path:** {resolved `folders[0].fullyQualifiedName`, or `` when no live child case was selected} -**Resource Identity:** {resolved `entityKey`, or ``; this cell, not `Child Case`, determines whether registry resolution succeeded} -**Data Passed (parent -> child):** - -| Parent Variable | Child Variable | -|----------------|----------------| -| {parent case variable} | {child case variable} | - -**Wait for Completion:** {Yes \| No} - -**Data Returned (child -> parent):** - -| Child Variable | Parent Variable | -|----------------|----------------| -| {child case variable} | {parent case variable} | - ---- - -###### Process / Agent / RPA / API Workflow Task Detail - -> Use this block for `process`, `agent`, `rpa`, and `api-workflow` tasks. These tasks do NOT support SLA — SLA column in the task summary should be "—". - -**Resolved Resource:** {the concrete intended resource `name` — e.g. `AgedInvoiceMockIntegrationApi` (api-workflow), `InvoiceTriageAgent` (agent), `AgedInvoice_StatementReconciliation` (rpa). REQUIRED and NEVER ``: use the selected registry entry's canonical name when resolved; otherwise retain the user-requested name so Phase 1 can re-run discovery from this SDD alone.} -**Folder Path:** {resolved `folders[0].fullyQualifiedName` — the `folderPath`-binding default — or `` when no live resource was selected. A concrete value MUST be the resource's exact folder (never a parent path, or the job faults at runtime).} -**Resource Identity:** {REQUIRED resolution status: resolved id (+version) — `apiWorkflowId` / `agentId` / `processOrchestrationId` — or ``. This cell, not `Resolved Resource`, determines whether registry resolution succeeded. Also carried in `tasks/registry-resolved.json` when that optional cache exists.} -**Binding Sub-Type:** {`Api` (api-workflow) \| `Agent` (agent) \| `ProcessOrchestration` (process) \| `—` (rpa) — the `resourceSubType` on the name/folderPath bindings. Omitting it makes Studio Web report the resource as not found.} -**Dispatch / Operation:** {when the resource is a shared façade dispatched by a parameter, name the selector and value — e.g. `requestSource = "RegisterCaseShell"`. Render `—` for single-purpose resources. The selector itself is also an Inputs row (a literal binding).} - -> `Resolved Resource` carries portable intent; `Resource Identity` carries resolution status. A concrete identity plus the exact folder makes the selected deployment replicable, while an unresolved identity plus the intended name lets Phase 1 repeat discovery on another machine without `tasks/registry-resolved.json`. When one façade resource (e.g. a generic mock-integration API, or a code-switched action app) backs many tasks, the **Dispatch / Operation** value is what distinguishes their behaviour — capture it explicitly, not just as an opaque input. - -**Inputs:** - -| Field | Type | Binding | -|-------|------|---------| -| {input argument name} | {type} | {`=vars.X`, `=metadata.X`, `=js:(...)`, or literal} | - -**Outputs:** - -| Field | Binding / Value | -|-------|------------------| -| {output argument name} | -> {case variable that receives this value} | -| — | {case variable} = {literal, =js:expression, or =js:vars.X.Y for dotted access} | - -> Target case variable MUST exist in Case Variables table. See Section 2 I/O bindings explainer for `->` vs `=` operator semantics. - -> **I/O completeness (resolved resources).** Once this task binds a deployed resource, every **required** input the resource declares MUST appear as an Inputs row with a value (or `` + a high review item), and every `-> caseVar` output `Field` MUST be a field the resource actually emits. **An input fed by an upstream task's output is bound directly — `<- "Stage"."Task".out` (whole value) or `vars.$xref('Stage','Task','out')` (inside a `=js:` expression) — and is NOT declared as a Case Variable.** Declare a Case Variable only to rename, default, retype, or expose case-level state. - ---- - -## Section 3: Personas & App Views - -**Purpose:** Who interacts with the case and through what interfaces. Maps personas to stage scope and permissions, and defines Process App views. - -### Personas - -| Persona | Stage Scope | Permissions | Description | -|---------|-------------|-------------|-------------| -| {persona name} | {comma-separated stage names, or "All"} | {comma-separated permission list, e.g., "View, Act, Reassign"} | {description of this persona's role in the process} | - -### Process App Views - -> Define the views available in the Case App / Process App. Include case list and case detail views at minimum. - -| App | View | Persona | Purpose | Key Components | -|-----|------|---------|---------|----------------| -| {app name} | {view name, e.g., "Case List", "Case Detail", "Dashboard"} | {persona who uses this view} | {what this view enables} | {key UI components: columns, filters, sections, charts} | - ---- - -## Section 4: Integrations - -**Purpose:** The complete inventory of every intended or deployed resource and external system the case binds — **one subsection per resource family**, so the full integration/resource footprint is visible and replicable from the SDD alone. Render only the subsections whose task type appears in the case; for a family with no tasks, either omit the subsection or render the heading with `> None.`. Every runnable resource row always carries its concrete intended **name**; its **folder** and **resource id** are concrete when resolved and `` otherwise (mirrors the per-task `Resolved Resource` / `Folder Path` / `Resource Identity` cells in Section 2 — this section is the de-duplicated roll-up). - -### Integration Service Connectors - -> For `execute-connector-activity` and `wait-for-connector` tasks. `> None.` when the case has neither. - -| Connector | Connector Key | System | Connection (ID) | Auth Method | Operations Used | Used By Tasks | -|-----------|---------------|--------|-----------------|-------------|-----------------|---------------| -| {connector name} | {connectorKey} | {target system} | {connection name (connectionId)} | {OAuth2 \| API Key \| Basic \| Service Account \| ...} | {comma-separated operation names} | {comma-separated task names} | - -> For each connector, provide operation detail. If CLI registry data is available, include actual I/O fields from the registry. - -#### {Connector Name} - -**Operations:** - -| Operation | Activity Type ID | Method | Input Fields | Output Fields | -|-----------|------------------|--------|-------------|---------------| -| {operation name} | {activityTypeId} | {GET \| POST \| PUT \| DELETE \| PATCH \| EVENT} | {field: type, ...} | {field: type, ...} | - -### API Workflows - -> For `api-workflow` tasks. One row per **distinct** workflow (de-duplicate across tasks). - -| Workflow | Folder | Resource ID (+version) | Inputs → Outputs | Used By Tasks | -|----------|--------|------------------------|------------------|---------------| -| {workflow name} | {folders[0].fullyQualifiedName} | {apiWorkflowId (+version)} | {in fields → out fields} | {comma-separated task names} | - -> **Shared-façade note:** when one workflow backs multiple tasks via a dispatch parameter, list the distinct selector values in the `Used By Tasks` cell, e.g. `Start case (requestSource=StartAgedInvoiceCase), Register shell (requestSource=RegisterCaseShell)`. - -### Agents - -> First-class UiPath `agent` tasks (NOT externally-hosted agents — those go under **External Agents** below). One row per distinct agent. - -| Agent | Folder | Resource ID (+version) | Inputs → Outputs (or shared contract) | Used By Tasks | -|-------|--------|------------------------|----------------------------------------|---------------| -| {agent name} | {folders[0].fullyQualifiedName} | {agentId (+version)} | {in fields → out fields, or "shared agent contract"} | {comma-separated task names} | - -### Processes & RPA - -> For `process` and `rpa` tasks. One row per distinct resource. - -| Resource | Type | Folder | Resource ID (+version) | Used By Tasks | -|----------|------|--------|------------------------|---------------| -| {resource name} | {process \| rpa} | {folders[0].fullyQualifiedName} | {processOrchestrationId (+version)} | {comma-separated task names} | - -### Child Cases - -> For `case-management` tasks. Render only if the case launches a child case. - -| Child Case | Folder | Resource ID | Identifier Prefix | Wait for Completion | Used By Tasks | -|------------|--------|-------------|-------------------|---------------------|---------------| -| {child case name} | {folders[0].fullyQualifiedName, or ``} | {entityKey, or ``} | {2-4 char prefix} | {Yes \| No} | {comma-separated task names} | - -### External Agents - -> Externally-hosted AI agents (CrewAI, Salesforce Einstein, Databricks, LangChain, …), modeled as `api-workflow` / `execute-connector-activity` tasks (the skill has no first-class `external-agent` type). Include this table only if the case uses such an agent. - -| Agent | Service Type | Endpoint | Used By Tasks | -|-------|-------------|----------|---------------| -| {agent name} | {CrewAI \| Salesforce \| ServiceNow \| Custom \| ...} | {endpoint URL or reference} | {comma-separated task names} | diff --git a/skills/uipath-maestro-case/references/brownfield.md b/skills/uipath-maestro-case/references/brownfield.md index 27048da64f..77091ffa58 100644 --- a/skills/uipath-maestro-case/references/brownfield.md +++ b/skills/uipath-maestro-case/references/brownfield.md @@ -1,6 +1,6 @@ # Brownfield — Edit an Existing Case -Targeted changes to an existing `caseplan.json`. Skips the Phase 0–6 build pipeline. Terminates at `validate`, then hands off to Phase 5 (debug) / Phase 6 (publish). +Targeted changes to an existing `caseplan.json`. Skips the design delegation and the Phase 1–6 build pipeline. Terminates at `validate`, then hands off to Phase 5 (debug) / Phase 6 (publish). > **Greenfield (new case from `sdd.md`) uses a different journey.** If `caseplan.json` does not yet exist, or the user wants to (re)build from a spec, see [planning.md](planning.md) → [implementation.md](implementation.md) → [phased-execution.md](phased-execution.md) instead. diff --git a/skills/uipath-maestro-case/references/implementation.md b/skills/uipath-maestro-case/references/implementation.md index bd9d3edb4c..c1caaec958 100644 --- a/skills/uipath-maestro-case/references/implementation.md +++ b/skills/uipath-maestro-case/references/implementation.md @@ -14,6 +14,8 @@ Execute the `tasks.md` plan, building `caseplan.json` via direct JSON edits per Every plugin uses direct JSON writes via its `impl-json.md`. Cross-cutting mechanics (ID generation, Pre-flight Checklist, primitive ops, the canonical write contract) are in [case-editing-operations.md](case-editing-operations.md). +> **Read each `impl-json.md` once per plugin type, not per T-entry.** Group the section's T-entries by plugin, read that plugin's `impl-json.md` a single time, then execute every T-entry of that type from the one read (this is what the per-section batch write contract already assumes). Re-opening a plugin reference per T-entry is a read-budget defect — observed at up to 26 re-reads of one `impl-json.md` in a single build, each costing a full inference round-trip. After context compaction, re-read only the plugin for the section in progress. + **Per-section batched writes — mandatory.** Process `tasks.md` one **section** at a time (§4.2.1 vars, §4.3 triggers, §4.4 stages, §4.6 task-shapes, §9.7 connector schema, §9.8 I/O binding, §10 conditions, §11 SLA): 1. **One Read** of `caseplan.json` at section entry. diff --git a/skills/uipath-maestro-case/references/phase-0-interview.md b/skills/uipath-maestro-case/references/phase-0-interview.md deleted file mode 100644 index b3eb92fdbf..0000000000 --- a/skills/uipath-maestro-case/references/phase-0-interview.md +++ /dev/null @@ -1,271 +0,0 @@ -# Phase 0 — Interview Mode (case design) - -This file is a **thinking guide** for the agent: how to listen, assume, confirm once, and hand off fast when no `sdd.md` is provided. Phase 0 designs the case in the session's **in-memory model**; `sdd.md` is rendered from that model in parallel with the first build actions — a reference artifact, never a review gate. - -> **Authoritative for the interview path only.** Trigger detection, mode behavior, confirmation, resumption, output contract. **Content rules** (authority hierarchy, task-type override priority, render-required fields, variable lineage, review items, source ledger) live in [sdd-generation-rules.md](sdd-generation-rules.md). Phase 1 logic lives in [planning.md](planning.md). Phases 2–6 live in [phased-execution.md](phased-execution.md). - -## Goal - -Design the case as an in-memory model shaped by [`assets/templates/sdd-template.md`](../assets/templates/sdd-template.md), confirm it in ONE user prompt, then start the build. Phase 0 is **best-assumption by default**: it decides everything it can from the user's words and documents, and *informs* the user of every decision — it does not interrogate. `sdd.md` renders from the confirmed model concurrently with the first build actions. For later sessions and re-runs the file is the contract (Rule 2: trust as written); within this session, the in-memory model that produced it drives the build. - -**The Phase 0 confirmation IS the plan-first approval surface.** If workspace or project rules require "show a plan before editing," satisfy that requirement by showing the structured §Confirm case-design summary below. Do not insert a separate generic implementation plan, "Build Plan," or "Approve this plan" checkpoint before §Confirm. A user "Yes" to a generic implementation plan is not a Build answer and must not create files. - -Phase 0 writes: - -- `sdd.md` — rendered once from the confirmed model, batched with the first build actions (or written and reported when the request was design-only). -- `sdd-viewer.html` — optional, generated only on explicit request (§HTML preview). -- `sdd.draft.md` — ONLY when the user explicitly asks for a draft to review; normal runs never create it. If the request explicitly says to get/save the draft and stop, show the Case Review and write the draft in the same response instead of asking for another approval. `tasks/registry-resolved.json` is a Phase 1 artifact — Phase 0 does not write it. - -**Fast path — no-build design + plan.** If the opening request explicitly asks to produce `sdd.md` plus `tasks/tasks.md` and stop before `caseplan.json`, follow §Build start's **No-build design + plan request** path immediately after sketching the case. This path is self-contained: do not read `planning.md`, plugin planning references, tenant registry/cache files, or the full `sdd-generation-rules.md` checklist. Read this file plus `assets/templates/sdd-template.md` only as needed, compose a concise full-template SDD, write `sdd.md`, create `tasks/`, write the compact plan, and stop. Keep the artifacts bounded: one short rationale paragraph per stage/task/SLA/exception choice is enough; do not expand optional examples, source-ledger prose, registry audit detail, or build-phase validation notes. - -## When Phase 0 runs - -Strict binary trigger. Look for an `.md` file at the resolved path whose basename (case-insensitive) contains `sdd`. Examples that count: `sdd.md`, `loan-sdd.md`, `case_demo_sdd.md`, `./specs/onboarding-sdd.md`. Plain `.md` references without `sdd` in the name don't count. - -| State | Action | -|---|---| -| File present, basename = `sdd.md` | Skip Phase 0. Hand to Phase 1. | -| File present, basename ≠ `sdd.md` | Copy contents to `./sdd.md` (preserve original at its path). Skip Phase 0. Hand to Phase 1. | -| File absent, `sdd.draft.md` present | Resume (§Resumption). | -| File absent, no draft | Run Phase 0 from scratch (§Entry). | - -If the user prompt names no `.md` reference, default candidate is `./sdd.md` — proceed on that assumption and record it as a decision; do not ask. - -## Entry - -**If the user's request already describes the case** (any stages, work, trigger, domain, or attached docs), skip every entry prompt: print the roadmap from `SKILL.md § User-facing roadmap` and go straight to work — the request IS the first Listen input. **Only a bare request** ("create a case" with nothing else) gets the Listen opener after the roadmap. There is no entry menu; a user who has an `sdd.md` will say so, and abort is always a free-text away. If the same request also asks for `tasks.md`, do not read planning/plugin references yet; first show the Phase 0 Case Review and get the Build / Save approval. - -**No tenant work at Entry.** Nothing about the tenant is a prerequisite for designing the case — do not run login or `registry pull` up front. Grounding starts only when the case shows it needs it (§Tenant grounding). - -## Tenant grounding — requirement-driven, one light pass, no questions - -Phase 0 grounds resources lazily, in parallel with the design, with a **single name-match pass** at most. Schema discovery (`tasks describe`, `case spec`) belongs to the build phases — never run it in Phase 0. - -1. **Intake batch.** Read every supplied document in parallel. Extract named systems, resources, likely tasks, and roles. -2. **Requirement-driven kickoff.** For build runs only, the FIRST moment the sketch identifies tenant-bound work — a named system/resource/connector, or an inferred runnable/connector/action task — start the grounding chain as ONE background command, in the same batch as whatever is already running: `uip login status --output json && uip maestro case registry pull`. It resolves while sketching continues; a case with no tenant-bound items never pulls in Phase 0. Best-effort: never block on it, never surface its output unprompted; on failure, one plain-language line (§What to say while working), keep intended names, mark identities `resolve at build`, continue. If the harness cannot run background commands, run login → pull in the batch that composes the confirmation. **No-build runs skip grounding:** when the user explicitly asks to stop at a draft, final SDD, or implementation plan and not create `caseplan.json`, do not run login, registry, connection, schema, or user-discovery commands in Phase 0; preserve concrete intended names and mark identities `resolve at build`. -3. **Light match pass — join, never wait.** When composing the confirmation, check the chain. If the pull succeeded, run ONE cache lookup per named or inferred resource (`~/.uip/case-resources/-index.json`; `action-apps-index.json` for HITL apps; `typecache-activities-index.json` / `typecache-triggers-index.json` for connectors) — all lookups in one parallel batch. With ≥ 4 lookups, use parallel read-only workers where supported (one per item or type family; cache reads only — never writes, never prompts, never login/pull; parent spot-verifies adopted identities). Bucket each result: - - **Single confident match** (1 match across all folders, ≥ 1 shared name token) → adopt silently; shows as the task's resource in the confirmation with a decision line. - - **Anything else** (multiple matches, cross-folder same-name, no token overlap, zero matches, 0 or > 1 enabled connections for a connector) → mark `resolve at build`. Do NOT ask, do NOT auto-pick among candidates, do NOT fetch schemas. Phase 1's discovery and its Rule 17 gate handle the choice with full authority. - - If the pull has NOT finished when the confirmation is ready, do not wait: present with `resolve at build` on the tenant-bound items and let the build reconcile — the confirmation is never delayed by the tenant. - -**Guardrails:** registry data is evidence, not requirements — never add/rename business work to match tenant inventory; never dump catalogs; keep type-specific portable names concrete (`Resolved Resource`, Action App title, `Child Case`) even when identity defers; a connector with zero connections is `resolve at build`, not a reason to change the task type. A no-build run does not need tenant evidence to be useful; the later build run owns authoritative identity resolution. - -## Modes - -Three moves. **Listen** takes in everything offered; **Sketch** builds the complete case model by best assumption, recording every decision; **Confirm** shows the whole case once with the decisions taken and asks a single question — on a Build answer, the build starts and `sdd.md` is written alongside it (§Build start). Listen and Sketch loop freely as new context lands; there is no separate Resolve or Approve pass. - -### Listen - -The opening move for a bare request. One message, one prompt: - -> Tell me about the case you want to build. What kicks it off, what stages does it move through, and how does it close out? Drop in any docs you have — paths, paste, or attach. - -What the agent does as input arrives: - -- **Reads everything mentioned.** Path, dragged file, named doc → read immediately, in parallel when multiple. "Everything in `~/process-docs/`" → `ls` + parallel Reads. -- **Narrates content, not filenames.** One short line per doc about *what's in it*: `vendor-onboarding.md — 4 stages (Intake → Compliance → Finance → Activation), 2 personas, 8-hour SLA on Compliance.` -- **Partial reads for huge docs.** Past ~2000 lines, read the first chunk, narrate the signal, decide if more is needed. Unreadable formats (`.docx`, `.pptx`, scanned PDFs) → one paste request; PDFs ≤ 10 pages read directly. -- **Mid-flow docs are first-class.** New doc after the sketch exists → re-read, update the model, narrate the delta. -- **Named systems seed grounding.** Deployed resources, apps, connectors, systems named by the user feed the §Tenant grounding light pass. - -Listen asks nothing beyond the opener. Gaps are filled by assumption in Sketch, not by questions. - -#### Domain-vocabulary capture (during Listen) - -Capture verbatim into the model: **roles** (exact casing — `CFO`, `Triage Nurse`), **domain nouns** (`Vendor` vs `Supplier` — never homogenize), **stage labels**, **decision outcomes** (`Approve` / `Decline` / `Needs Info`, not synonyms), **integration shortnames** (`Workday`, never "the HR system"). Provenance `verbatim:""` per [sdd-generation-rules.md § Source ledger](sdd-generation-rules.md#source-ledger-provenance). Synonym drift is a fidelity defect ([§ Domain fidelity](sdd-generation-rules.md#domain-fidelity)). - -#### File / attachment / document detection (during Listen) - -When the user mentions `file`, `attachment`, `PDF`, `upload`, `evidence`, `receipt` (as artifact, not domain noun), pick the best-matching pattern from the indicators and record the decision — ask only if the user's own words point at two patterns at once: - -| Pattern | Indicator phrases | SDD shape | -|---|---|---| -| Caller pre-uploads at case start | "caller submits a PDF", "uploaded with the request" | `Category: In`, `Type: file` — Use Case 9; caller obligation surfaces in the confirmation. | -| Connector downloads mid-case | "fetch the attachment from email", "pull from Drive / S3" | `Category: Variable`, `Type: file` from a task Outputs `->` row — Use Case 10. | -| Stores URL/metadata, not bytes | "we just store the link", "we keep the document ID" | `Type: string` (URL) or `Type: jsonSchema` (metadata). NOT `file`. | - -### Sketch — best assumption, every field - -Fill the complete SDD shape against [`sdd-template.md`](../assets/templates/sdd-template.md) from what Listen captured, deciding every open field by best assumption. Authority order per [sdd-generation-rules.md § Content authority hierarchy](sdd-generation-rules.md#content-authority-hierarchy) — platform schema and compliance constraints override user phrasing (apply the override silently; it becomes a decision line). Every non-verbatim value gets a source-ledger entry AND a line in the confirmation's `Decisions` block. Every stage, task, and configured SLA also gets a durable `Design Rationale` in the model explaining the kind/type, activation/sequencing, and routing/threshold choice; the confirmation summarizes it but does not replace it. The model lives in memory — **no draft file, no checkpoint writes**; `sdd.md` is written later at build start. - -**Assumption playbook** (former ask-list, now decided and disclosed): - -| Field | Best assumption | -|---|---| -| Trigger type | External system / portal / form / inbound event / record-created mentioned → **Connector Event** with that source (unprovisioned tenant object stays an event trigger — never downgrade to Manual); schedule/recurring → **Timer**; otherwise → **Manual**. | -| Task type on ambiguous verbs (`review`, `approve`, `validate`, `decide`, …) | Named human role or judgment implied → `action`; framed as automated/AI → `agent`; truly even → `action` (keeps a human in the loop; the user can flip it in one correction). Compliance trigger phrase (HIPAA, ECOA, FINRA, "licensed X", …) → `action`, always ([§ Task-type override priority](sdd-generation-rules.md#task-type-override-priority)). | -| "Manual" in-case work | Starts a new case → Manual trigger; optional worker-launched task → `adhoc` + `Required: No`; worker-chosen exception/rework lane → secondary stage with `user-selected-stage`. Pick by context; disclose. | -| Case exit | Last primary stage completes (`required-stages-completed`, `Marks Case Complete: Yes`) unless the user described another close-out; alternate outcomes → non-completing case-exit rules. | -| Stage exit ↔ Marks Complete pairing | Derive mechanically per sdd-template Key Rule 4 — never author an illegal pair. | -| SLA | Only when the user mentioned timing; take their words literally ("about a day" → 1 day). No timing mentioned → `—`. For every SLA, decide scope, status, and response separately (§ SLA response model). No stated response → `notify-only` for both statuses; never invent a stage or task for a notification. | -| Case name / prefix | PascalCase from the domain noun; prefix = 2–4 letter mechanical derivation. | -| Personas | Named roles verbatim; none mentioned → single `Process Owner`. | -| Optional fields untouched by the user | `—`. Never a question. | -| Resources / connections | §Tenant grounding light pass: single confident match adopted, everything else `resolve at build`. | - -**Structure rules while sketching:** §1.5 declare-vs-xref — mint a §1.5 row ONLY for `In`/`Out` args, trigger-payload Variables, and state read by a condition or ≥ 2 consumers; a single upstream output feeding one consumer is referenced directly (`<- "Stage"."Task".out` / `vars.$xref(...)`), never relayed. Required fields (case name, prefix, ≥1 trigger, ≥1 stage, ≥1 task per stage with type, ≥1 case exit) must all be settled — by user input or by playbook assumption. - -**Other-path sweep — mandatory before confirmation.** Do not design only the primary flow and wait for the user to ask about alternatives later. Check the source for: rework / needs-info loops; rejection, withdrawal, and cancellation; SLA escalation; external-system failure; manual override or worker-selected side work; optional side work; and terminal outcomes that differ from successful completion. For each scenario, choose the correct model: interrupting secondary stage, terminal case-exit, non-completing case-exit, task-level branch, `adhoc` task, SLA notification only, or "not modeled" when the source explicitly rules it out. If the source names or strongly implies a scenario, model it by best assumption and disclose it in **Other Paths Considered**. If the source has no signal at all, spend the one clarifying call on a single bounded question before confirmation: "I don't see any other paths beyond the primary flow. Should I add standard paths for rework, cancellation/withdrawal, SLA escalation, or keep only the primary flow?" - -**Buildability musts** — settle all nine by assumption and surface each in the confirmation; they are where designs silently become unbuildable: (1) other-path trigger source (gate decision → `selected-stage-completed/-exited` + IF; person → `user-selected-stage`; external/global event → one `wait-for-connector` entry on the secondary stage; SLA at-risk/breach that requires case work → one `sla-status-change` entry whose target and SLA title — plus an at-risk escalation title for an at-risk row only — are declared in the SDD, while warning-only escalation stays a notification; interrupting flags on stage + entry rows; terminal `exit-only` vs `return-to-origin`; never duplicate global-event exits/tasks across primary stages); (2) every decision outcome routes somewhere — no dead-end status values, and an outcome that targets a lane keys that lane's entry; (3) every configure/decide task's output lands in a variable or direct reference; (4) every send/connector/agent's required inputs map to variables/literals/upstream outputs as far as knowable without schemas — the rest resolves at build; (5) conditional roles/steps become guarded rules + personas, not prose; (6) a critical-path connector failure gets a modeled other path when the user described failure handling — otherwise note it as an architect advisory; (7) manual-surface classification per the playbook; (8) intended resource names concrete, identities per the light pass; (9) every stage/task/SLA has durable rationale in the model, including why an ordered run is sequential or independent work is parallel. - -**The one clarifying call (rare).** Ask before the confirmation ONLY when: (a) no case is inferable at all (empty or contentless request), (b) the user's own inputs contradict each other on a shape-changing field, (c) the user asked to be asked, or (d) the mandatory other-path sweep found no source signal at all. Batch everything into ONE AskUserQuestion call (≤ 4 questions). An unclear answer → take the best assumption, disclose it, move on — never re-press. Everything else: assume and inform. - -**Red flags — you're about to over-ask.** "I should confirm the trigger type" / "review could be action or agent, better ask" / "the SLA wording is vague" / "this resource has two matches" — STOP: the playbook decides all of these; the decision line in the confirmation is the user's chance to correct. The bar for a question is *contradiction or emptiness*, not uncertainty. Equally, there is NO size gate, no "approval before creating files", no lightweight mode — the only stops in Phase 0 are the one clarifying call (when earned), the confirmation itself, and the explicit-sign-off path. - -### Confirm — the single checkpoint - -One structured **Case Review**, one question. Run the [sdd-generation-rules.md § Finalization](sdd-generation-rules.md#finalization) checks against the in-memory model FIRST — fix failures silently (they are the agent's defects, not the user's decisions); anything unfixable becomes a flagged line. This is the user approval surface and must be complete enough to review without opening `sdd.md`. It is not a generic build plan and not the full SDD prose: it mirrors the SDD sections in scan-friendly tables and grouped bullets. - -**Coverage map:** SDD Section 1 (case definition) → Case snapshot + Data contract + Rules / tiers; SDD Section 2 (stages/tasks) → Stages list + Stage/task detail cards + Other Paths Considered; SDD Section 3 (personas/views) → Case snapshot + stage/task cards; SDD Section 4 (integrations) → Resources & integrations. Anything with a High review item in the SDD model also appears in Review flags. - -Use this exact section order: - -1. **Case snapshot** — table `Item | Review value`. Include case name/prefix, objective, trigger(s), primary personas, completion/terminal outcomes, SLA summary, and build-review preference if already implied. If a value was assumed, mark it with `(assumed)`. -2. **Data contract** — table `Kind | Name | Type | Source | Used for`. Include every user-facing `In` and `Out` argument, every trigger-payload variable, and every state variable that drives routing, SLAs, task inputs, or downstream outputs. Group only purely task-local one-consumer values as `task-local outputs`; do not omit case-level data by saying it appears in `sdd.md`. -3. **Stages list** — table `Kind | # | Stage | Why it exists | Tasks to review | Entry / trigger | Completes / exits | SLA`. Include every primary and secondary stage so the user can see the main path and exception lanes in one scan. List primary stages first in flow order (`Kind: primary`, numbered), then secondary stages (`Kind: secondary`, `# = —`). For secondary rows, `Entry / trigger` names the interrupting signal or decision route, and `Completes / exits` says `return-to-origin`, `exit-only`, or case-close behavior. The `Tasks to review` cell lists every task in that stage as `mode: Task Name (type, persona/resource, required/optional)`, preserving sequence and fan-in: `sequential: Verify identity → Set supplier record`; `parallel: Risk review + Tax validation`; `fan-in: Onboarding decision after both`. -4. **Stage/task detail cards** — grouped bullets, one review card per stage. Each card shows: stage kind and why it is primary or secondary, entry trigger/condition, task type choices with classification rationale, activation rationale, key inputs/outputs, and any resource identity (`resolved`, concrete intended name, or `resolve at build`). For every task, name why its type fits the work (`action`, `agent`, `process`, `api-workflow`, etc.) and why its activation mode fits the timing (`sequential`, `parallel`, `event-driven`, `adhoc`, `fan-in`, `conditional-gate`). Keep it scannable, but every stage must have a card and every task must be named at least once across Stages list or the card. -5. **Other Paths Considered** — table `Scenario | Trigger / condition | Modeled as | Return / close behavior | Review note`. Include modeled exception/secondary paths and any intentionally unmodeled standard path when the user explicitly chose primary-flow-only. User-facing heading is exactly **Other Paths Considered**; do not use any alternate heading. -6. **Rules / tiers** — table `Rule | Where it applies | Data used | Outcome`. Include every conditional gate, amount/risk tier, SLA escalation rule, withdrawal/cancellation rule, rejection/needs-info route, and terminal outcome rule. -7. **Resources & integrations** — table `Family | Intended resource/system | Used by | Resolution`. Include action apps, agents, RPA/processes, API workflows, case-management children, connectors, and named external systems. `resolve at build` is acceptable; a missing row is not. -8. **Decisions I made** — grouped bullets for every assumption, override, resource decision, task-type decision, activation/sequence decision, and intentionally omitted path. Use plain-language source notes (`you said "then"`; `compliance wording`; `no SLA mentioned`). Flagged items (unfixable Finalization findings, missing connections) appear here with a ⚠ marker. -9. **Review flags** — explicit `None` when empty; otherwise list the exact items the user should inspect before approving. -10. **Caller obligation** — mandatory fixed text when any §1.5 row is `Category: In` + `Type: file` (JobAttachment pre-create contract; Studio Web's "Start case" dialog handles it automatically). Omit otherwise. - -**Activation mode vocabulary.** Use these user-visible labels consistently in the review: `sequential`, `parallel`, `event-driven`, `adhoc`, `fan-in`, `conditional-gate`. Use `event-driven` in chat even when the SDD field is `event-triggered`. - -**Completeness gate.** The confirmation is incomplete unless it contains Case snapshot, Data contract, Stages list, Stage/task detail cards, Other Paths Considered, Rules / tiers, Resources & integrations, Decisions I made, Review flags, and Caller obligation when relevant. Do not ask `Build it...`, `Save...`, or any approval question until every section has been shown, even when a section says `None` or `Not used`. Do not replace this confirmation with a generic list of build steps, artifact names, output folder, validation commands, resource-placeholder caveats, or a summary that points to `sdd.md` for the missing detail. - -Confirmation question (AskUserQuestion): `Build it — straight through` / `Build it — pause at the build preview` / `Change something`. The build choice records the Rule 11 preference — never re-asked mid-build. When ⚠ flagged items exist, relabel the first option `Build despite N flagged items — straight through`. For a **design-only** request swap the build options for `Save the design`; for a **draft** request, `Save as draft`. If the user's initial prompt already says to get/save a draft and stop, treat that as the `Save as draft` answer after the Case Review: write `sdd.draft.md` immediately and stop. The draft still uses SDD section/stage/task headings so a reviewer can inspect it directly. - -Corrections (`Change something` or any free text) update the model, re-run affected Finalization checks, and re-show ONLY the changed Case Review sections or rows: changed stage/task cards, data rows, rules, resources, other paths, review flags, and decision lines. A correction never restarts the walk. After showing the changed sections, include a short `Suggested next steps` line before the next confirmation prompt, e.g. `Suggested next steps: approve the updated design, choose preview pause if you want a visual checkpoint, or change another part of the case.` - -**Explicit sign-off requests** ("only after I approve", "I'll review before you build") suppress nothing about the flow but add one explicit approval prompt after the confirmation is accepted and before any file is created — honor it exactly. - -### Template conformance gate — before `sdd.md` is written - -The exact rendered text for `sdd.md` must pass this gate before Write. This is a render check, not a second design review: run it against the in-memory text you are about to write; if the harness makes that impossible, do one shallow post-write structural Read before Phase 1. Do not use the read to redesign the case. - -Required shape: - -- First heading: `# SDD — {Case Name}`. -- `## Table of Contents`. -- Exact section headings: `## Section 1: Case Definition`, `## Section 2: Stages & Tasks`, `## Section 3: Personas & App Views`, `## Section 4: Integrations`. -- Section 1 contains `### Case Metadata`, `### Case Triggers`, `### Case Exit Conditions`, and `### Case Variables`. -- Every modeled primary stage has `### Stage {N}: {Stage Name}`; every modeled secondary stage has `### Secondary Stage: {Stage Name}`. -- Every stage block contains `**Type:**`, `**Design Rationale:**`, `#### Stage Entry Conditions`, `#### Stage Exit Conditions`, and `#### Tasks`. -- Every modeled primary-stage task has `##### Task {N}.{M}: {Task Name}`; every modeled secondary-stage task has numeric secondary numbering `##### Task S{K}.{M}: {Task Name}` where `K` is the secondary-stage order. Do not preserve letter prefixes such as `R.1`, `W.1`, `CC.1`, or `ESC.1`. Each task block contains `**Type:**`, `**Activation Mode:**`, `**Design Rationale:**`, `**Entry Condition:**`, exact marker `**Task envelope**` (no colon), and the matching type-specific detail block. -- Section 3 contains `### Personas` and `### Process App Views`. -- Section 4 contains the integration/resource family headings needed by the modeled task types, or an explicit `> None.` for empty families. - -Forbidden summary-only replacement sections at top level: `## Source`, `## Case Objective`, `## Actors And Systems`, `## Case Trigger`, `## Stages`, `## Business Rules`, `## Task Plan`, `## Resource Resolution`, `## Acceptance Scenarios`. Their presence as the main document structure means the SDD is a summary, not a template render. Also forbid source/build-mode/path narration such as `Source: /...`, `Build mode`, `output folder`, validation-command checklists, or "generated from requirements file" prose in the SDD body. - -If the gate fails, rewrite from the model and template before Phase 1. Do not proceed to planning on a summary SDD, even if a later `caseplan.json` would validate. - -### Build start — SDD written alongside the build - -On a Build answer: - -1. **Transition line** (§What to say while working): `Starting the build — the design doc will be saved alongside as a reference. Say stop anytime.` -2. **Render gate first:** compose the full SDD text from `assets/templates/sdd-template.md` and pass §Template conformance gate. This is the only allowed pre-write SDD check. -3. **One parallel batch:** Write `sdd.md` (full render from the confirmed in-memory model — direct Write, no draft, no rename) + `uip solution init ` (derived exactly as Phase 2 Step 6.0 does; its idempotent skip then applies) + Phase 1's Rule 3 `uip login status` → `registry pull` chain **only if Phase 0's pull did not already succeed this session** — a same-session successful pull is reused, never repeated (SKILL.md Rule 3 fast path). The SDD write is NEVER a standalone blocking turn — it always shares the batch with build actions. -4. **One artifact line** after the write lands: `Design doc saved to ./sdd.md — reference it anytime.` -5. Proceed into [planning.md](planning.md) Step 1 **from the in-memory model** — do not re-read the just-written `sdd.md` in this session except for the shallow template-conformance check described above. Re-read it only when working memory may be stale (context compaction, resumed session); then the file is authoritative (Rule 2). For later sessions and re-runs, `sdd.md` is the contract exactly as if the user wrote it. -6. If `sdd.md` appeared at the path since Phase 0 started, abort instead of overwriting. - -**Design-only request:** write `sdd.md`, report the path in one line, stop before Phase 1. **Draft request:** write `sdd.draft.md`, report, stop — never promote. **Free-text corrections stay first-class after the build starts:** treat one as a targeted edit to the affected artifact (model + `sdd.md` + downstream), narrate it in one line, continue. - -**No-build design + plan request:** when the prompt explicitly asks for `sdd.md` plus `tasks/tasks.md` and says to stop before creating `caseplan.json`, do not enter full Phase 1 and do not read `planning.md` or plugin planning references. If the same prompt already says to produce those artifacts and stop, treat it as the save instruction: show the Case Review, then write the full `sdd.md`, create `tasks/`, write compact `tasks/tasks.md`, and stop in the same response without asking for another approval. If the user only asked to review the plan first, wait for approval before writing. The compact plan is a review handoff for a later build run, so it omits registry-derived files and tenant evidence. - -For this no-build path, prefer progress over exhaustive internal auditing: once the case model covers the stated stages, tasks, global interrupts, SLAs, variables, resources, and rationales, write the artifacts. Do not run the full Finalization checklist, do not inspect schema/planning references, and do not spend a separate turn refining optional SDD prose. The artifact contract below plus the template conformance shape are the gate. - -Compact `tasks/tasks.md` contract for this no-build path: - -- Use T-numbered entries for the case root, triggers, variables/arguments, stages, tasks, entry/exit/condition rules, and SLA/escalation rules that matter to the design. -- Use machine-scannable task headings in the plan: `## T{N}: task "{Task Name}"`. Do not hide task T-entries under dotted subheadings such as `### T12.1`; nested prose is allowed under the H2, but the task entry itself uses a plain integer T-number and quotes the task name. -- Stage entries include `stage-kind`, `entry-rule`, `exit-rule`, `interrupting`, `required`, `sla`, and `rationale`. -- Task entries include `stage`, `type`, `activation-mode`, `entry-rule`, `lane`, `required`, `run-only-once`, `resource-intent`, `identity: resolve at build`, and `rationale`. -- Sequential runs use consecutive single-task lane numbers; every task in the run has `activation-mode: sequential` and `entry-rule: runs-sequentially`. -- Global event/exception entries name exactly one interrupting secondary stage and the rule type (`wait-for-connector` or `sla-status-change`); do not duplicate those events across every primary stage. A `sla-status-change` entry names target + SLA title, plus an at-risk escalation title only for an at-risk row (a breach names the SLA alone) — all declared in the SDD. -- Do not add `taskTypeId`, `activityTypeId`, `connectionId`, resolved schemas, `inputs`, `outputs`, `registry-resolved.json`, or `recipients-resolved.json`. -- End the response with suggested next steps: review the SDD/plan, then run a later build to resolve tenant resources and create `caseplan.json`. - -## HTML preview - -Optional, **on-request only** — never offered proactively. Available any time after the confirmation exists, including mid-build. Self-contained local HTML: Case Definition, collapsible Stages & Tasks with detail panels, Personas & App Views, Integrations; persona/type filters, unresolved-only and schema-view toggles, search, print stylesheet. - -Generation: Read [`assets/templates/sdd-viewer.html`](../assets/templates/sdd-viewer.html), replace the `__SDD_DATA__` token in its `