# Fluix Report Dashboard

**One-line purpose:** Turn any Fluix data source — a task report or a document dataset/status view, whatever fields it actually contains — into a visual dashboard with the metrics, breakdowns, and anomalies that its own schema supports, plus a flagged-findings list. No fixed set of dimensions; the skill discovers what's meaningful in *this* data before deciding what to chart.

---

## When to trigger it

- "Read the report [X] in Fluix and create a dashboard from that data"
- "Turn this Fluix report/dataset/document status into a dashboard / visualize this data"
- "What does the [X] data look like" / "summarize [X] report visually" / "analyze this report or dataset"
- Any request that names a Fluix task report, document dataset, or document-status view (by name or ID) and asks for a visual, summary, dashboard, or analysis
- Follow-ups like "add more charts," "break this down by [some field]," or "combine that into one dashboard" continue the same skill rather than starting over

## Inputs

Required (ask only if genuinely ambiguous — otherwise infer):
- **Data source name or ID, and which family it belongs to** — Fluix exposes two parallel tool families:
  - **Tasks** (`tasks_list_reports`, `tasks_report_schema`, `tasks_report_rows`) — process/workflow task reports, e.g. inspections, work orders.
  - **Docs** (`docs_list_datasets`, `docs_dataset_schema`, `docs_dataset_rows` for form-submission datasets; `docs_status_rows`/`docs_status_schema` for document status/workflow tracking by condition, owner, group, or date range).
  If the user names a source loosely, check both families' listing calls rather than assuming Tasks by default — a name like "inspection" could live in either. If it's genuinely unclear which family or which specific item matches, ask.

Optional, inferred from context or defaulted:
- **Need signal** — never asked for directly unless truly ambiguous. Inferred from how the request is phrased against the Jobs to be done below — e.g. "what's overdue for my crew" reads as chase-list/ownership framing, "give me the trend across sites this quarter" reads as aggregate-trend framing. Defaults to the broadest useful framing (general operational view: chase-list + top-line pattern) when no clear signal is present.
- **Row limit / pagination** — pull up to 100 rows per page via `tasks_report_rows` or `docs_dataset_rows`/`docs_status_rows`; paginate on `cursor` if the source is larger. For very large sources (100s+ rows), pull enough to characterize the distribution reliably rather than every row — say so if sampling.
- **Dimensions and metrics** — never fixed in advance. Derived from what the matching schema call (`tasks_report_schema` or `docs_dataset_schema`/`docs_status_schema`) returns for this source (step 2), the use case inferred from its name, fields, and values (step 4), and the need signal inferred above.
- **Threshold for "flagged" findings** — no fixed number. A finding earns a flag if it's a disproportionate share, a concentration, a 100%-of-a-small-group result, a correlation between two fields, or a value that breaks a pattern the rest of the data follows.

## Jobs to be done

These describe *what someone actually needs from the data*, grouped by need-type rather than by who they are — so chart selection, level of detail, and findings-list tone match the need signaled in the request, not a guessed job title. Matching is a soft signal from phrasing/context, not a required input; when no clear need is signaled, default to a general operational view (outstanding-work chase-list + top-line pattern) rather than forcing a fit.

- **Chase-list, ownership-level visibility** — wants to see which items on a specific site/crew/scope are incomplete, unsigned, overdue, or stuck, and who's responsible for each, so the right person can be chased before it becomes a bigger gap. Wants what's outstanding *for a specific slice* right now, not a full report to sift through.
- **Cross-site/cross-team rollups and aging** — wants a digest of what's overdue, aging, or blocked across multiple sites/teams/projects, so the right issues can be raised without manually compiling status from each one. Wants to see which workflow step or stage things get stuck at, so the process bottleneck gets fixed rather than any one individual chased.
- **Severity, trend, and root-cause analysis** — wants findings/defects ranked by severity, with anything found-but-not-verified-as-resolved flagged, so the gap closes before it becomes a bigger incident or audit finding. Wants failure counts for a specific slice over a chosen period, to judge whether risk is isolated or part of a wider pattern; the most frequent issues across everything, to prioritize the highest-impact fixes; issues broken down by type with dominant root causes; categories trending up or down over time, to catch a worsening risk hiding behind an improving overall average; unusual periods (spikes/drops) flagged for investigation rather than treated as noise; and which sources (inspectors/sites/forms) produce inconsistent or messy data, so the process/form gets fixed rather than the reports cleaned up after the fact.
- **Asset-level status and failure patterns** — wants to see which assets are up to date vs. due, so scheduling happens before a compliance or breakdown risk occurs. Wants the most recurring issues across assets, to address a systemic problem instead of treating each failure as one-off. Wants the real pass/fail ratio, not just raw volume.
- **Aggregate trend with a confidence check, no row-level detail** — wants to know whether metrics are trending better or worse, to judge if current efforts are working before risk escalates. Wants a short, high-signal read on where to focus attention or budget without reading raw data. Wants explicit confidence that the numbers reflect real, clean data (not demo/test entries or malformed records) before deciding on them.
- **Personal, non-punitive visibility into one's own pending work** — wants to see if their own recent submissions are missing required fields, photos, or signatures, so it can be fixed before someone else flags it.
- **External, simplified proof-of-compliance** — wants a simple, read-only summary confirming required work was completed and passed, as documented proof without needing to interpret raw operational data or see internal detail (assignee names, internal notes).
- **Data/template quality auditing** — wants to identify which forms or sources have inconsistent field formats, placeholder values, or missing validation, so templates get fixed at the source and every downstream report becomes trustworthy.

## Workflow steps

1. **Find the data source and confirm which tool family it's in** — call `Fluix:tasks_list_reports` and, where relevant, `Fluix:docs_list_datasets` (and check `docs_status_rows`/`docs_status_schema` if the request is about document status/workflow rather than a report or dataset). Don't assume Tasks is the right family just because it's the more familiar one — match on what the user actually named.
2. **Get the schema first, always** — call the schema tool matching the source (`tasks_report_schema` for a Tasks report; `docs_dataset_schema` for a Docs dataset; `docs_status_schema` for a document-status view) before touching rows. Classify every field returned (system + form) into a working type, since the source's own shape determines everything downstream:
   - **Categorical / status** — small set of repeating values (condition ratings, pass/fail checks, priority, workflow status, document status). Candidates for distribution charts.
   - **Numeric** — counts, durations, scores, measurements. Candidates for averages, ranges, outlier detection.
   - **Date / time** — inspection date, due date, last action, created/completed timestamps. Candidates for trend-over-time charts and lag/duration calculations (e.g. time between two dates).
   - **Identifier** — serial numbers, emails, process keys, document IDs, owners/groups. Not charted directly, but used to detect repetition (the same entity recurring across rows).
   - **Free text** — notes, observations, descriptions. Not aggregated or charted; sampled/quoted only if a chart finding calls for a specific example, and only in your own words per copyright rules.
   - **Signature / boolean-ish** — signed/unsigned, yes/no flags. Treated as categorical.
   - If a field's role is unclear from its name, check a handful of sample values before deciding — don't guess from the field name alone (e.g. `radio-group-34` tells you nothing; its values do).
3. **Pull the rows** — `Fluix:tasks_report_rows`, `Fluix:docs_dataset_rows`, or `Fluix:docs_status_rows`, matching whichever family step 1-2 identified (format `json` where applicable). Note which rows have empty/unfilled data — exclude them from content aggregations but keep them in workflow-status counts (a blank checklist, or a document still in draft, is still a real "not started" data point).
4. **Identify the use case and likely audience before picking charts** — using the report name, workflow name, field names, and a sample of actual values, work out what kind of process this is and what "good" vs. "bad" looks like in it. Reports vary widely — equipment/vehicle/turbine/facility inspections, safety or compliance audits, work orders describing work performed, incident reports, delivery or handover checklists, surveys — and each implies a different center of gravity:
   - **Inspections/audits of a physical asset** (equipment, vehicle, turbine, facility) — the asset's identity (serial/unit/asset ID) and condition/pass-fail rating are usually central; check for repeat-unit concentration and recurring failure points, as done for the Demo Equipment Inspection report.
   - **Work orders / completed-work reports** — the center of gravity shifts to what work was done, by whom, how long it took, and whether it was completed as scoped. Prioritize: task/job type distribution, duration or turnaround time, completion vs. rework rate, technician/crew comparison. Condition-style charts may not even exist here.
   - **Incident / safety reports** — severity, root cause/category, location, and time-to-resolution or time-to-report tend to matter most; look for clustering by cause or by location/time rather than by physical unit.
   - **Delivery / handover / survey-style reports** — response distributions and completion/compliance rates (e.g. % signed off, % fields completed) tend to be the most useful summary, since there's often no "condition" concept at all.
   - **Document status / library tracking (Docs tools)** — center of gravity is usually status distribution (draft/in review/approved/expired), age or time-in-status, and ownership/group concentration — where are documents piling up, and who or which group holds the most.
   - If the use case doesn't clearly match one of these, don't force it into the closest template — reason from the actual fields and values present instead (this is still governed by step 2's field classification either way).
   - Alongside the use case, check the request's phrasing against the Jobs to be done above for a need signal — "what's overdue for my crew" points toward chase-list/ownership framing (actionable, minimal, by-owner); "trend over the quarter" or "are we improving" points toward aggregate-trend framing (KPI rollup + trend, no row-level detail, confidence check); "rank findings by severity" or "found vs. repaired" points toward severity/root-cause framing. Don't force a fit when there's no signal — default to a general operational view.
   - State the inferred use case (and need signal, if any) to yourself before building anything, since both determine which of the analyses in step 5 are worth doing and which would be noise for this particular report and request.
5. **Decide what's worth aggregating** — don't apply a fixed checklist of breakdowns. Instead, for the categorical and numeric fields actually present:
   - Compute the distribution of every categorical field with more than one distinct value and fewer distinct values than roughly a third of the row count (past that, it behaves like an identifier, not a category — e.g. don't chart 40 near-unique "location" values as a bar chart).
   - For numeric fields, compute min/max/mean/median and flag values far from the rest (outliers).
   - For date fields, check whether the range is wide enough to support a real trend line (multiple distinct periods) — if the whole report is one week, a time chart adds nothing; say so instead of forcing one.
   - For identifiers, count repetitions — a serial number or process key appearing multiple times is itself a finding worth surfacing (concentration on one entity).
   - Only compute a cross-tab (dimension A by dimension B) when a single-dimension view of A wouldn't already explain the pattern — e.g. if 100% of rows are "poor," a status-by-type cross-tab won't add anything; if it's mixed, it might.
6. **Look for patterns actively, not just tally** — beyond raw counts:
   - **Concentration** — does a small number of categories/entities account for most of the volume or most of the problem cases?
   - **Correlation across fields** — does one categorical/numeric field track with another (e.g. a specific check failing alongside a specific outcome)?
   - **Trends over time** — if dates support it, is a rate rising/falling across periods rather than flat?
   - **Outliers/anomalies** — values, entities, or categories that break the pattern the rest of the data follows, especially small-sample 100%-of-something results (call out the sample size so it isn't over-read).
   - **Workflow health** — where in the process are records stuck, and is that concentrated in one step/assignee?
7. **Render one consolidated dashboard** via the Visualizer (`chart` module): metric cards for the headline totals, then charts ordered by how much they explain — the strongest/most decision-relevant signal first, general context breakdowns after, any cross-tab or trend last. The set of charts is whatever step 4-6 actually produced, weighted by the use case *and* the need signal from step 4 — e.g. an aggregate-trend framing keeps every individual chart at the rollup/trend level (no row-level breakdowns), but that doesn't mean fewer charts: pair the headline KPI cards with a trend line, a confidence/data-quality note, and any other aggregate cut (by category, by period, by ratio) that adds real signal, so the result reads as a genuine dashboard rather than four numbers on a page. A chase-list/ownership framing leans toward who/what is outstanding over a severity trend. Never pad with a chart that repeats another one's information, and never omit one because it wasn't in a template — the goal is the most insight the data actually supports, at whatever level of detail the need signal calls for.
8. **Write findings as prose bullets in the response text**, not inside the widget — each bullet names the specific number/pattern and why it matters, ends with an offer to drill into one of them (a different dimension, the free-text fields for a flagged subset, or a narrower date range). Match tone to the inferred need where one is signaled (e.g. more clinical/risk-framed for severity/root-cause requests, more "here's what to do today" for chase-list requests) without changing what the underlying numbers say.

## Output format

Response always has exactly two parts, in this order:
1. One Visualizer call producing a single dashboard (metric cards + whatever charts steps 4-7 determined were meaningful for this specific report and use case).
2. A short "worth flagging" bullet list in the response text (not in the widget) — each bullet: **the number/pattern** + **why it matters** or what to check next. Close with an offer to drill down further, not an open-ended "what else."

Never repeat chart data as prose paragraphs above/below the list — the findings list is the only prose summary, and it should read differently each time based on what the schema, use case, and data actually contained.

## Guardrails

- Don't assume any report has a fixed set of dimensions (no hardcoded "location," "equipment type," "condition" fields) — every report gets its charts from its own schema, not from a template of prior reports.
- Don't default to an inspection-style dashboard (condition, unit concentration, failure ranking) just because that's a common case — if the use case identified in step 4 is a work order, incident log, survey, or document-status view, build the charts that fit that use case instead, even if it looks nothing like a prior run.
- Don't assume every request is a Tasks report — check both `tasks_list_reports` and `docs_list_datasets` (plus `docs_status_rows` for status-tracking asks) before concluding a source doesn't exist, and use the schema/rows tools that match whichever family it's actually in.
- Don't call the dashboard render before pulling the schema — field names/labels (especially auto-generated ones like `radio-group-34` or `image-field-48`) aren't guessable and must be confirmed against sample values first.
- Don't chart a field just because it exists — high-cardinality fields (near-unique per row) behave like identifiers, not categories, and belong in repetition/concentration checks, not bar charts.
- Don't front-load every possible metric into the first version — build the strongest-signal chart(s) first; add further breakdowns or cross-tabs only if the user asks for "more charts" or a follow-up question needs them.
- Don't force a chart type the data doesn't support — no time-trend chart over a single short date range, no cross-tab when one dimension already fully explains the pattern.
- Don't treat unlabeled/generic form field names as meaningful categories in the findings list — describe them neutrally rather than guessing what they represent.
- Don't put explanatory prose, headings, or the findings list inside the widget itself — text belongs in the chat response.
- Don't state or imply data is production/live without checking — if a report name or content suggests demo/sample data (e.g. "Demo," placeholder emails, sequential fake serial numbers), flag that uncertainty to the user rather than treating findings as operational fact.
- Don't skip re-aggregating after the user asks to merge multiple prior widgets into one — pull the same computed numbers forward consistently rather than re-deriving them differently the second time.
- When combining previously-shown charts into a single dashboard, don't silently drop any chart the user has already seen unless they asked to remove it.
- Don't over-read small samples — a 100%-of-something finding on a sample of 1-2 is worth a caveat, not a confident claim.
- Don't invent a specific need framing when there's no phrasing/context signal for one — defaulting to a general operational view is correct more often than guessing a narrow framing and getting it wrong.
- Don't apply external/simplified framing (hiding assignee names, internal notes, row-level detail) unless the request actually signals an external/compliance-summary need — internal requests should get full operational detail by default.
- Don't let need-framing change what the data actually says — tone and chart selection can shift with the signaled need, but numbers, findings, and caveats must stay identical regardless of who's asking or why.
- Don't mistake "aggregate-only" for "sparse" — a trend-and-confidence framing still deserves multiple charts and a data-quality note, not just a handful of KPI cards; maximize genuine insight at whatever level of detail the need signal calls for, so it reads as a real dashboard rather than a stat block.
