# Dashboard Capability

Build, edit, or deploy UiPath dashboards powered by Insights RTM and the TypeScript SDK.

---

## Step 0 — Detect intent BEFORE loading anything

Read the user's message and classify it as one of three intents. **Do not load any files yet.**

| User says | Intent | What to do next |
|-----------|--------|-----------------|
| "build me a dashboard", "show me X metrics", "create a dashboard for…" | **BUILD** | Follow the Build path below |
| "add/remove/change a widget", "update the chart", "make it 7 days" | **EDIT** | Follow the Edit path below |
| "deploy this", "publish it", "make it live", "ship it to the team", "deploy the dashboard" | **DEPLOY** | Follow the Deploy path below |

If the intent is unclear, ask one question — "What do you want to do with the dashboard?" — as a **structured choice** (SKILL.md Critical Rule 18: native question tool with selectable options when the host agent has one, else a numbered list):

| Option | Description |
|--------|-------------|
| **Build a new dashboard** | Describe metrics in plain language, get a live dashboard |
| **Edit the existing one** | Add/remove/change widgets or time ranges |
| **Deploy it** | Publish to Automation Cloud |

---

## Path A — BUILD (new dashboard)

## Turn 2 output — Show the plan (zero tool calls, zero intermediate output)

After the blocking file reads + state check complete (login status and pre-warm run in the background — don't wait on them), output the plan as the first and only text.

**The user should see nothing between their request and the plan.** No "Reading files…", no "Checking login…", no "Starting pre-warm…". Pure silence then the plan.

If you need to show something, show only the plan.

### Turn 2 — Everything in ONE parallel message

Fire all of these simultaneously. Use multiple tool calls in one response — do not wait for one before starting another.

> **Path note:** All file paths are relative to `SKILL_BASE_DIR` — the directory where `SKILL.md` lives. Not relative to this file's location.

**File reads (parallel) — fire all in one message:**

| File | Purpose |
|------|---------|
| `references/dashboards/plugins/build/impl.md` *(from skill root)* | Build instructions, plan format, intent.json schema |
| `references/dashboards/primitives/tier-resolution.md` *(from skill root)* | Metric classification and SDK validation rules |
| `references/dashboards/aesthetic/layout-patterns.md` *(from skill root)* | Layout rules |
| `references/dashboards/aesthetic/charting.md` *(from skill root)* | Chart-type selection, colour tokens, delta polarity |
| `assets/scripts/dashboards/capability-registry.json` *(from skill root)* | Metric catalog (T1/T2 display hints) |
| `references/sdk/agents.md` *(from skill root)* | Agents + Agent Memory (Insights RTM) — validate agent/memory metrics |
| `references/sdk/orchestrator.md` *(from skill root)* | Jobs/Queues/Processes methods — validate job/process metrics |

**Conditional reads (add to the same parallel message if the request mentions these):**

| If user mentions | Also read |
|-----------------|-----------|
| tasks, action items | `references/sdk/action-center.md` *(from skill root)* |
| cases, process instances, Maestro, SLA, top/slowest/failing processes or cases, element stats | `references/sdk/maestro.md` *(from skill root)* |
| traces, spans, trace-level errors/latency/units | `references/sdk/traces.md` *(from skill root)* |
| governance, policy, compliance, denials, blocked actions, allow/deny, enforcement | `references/sdk/governance.md` *(from skill root)* — Insights-API governance (`policy-denials`, `governance-verdicts`) |
| **EXPLICIT runtime compliance / a standard or pack / ISO clause / "rule(s) violated"** (agent runs checked against standards) | `references/sdk/governance-traces.md` *(from skill root)* — gated, org-admin (`AgentTraces` governance decisions). Generic "governance/policy" stays on the row above |

**1 blocking command (instant, local — routes build vs edit, so the plan needs it):**

```bash
node -e "
const fs = require('fs')
fs.existsSync('.dashboard/state.json') ? process.exit(0) : process.exit(1)
" && echo INCREMENTAL || echo FRESH
```

**Login status — `run_in_background: true` (do NOT block the plan on it):** `uip login status` is only needed when building starts (the project's cloudUrl/org/apiUrl and to create the OAuth client) — never to present the plan. Fire it in the background alongside pre-warm; read its result in Phase 1 when you build.

```bash
uip login status --output json
```

**Pre-warm (same message — `run_in_background: true` on the Bash tool call):**

Derive the routing name from the user's request now (e.g. `"agent health dashboard"` → `"agent-health-x7k2"`). The project lands at `<cwd>/<ROUTING_NAME>`. Pre-warm = **extract the starter kit there, then install deps** — both in the background. Extraction uses the OS `tar` (built into Windows 10+, macOS, Linux — identical on every platform, no hand-rolled code), feeding the archive on **stdin** (`-f -`) so GNU tar doesn't misread the `C:\…` drive colon as a remote host (see `plugins/build/impl.md § The starter-kit archive`). One background call (chain with `&&`):

```bash
mkdir -p "<ROUTING_NAME>" && tar --no-same-owner --no-same-permissions -xz -C "<ROUTING_NAME>" -f - < "<SKILL_BASE_DIR>/assets/fixtures/governance-dashboard-starter-kit.tar.gz" && node "<SKILL_BASE_DIR>/assets/scripts/dashboards/build-dashboard.mjs" --prewarm "<ROUTING_NAME>"
```

The extract is fast; `--prewarm` then runs `npm ci` (the slow part) so it overlaps plan approval. ⚠️ `run_in_background: true` is a tool call parameter, not a shell flag. Without it, the call blocks before the plan appears.

**If that command exits non-zero — repair `<ROUTING_NAME>` in place. Never scaffold into a second folder.**

A partial extract (`Cannot mkdir`, `Cannot open: File exists`, `Permission denied`) leaves a half-populated project. Re-run the exact same command once — `tar` overwrites and the scaffold is idempotent, so a transient failure clears. If it fails again, delete and retry once:

```bash
rm -rf "<ROUTING_NAME>" && mkdir -p "<ROUTING_NAME>" && tar --no-same-owner --no-same-permissions -xz -C "<ROUTING_NAME>" -f - < "<SKILL_BASE_DIR>/assets/fixtures/governance-dashboard-starter-kit.tar.gz" && node "<SKILL_BASE_DIR>/assets/scripts/dashboards/build-dashboard.mjs" --prewarm "<ROUTING_NAME>"
```

If `rm -rf` itself is denied, the sandbox — not the kit — is at fault: **stop and report it.** Do NOT pick a new `<ROUTING_NAME>` to route around the error. An abandoned scaffold sitting beside the real one is indistinguishable from the real one to anything that later has to locate the project, and every downstream step then has a coin flip in it.

> **What the user should see:** Only the plan text. Nothing else — not file reads, not login output, not pre-warm status, not bash results, and no question popup. If there is ANY output before the plan, or any tool call in the plan response, that is a bug.

**After all reads:** output the plan as **pure text** and stop — zero tool calls in the plan response. The user replies with feedback or confirmation; setup questions (OAuth client ID, via the structured-choice tool) come only AFTER the plan is approved, and only for details the confirmation didn't already provide. See `plugins/build/impl.md` Phases 2–3.

**Routing:**
- `INCREMENTAL` → read `primitives/incremental-editor.md`, then follow it
- `FRESH` → follow `plugins/build/impl.md`

---

## Path B — EDIT (change existing dashboard)

**Check `regime` in `.dashboard/state.json` first.** If `regime` is `"ejected"` (or the project is a template — full source, no compiler state), do NOT use the edit-script: edit the `src/` files directly per the request, then `npm run build`. The structured ops below apply only to `compiler-managed` (or absent/legacy) dashboards. See `primitives/customization.md` (Regimes).

For a compiler-managed dashboard, read `primitives/incremental-editor.md` in the same message as `uip login status --output json`. Follow it.

**Also read `primitives/customization.md` first** when the user asks for look-and-feel changes (theme, layout, styling, "make it look…") or the project shows hand edits — it defines what the build script overwrites, when to **eject** (one-way switch to full-source editing), and when to edit the project directly instead of running the script.

---

## Path C — DEPLOY

### Step 1 — Read the deploy plugin FIRST (before any CLI commands)

```
Read: references/dashboards/plugins/deploy/impl.md  *(from skill root)*
```

Read this file in parallel with:

```bash
uip login status --output json
```

**Do not run any other commands until you have read the deploy plugin and presented the plan to the user.**

### Step 2 — Present the deploy plan (pure text, zero CLI calls)

Read `.dashboard/state.json` in memory to get the app name, version, and routing name. First determine the deployment target — **governance/admin dashboard** vs **standard dashboard app** — per `plugins/deploy/impl.md` Step 0. The folder line and the pin question depend on it.

```
Your **[Dashboard Name]** is ready to be deployed.

📦  Version:    [current] → [bumped]
🔗  URL path:   [routing-name]
📁  Folder:     [AdminDashboards (governance) | user-chosen folder (standard)]
🔄  Type:       Fresh deploy  OR  Updating existing deployment

📌  (governance only) Do you want to pin this dashboard to the Governance UI?
   → "deploy and pin" — visible in the Governance section
   → "deploy" — deploy without pinning
```

A standard dashboard deploys to a user-chosen folder with no pin question — see impl.md Step 4.

> ⚠️ Pinning surfaces the dashboard in the Governance section, which is an **Agentic Governance preview** feature — it only takes effect if the org is enrolled in the preview. When offering the pin, say so; either way the dashboard deploys and is reachable at its URL. See `plugins/deploy/impl.md` Step 4 / Step 10.

**HALT. Do not run any CLI command until the user confirms.**

### Step 3 — Follow plugins/deploy/impl.md

After user confirms, follow every step in `plugins/deploy/impl.md` exactly as written. Do not invent steps, do not run `uip tools list`, do not run `npm run build` before the plan is confirmed.

---

## Scope

This skill only handles dashboard building, editing, and deploying. For anything else, respond:

> "This skill is for UiPath dashboard generation only. For [what they asked], please use the appropriate skill."

---

## Hard stops

- **Never** show raw tool call outputs to the user — read results in context, surface only meaningful information
- **Never** echo raw event names (WIDGET_READY, TSC_PASS, BUILD_RESULT, etc.) — translate them to clean progress lines
- **Never** show intermediate bash command outputs between the user's request and the plan — the plan is the first visible output
- **Never** call any tool — including the question/option tool — in the same response as the plan. The plan is pure text; the user replies to it; structured setup questions (OAuth, deploy pin) fire only after approval and only for details the user hasn't already given
- **Never** run ANY CLI command before presenting the plan and getting user confirmation
- **Never** improvise deploy steps — always read `plugins/deploy/impl.md` first
- **Never** run `uip tools list`, `npm run build`, or any command not in the relevant impl.md
- **Never** use `"agent-health-dashboard"` (routing slug) as the `-n` flag — always use the human-readable display name from state.json
- **Never** run `uip codedapp publish` without `-n` and `--version` flags
- **Never** fetch the live SDK docs URL — it takes 60–90s
- **Never** read `build-dashboard.mjs` — documented in impl.md
- **Never** run directory exploration via ANY shell — `ls`, `find`, `dir`, `Get-ChildItem`, `tree`, glob loops. Memory or prior-session hints are not a reason to explore; the state.json check is the only existing-work probe
- **Never** read files one at a time
- **Never** commit generated dashboard files
- **Never** auto-deploy without explicit user confirmation
