Copilot
The Copilot is the in-app assistant. Ask it a question in plain English and it answers against your live data — and when the answer is a trend or a breakdown, it draws a chart. Every copilot chart is a live, fully configurable object: the same read-only data the agent could see, plotted through the same charting engine, with a full set of knobs you can turn forever without asking the agent again.
The floating widget
The copilot lives in a floating widget at the bottom-right of every admin and org screen — press ⌘J (Ctrl+J) or click the round launcher to open it. It is a companion, not a pop-over: the page behind stays fully readable and interactive, and minimizing never loses anything — a streaming answer keeps running, and a quiet dot on the launcher tells you it finished (or that a change is waiting for your approval). The widget has two sizes — the compact card and an expanded, near-fullscreen view — and it remembers your conversation and its size across page moves and reloads (per tab).
Open full page in the widget header takes the current conversation to the
full copilot workspace (/admin/copilot) — the deep-work surface with the
conversation rail, search, and delete. The two stay in sync: open a
conversation on the page, leave, and the widget resumes the same thread. On
the workspace itself the launcher hides — the page is the copilot there.
Expanded-view scrim
In the expanded (near-fullscreen) view a subtle scrim dims the page behind the widget so the panel reads as the focus. The compact card never dims the page — it is a companion, not a modal. Clicking the scrim minimizes the copilot back to its floating button. The page keeps scrolling normally and the fade honors your reduced-motion preference.
Reply nudge
If you minimize the copilot while it is working, a small preview appears above the floating button when the reply is ready — the first lines of the answer. Click it to reopen the copilot at the size you last used. The preview slips away after about ten seconds; the unread dot on the button stays until you open the copilot.
Approvals — the action log
Confirming a proposed action executes it under your own permissions, and the conversation then records a neutral “Action completed” event card — the operation name, a one-line outcome, and an expandable raw result for troubleshooting. These event cards are authored by the platform, never by chat input: typing something that looks like a system notice just sends it as an ordinary message. Older conversations show their historical approval notices in the same event-card style.
Proposed-action cards describe what will happen in plain language: a human-readable title, a one-line summary, and the settings the copilot chose — empty filters are omitted (unrestricted), date ranges read naturally (“All time” when unbounded), and job-style operations such as exports count as 1 job, not one record.
Copilot charts
A copilot chart is authored by the agent from a single read-only operation, but it is not a frozen picture. Each chart declares the knobs it exposes — its date window, granularity, group-by dimension, and filters — and binds each one to an argument of the operation it reads from. You turn those knobs on the chart card itself; the agent is only needed to create the chart, never to reshape it.
This brings copilot charts to full parity with the hand-built Dashboard charts (see Dashboard): live data, calendar-anchored windows, persisted per-user filters, and instant presentation toggles. Advanced dynamic charting is now the only way charts are created — there is no static-only chart authoring path.
Charts can also appear inside a screen, with the same pin, export and full-screen options.
Live by default
Every chart the agent draws re-executes its underlying read operation as you, the viewer — not as a cached snapshot of what the agent saw. When you pin a live chart to the dashboard, opening the page re-runs the query with your permissions and shows fresh data. The chart carries a Live badge (or Live · rolling Nd when it uses a rolling window such as the last 30 days). The saved snapshot is used only as an instant placeholder so the chart appears with no loading spinner, then the live series swap in.
If a live refresh can’t complete, the chart degrades rather than failing: it keeps showing the last good snapshot with a quiet “couldn’t refresh” hint and a Live (stale) badge. A dead chart never breaks the page.
Presentation vs. query — what recompiles instantly vs. what re-runs
Copilot charts split every knob into two classes, and the class decides whether the server is involved:
- Presentation knobs recompile instantly, client-side, with zero server round-trips. Changing the chart type, the view (Stacked / Lines / Total), the title, smoothing, data labels, or the y-axis number format is a pure re-render of data you already have. Switching to Total, for example, collapses the series into one summed-per-period line without touching the server.
- Query knobs always re-execute server-side. Changing the window, granularity, group-by (when it is bound to an operation argument), or a filter re-runs the underlying read operation and returns fresh rows. These go through the same read-only execution gate the agent uses.
This is why a presentation tweak is always instant and a query tweak has a brief refresh — they are fundamentally different operations.
A filter control picks its shape from the filter’s kind: a multi-select filter (docket statuses, cost streams) renders as a column of checkboxes you tick on and off, while a single-choice control stays a segmented toggle.
The knobs
The controls that appear on a chart card are exactly the ones the chart declared. A chart only shows the knobs its underlying operation actually supports.
- Window — a date-window picker with calendar-anchored presets: This week, This month, This quarter, This year, Last 7 / 30 / 90 days, or Custom… for a fixed start/end range. Calendar presets (e.g. “this quarter”) are now first-class — ask the agent for a calendar view and you get one you can keep re-anchoring. Windows resolve in the project’s timezone (defaults to
Australia/Sydney), so “this month” always means the current month wherever the page is opened. - Granularity — a Day / Week / Month segmented toggle, shown only when the operation buckets by time.
- Group-by — a segmented toggle over the series/stack dimensions the operation’s row shape allows (for example, group cost by cost code vs. by stream).
- Filters — zero or more filters declared by the chart, each rendered by kind: single-select (enum), multi-select (multi_enum), a boolean checkbox, or a free-text field. Options are seeded when the chart is created and re-validated server-side on every re-run.
- Thresholds — any number you state (“shift hours greater than 3”) becomes a live numeric stepper bound to the query, with the declared min/max/step and unit. Distinct from a chart’s reference lines, which are drawn-on markers that don’t change the data.
- View — the Stacked / Lines / Total presentation toggle (client-side).
- Rename — inline title editing (client-side).
Live filter options (cost codes)
Some chart filters are backed by live platform reference data rather than a
fixed list. When a filter’s operation argument carries a contract-level
x-agent-options binding (cost codes today; suppliers, crews, activities and
field users as fast-follows), the platform attaches a live options source to
the chart — in chat and on every pinned dashboard card, including charts pinned
before this feature existed.
- The filter renders as a searchable dropdown. Opening it fetches the project’s current list (for cost codes: the same register the cost-code workbench uses — CSV upload or COINS, per your organisation’s ERP source).
- Options are fetched as you: a shared chart shows each viewer only what their own access allows.
- The dropdown accepts values beyond what the chart originally embedded — pick any current cost code and the chart re-queries and saves your selection.
- Closed lists (docket statuses, cost streams) keep their fixed chip toggles.
Adding a new live-bound domain is a one-line contract annotation — no new code.
Live filter option domains
Chart filter dropdowns are bound to the platform’s live reference data in the
contract (x-agent-options) — never a generation-time snapshot. Options are
fetched as the viewer, so shared pins show each viewer only what they can access.
| Domain | Options source | Scoped by | Typeahead |
|---|---|---|---|
| Cost codes | listProjectCostCodes | project | yes (q) |
| Supervisors | listEligibleSupervisors (+ per-report pickers) | project | — |
| Issue types / statuses | listIssueTypes / listIssueStatuses | project | — |
| Project people | listProjectMembers | project | — |
| Field workers | listProjectFieldUsers | project | yes |
| Diaries | listDiaries | project | yes |
| Plant | listPlantRegister | project | yes |
| Dayworks items | listDayworksCatalog | project | — |
| Sign-on locations | listProjectLocations | project | — |
| Induction roles | listInductionRoles | induction form | — |
| Suppliers | listSupplierLinks | org | yes |
| Projects | listProjects | org | yes |
| Org users | listOrgUsers | org | yes |
| Contracts | listContracts | org | — |
Persistence on the dashboard
Pin a copilot chart to the dashboard and your knob settings are saved per user, per pin. Each viewer’s current window, granularity, group-by, and filter values are stored in that pin’s filter_state, so your view of a shared pinned chart is yours — changing your filters never affects a teammate’s. Saves are debounced (500 ms) and written as a wholesale swap of the override object, then the live chart re-runs against the freshly persisted values — identical UX physics to the hand-built Dashboard chart cards.
Tweaks you make in the chat thread before pinning are carried into the pin at pin time, so the pinned chart starts exactly as you shaped it.
Security model
A user override can never widen what runs: reshaping a chart only changes the values of declared params bound to declared operation arguments — the operation identity, its result mapping, and any unbound arguments are immutable from the client. Every override is re-validated against the catalog’s argument schema, and every execution (creation, chat re-query, pinned refresh) passes the same read-only gate the agent is held to (HTTP read risk, GET-only). A pinned chart can never run anything its viewer couldn’t run themselves.
Static snapshots
Occasionally the agent computes a figure that can’t come from a single read operation (for example, a number it assembled across several tools). It can still chart that result, but the chart is clearly labelled Static snapshot and shows no live controls. Because a static snapshot has no re-executable source, it cannot be pinned to the dashboard — this keeps one-off analysis available in the chat without polluting anyone’s dashboard with a chart that can never refresh.
Drill-down
Clicking a chart segment stages a drill chip above the composer — e.g. “Drill: 8 Jul · Labour” — with an × to discard it. Your next message carries the drill context automatically; type a follow-up or just hit send. Drilling from a pinned dashboard chart surfaces the floating widget with the chip staged; on the full-page workspace you’re already there, so nothing pops over your thread.
Screens in answers
An answer can be a screen: a small page of totals, tables, charts, filters and buttons, built from your live data. It appears in the conversation under the answer’s text.
- Records open from the screen. Click a record in a table to open it. In a project, dockets open beside the page you are on. Other records open on their own page. A record from another project switches to that project first.
- Questions and buttons. Suggested questions appear as chips under a screen. Click one, or a button, and Copilot answers in the same conversation. A button on a form also sends what you typed.
- Starter questions. An empty conversation offers three questions to begin with. The Guide has the same three.
- Suggested reply. After each answer, the message box shows one suggested next message in grey. Press Tab (or Use on a touch screen) to put it in the box, change it if you like, then press Enter. Esc hides it until the next answer. An empty conversation suggests its first starter question.
- Filters update instantly. Change a status, a date range or a picker and the table and charts re-run straight away. The previous rows stay on screen until the new ones arrive.
- Charts. A chart on a screen can be exported or opened full screen. In a project it can also be pinned to the dashboard, like any other Copilot chart.
- Showing N of M. A table that has more rows than fit says “Showing 20 of 140”. Use Previous and Next to move through the rest.
- Saving changes. Saving from a screen shows a confirm card first. Nothing changes until you confirm. Once it runs, Undo is on the result.
- What you typed is kept. Filters and text you entered stay on the screen when you reload the page or come back to the conversation.
- Screens stay current. In a project, when a record changes, here or in another tab, the screen shows the new value without a reload.
- QR codes. In a project, ask for QR codes (for example, “show the location QR codes”) and Copilot shows them ready to scan, each with its full name and Print, which opens the print sheet. Up to 6 show in the answer; when there are more, Show all in QR Manager opens the rest. QR codes are not shown on a screen saved to the dashboard.
Copilot cannot change anything without your confirm, on a screen or anywhere else.
Guide
The Guide button at the top of the Copilot page (/admin/copilot and /org/copilot) opens a short guide: three starter questions and the Tab key for the suggested reply, what a screen can show, opening records, filtering and charts, changing records with Confirm and Undo (including ticking rows and editing cells in a table), changing a screen, asking follow-ups from a screen, and saving a screen to the dashboard.
Voice typing
Hold the microphone button in the composer to dictate; release to transcribe. The transcript lands at your cursor so you can edit before sending. Voice notes cap at 60 seconds / 10 MB and nothing is stored — audio is transcribed and discarded. If the mic permission is blocked, the copilot tells you instead of failing silently.
Changing a screen
Ask for a change to the screen Copilot just showed, in plain words: “make it weekly”, “add a supplier column”, “only night shifts”, “remove the chart”.
- The screen changes in place. Copilot answers with the updated screen, built from the one you were looking at.
- Your picks are kept. Filters, pickers and text you entered on the earlier screen carry over to the updated one.
- The earlier version folds away. It shows as one line, “Updated below”. Click Show to open it again, Hide to fold it. A change it is still waiting on you to confirm stays visible under the line.
- If the screen can no longer be shown (for example, you no longer have access to its data), Copilot gives the answer without the screen.
Daily limit
Each person, and each organisation, has a daily Copilot limit. When a question goes over it, Copilot says so in the conversation and gives the time it resets, in the project’s time zone: “You’ve reached today’s Copilot limit. It resets at 11:00 am.” The question goes back into the box, ready to send again.
- The day is the UTC day, so the limit resets at UTC midnight: 11:00 am in Sydney during daylight saving, 10:00 am outside it.
- A first question that is refused leaves no empty conversation in the list.
- The same applies when Copilot is busy, paused or restarting; those messages carry no time.
Saving a screen to the dashboard
A screen that shows live data has a Save to dashboard button under it. Give the screen a name and click Save. The toast’s Open link takes you to it.
- Where it goes. A screen made in a project goes on that project’s
dashboard. A screen made on the org Copilot (
/org/copilot) goes on the org dashboard. - Only you see it. Saved screens are yours, like pinned charts.
- Live data. The screen shows your current data each time you open the dashboard, and updates when the records change. Filters and picks you change on it stay when you come back.
- Changes still ask first. A button that changes records shows a confirm card in the screen’s card. Nothing changes until you confirm. The result and its Undo stay on the card.
- No chat on the dashboard. Suggested questions and buttons that ask Copilot are not shown on a saved screen.
- Up to 12 per dashboard. Remove one to save another.
- Saved as it was. Deleting the conversation does not remove the saved screen. If a screen can no longer be shown, its card says “This screen needs to be made again in Copilot.”
See Dashboard: Saved Copilot screens for renaming, moving and removing.
Filters
Copilot only uses the filters you ask for.
Changing many records on a screen
Ask for a screen that changes records (“show submitted dockets so I can review them”, “let me set each draft’s start time”) and Copilot can build one of two kinds of table:
- Tick rows. Tick the rows, then press the button under the table. “3 selected” counts every ticked row, on any page; Clear unticks them.
- Edit cells. Type a value in each row you want to change, then press Save changes. “2 changed” counts the rows you edited; Clear changes puts them back.
Either way you get one confirm card for the whole change and one Undo on the result. Up to 500 records go in one change. Dockets are the first records with editable cells. See Bulk Edit & Undo.
Spec & plan
- Spec:
docs/superpowers/specs/2026-07-14-copilot-chart-full-parity-design.md - Widget:
docs/superpowers/specs/2026-07-14-copilot-floating-widget-design.md