@malloy-publisher/skills 0.1.9 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/malloy/SKILL.md +3 -2
- package/skills/malloy-analysis/SKILL.md +1 -1
- package/skills/malloy-analysis-pitfalls/SKILL.md +1 -1
- package/skills/malloy-analysis-report/SKILL.md +2 -2
- package/skills/malloy-analyze/SKILL.md +5 -3
- package/skills/malloy-charts/SKILL.md +1 -1
- package/skills/malloy-dashboards/SKILL.md +123 -59
- package/skills/malloy-debug/SKILL.md +9 -6
- package/skills/malloy-define/SKILL.md +2 -2
- package/skills/malloy-discover/SKILL.md +1 -1
- package/skills/malloy-document/SKILL.md +6 -4
- package/skills/malloy-getting-started/SKILL.md +51 -1
- package/skills/malloy-gotchas-modeling/SKILL.md +42 -2
- package/skills/malloy-gotchas-queries/SKILL.md +1 -1
- package/skills/malloy-gotchas-rendering/SKILL.md +1 -1
- package/skills/malloy-html-data-app-embedding/SKILL.md +1 -1
- package/skills/malloy-html-data-app-runtime/SKILL.md +1 -1
- package/skills/malloy-html-data-apps/SKILL.md +1 -1
- package/skills/malloy-lookml-review/SKILL.md +1 -1
- package/skills/malloy-lookml-review/reference/_concepts.md +1 -1
- package/skills/malloy-lookml-review/reference/build-derived-tables.md +5 -3
- package/skills/malloy-materialization/SKILL.md +19 -4
- package/skills/malloy-materialization-tuning/SKILL.md +1 -1
- package/skills/malloy-model/SKILL.md +17 -3
- package/skills/malloy-model-as-you-go/SKILL.md +306 -0
- package/skills/malloy-modeling/SKILL.md +5 -6
- package/skills/malloy-notebook-chat/SKILL.md +2 -2
- package/skills/malloy-notebooks/SKILL.md +1 -1
- package/skills/malloy-patterns/SKILL.md +1 -1
- package/skills/malloy-phrase-detection/SKILL.md +1 -1
- package/skills/malloy-publish/SKILL.md +1 -1
- package/skills/malloy-queries/SKILL.md +1 -1
- package/skills/malloy-review/SKILL.md +1 -1
- package/skills/malloy-review/reference/rubric-structure.md +1 -1
- package/skills/malloy-scope/SKILL.md +1 -1
package/package.json
CHANGED
package/skills/malloy/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy
|
|
3
3
|
description: Index of all Malloy skills. Use when user asks "malloy help", "what malloy skills are available", "how do I use malloy", or needs guidance on which Malloy skill to use.
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.12
|
|
5
5
|
---
|
|
6
6
|
<!--
|
|
7
7
|
Copyright (c) Credible Data Inc.
|
|
@@ -42,7 +42,8 @@ Every skill in this deployment, by what it is for. Start at a driver; it routes
|
|
|
42
42
|
|
|
43
43
|
| Skill | Use when... |
|
|
44
44
|
|-------|-------------|
|
|
45
|
-
| `skill:malloy-
|
|
45
|
+
| `skill:malloy-model-as-you-go` | After answering a question, writing down what it assumed: a `#(doc)`'d field in the model, an `extend` in the notebook, or a stated assumption plus snippet, depending on what the session can write |
|
|
46
|
+
| `skill:malloy-analyze` | Open-ended exploration with no intent to keep anything: profiling, hypotheses, views |
|
|
46
47
|
| `skill:malloy-charts` | Chart selection and renderer reference for Malloy visualizations |
|
|
47
48
|
| `skill:malloy-notebooks` | Building Malloy notebooks (.malloynb) |
|
|
48
49
|
| `skill:malloy-analysis-report` | Combining validated queries into a notebook report or dashboard |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-analysis
|
|
3
3
|
description: Workflow for answering data questions against Malloy semantic models over MCP - structured discovery with get_context, query construction with execute_query, verification, and answer delivery. Use whenever the user asks a data question, wants a metric, a breakdown, a trend, or a chart over a model.
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.12
|
|
5
5
|
---
|
|
6
6
|
<!--
|
|
7
7
|
Copyright (c) Credible Data Inc.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-analysis-pitfalls
|
|
3
3
|
description: Common data analysis pitfalls to watch for during query construction and result interpretation. Reference this checklist when verifying queries and results to catch errors before presenting an answer.
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.12
|
|
5
5
|
---
|
|
6
6
|
<!--
|
|
7
7
|
Copyright (c) Credible Data Inc.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-analysis-report
|
|
3
3
|
description: Combine validated Malloy queries into a notebook report or dashboard. Use when the user asks to "create a report", "build a dashboard", "combine these into a report", or wants a persistent multi-query artifact.
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.12
|
|
5
5
|
---
|
|
6
6
|
<!--
|
|
7
7
|
Copyright (c) Credible Data Inc.
|
|
@@ -24,7 +24,7 @@ Do NOT build the notebook in the same turn as `execute_query`. Explain first, th
|
|
|
24
24
|
|
|
25
25
|
## Filters are inherited from the model, don't declare them in the report
|
|
26
26
|
|
|
27
|
-
Reports do not (and cannot) define their own filters. If the source
|
|
27
|
+
Reports do not (and cannot) define their own filters. If the source declares `given:` parameters (or legacy `#(filter)` annotations), Publisher renders the controls, parses caller parameters, and applies them server-side automatically: the report inherits and displays them with no extra work. If the analysis needs a knob the source doesn't expose, the right move is to add a `given:` to the source itself, not to wedge a filter widget into the report. `#(filter)` is deprecated in favour of native Malloy `given:` parameters. Do not add new `#(filter)` annotations; the two exceptions are `required` and `implicit`, which `given:` cannot cover yet. The `malloy-model` skill covers this under § Legacy: Parameterizable Filters. For curated notebooks with their own per-notebook filter UI on top of the model, see `skill:malloy-notebooks` instead.
|
|
28
28
|
|
|
29
29
|
## What goes in the report
|
|
30
30
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-analyze
|
|
3
|
-
description:
|
|
4
|
-
version: 0.1.
|
|
3
|
+
description: Open-ended exploration with no specific question to answer, and building views/dashboards/notebooks on an existing model. Use when the user asks "what's interesting?", "explore this data", "find insights", "look for patterns", "build a dashboard", or "create views". Not for a specific data question - answering one is `malloy-analysis`, and writing down what the answer assumed is `malloy-model-as-you-go`. For exploration start at Step 1; for views on an existing model jump to View Patterns.
|
|
4
|
+
version: 0.1.12
|
|
5
5
|
---
|
|
6
6
|
<!--
|
|
7
7
|
Copyright (c) Credible Data Inc.
|
|
@@ -254,7 +254,9 @@ A notebook is also the home for a polished, narrated report: alternate `>>>markd
|
|
|
254
254
|
|
|
255
255
|
### Interactive Filters
|
|
256
256
|
|
|
257
|
-
**Notebooks do NOT define filters themselves.** When you import a model, the model's
|
|
257
|
+
**Notebooks do NOT define filters themselves.** When you import a model, the model's runtime parameters are **inherited and displayed automatically**: the publisher renders the controls, parses caller parameters, and applies them server-side. You don't redeclare them in the consumer. If the analysis needs a knob the model doesn't expose, the right move is to add it to the source itself, not to wedge filtering into the consumer.
|
|
258
|
+
|
|
259
|
+
**Declare that knob as a `given:`.** `#(filter)` is deprecated in favour of native Malloy `given:` parameters. Do not add new `#(filter)` annotations; the two exceptions are `required` and `implicit`, which `given:` cannot cover yet. See `skill:malloy-model` § Legacy: Parameterizable Filters.
|
|
258
260
|
|
|
259
261
|
The notebook-level `##(filters)` annotation and the dimension-level `#(filter) {"type": "..."}` JSON-blob form are **unsupported legacy syntax**, don't use them. The only supported form is `#(filter) name=... dimension=... type=...` declared above the source.
|
|
260
262
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-charts
|
|
3
3
|
description: Chart selection guidance and renderer reference for Malloy views. Use when choosing visualization types, adding chart annotations, user asks "what chart should I use", "how should I visualize this", or when deciding between bar_chart, line_chart, scatter_chart, etc.
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.12
|
|
5
5
|
---
|
|
6
6
|
<!--
|
|
7
7
|
Copyright (c) Credible Data Inc.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-dashboards
|
|
3
3
|
description: "Build or modify a Malloy Publisher dashboard, a tagged .malloy file in a package's dashboards/ directory, with auto-rendered filter controls, a grid layout, and # drill click-through. Use when the user asks for a dashboard, a filterable operational view, or drill-through between views, and no code is wanted."
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.12
|
|
5
5
|
---
|
|
6
6
|
<!--
|
|
7
7
|
Copyright (c) Credible Data Inc.
|
|
@@ -31,8 +31,9 @@ Scanned at a glance is a dashboard; read top to bottom is a notebook.
|
|
|
31
31
|
`malloy_getContext` if you have it, otherwise the REST model endpoint or the `.malloy` files.
|
|
32
32
|
Never guess a name. A guessed field in a query fails the whole package load, not just that one
|
|
33
33
|
dashboard; a guessed tile or suggest source is quieter, and only shows up in the package warnings.
|
|
34
|
-
2. **
|
|
35
|
-
|
|
34
|
+
2. **PICK THE VIEWS TO SHOW.** A dashboard is `## artifact { tiles=[…] }` naming existing views, so
|
|
35
|
+
this is the design step: which views, how wide each sits, what each is called. There is one form,
|
|
36
|
+
so there is no form to choose.
|
|
36
37
|
3. **DECLARE THE GIVENS** the dashboard will filter by, in the model (usually `givens.malloy`), with
|
|
37
38
|
their control tags: see "Filter controls" below for the syntax and what each tag renders as. Skip
|
|
38
39
|
if they already exist, since a given is a model concern and dashboards share them.
|
|
@@ -40,7 +41,11 @@ Scanned at a glance is a dashboard; read top to bottom is a notebook.
|
|
|
40
41
|
Import every given it filters by, and every source or query any of those givens names in a
|
|
41
42
|
`suggest`. Both are per-file, and getting the suggest wrong does not error: the control still
|
|
42
43
|
looks like a picker but has no options, and says so underneath, "Could not load the options for
|
|
43
|
-
this control". The package warnings name it too.
|
|
44
|
+
this control". The package warnings name it too. **A `suggest` naming a `query=` needs that
|
|
45
|
+
query's own source imported as well**, because an import is not transitive: the query resolves by
|
|
46
|
+
name, so the file compiles and the package loads, but running the picker fails with
|
|
47
|
+
`Undefined source '<name>'`. The package warnings name this one too, saying which source to
|
|
48
|
+
import. Import the source that suggest query reads, not just the query.
|
|
44
49
|
5. **COMPILE IT** with `malloy_compile` (or `POST …/models/<path>/compile`), against the source text,
|
|
45
50
|
before you save, at the path the file will have. **Editing one that already exists needs
|
|
46
51
|
`"scope": "file"`**, which compiles your source AS that file; the default appends it instead, so
|
|
@@ -48,7 +53,7 @@ Scanned at a glance is a dashboard; read top to bottom is a notebook.
|
|
|
48
53
|
already-defined errors that reads as broken Malloy rather than a wrong scope. **Editing a shared
|
|
49
54
|
include wants `"scope": "package"`**, which recompiles every file as saved: `file` only checks the
|
|
50
55
|
one you are editing, so renaming a source in `_shared.malloy` passes it while breaking every
|
|
51
|
-
|
|
56
|
+
dashboard that imports it. A clean compile is not a working dashboard: some tag mistakes surface
|
|
52
57
|
at step 6, and some only when you look at the page in step 7. (The third scope, `append`, is the
|
|
53
58
|
default and is what a not-yet-saved file gets.)
|
|
54
59
|
6. **SAVE IT, RELOAD, AND READ THE MANIFEST AND THE WARNINGS.** `malloy_reloadPackage`, or
|
|
@@ -60,9 +65,63 @@ Scanned at a glance is a dashboard; read top to bottom is a notebook.
|
|
|
60
65
|
and its `query` is the name to run in step 7. See "Read the lint" below.
|
|
61
66
|
7. **OPEN IT AND LOOK.** Not optional; see "What 'done' means".
|
|
62
67
|
|
|
63
|
-
## The
|
|
68
|
+
## The form
|
|
64
69
|
|
|
65
|
-
|
|
70
|
+
A dashboard is `## artifact { tiles=[…] }` at model level: named views, each run as its own query, laid
|
|
71
|
+
out by Publisher into the grid `# dashboard { columns=N }` names.
|
|
72
|
+
|
|
73
|
+
```malloy
|
|
74
|
+
##! experimental.givens
|
|
75
|
+
## artifact { title="Storefront overview" tiles=["overview -> kpis", "overview -> revenue_trend", "overview -> revenue_by_state"] } dashboard { columns=12 }
|
|
76
|
+
import { scoped_sales } from './_shared.malloy'
|
|
77
|
+
import { products } from '../storefront.malloy'
|
|
78
|
+
import { CATEGORY, SINCE } from '../givens.malloy'
|
|
79
|
+
|
|
80
|
+
// Layout goes on the VIEW, and a thin re-declaration is the place to put it: the
|
|
81
|
+
// modelled view keeps its chart tag, and this decides how wide it sits here.
|
|
82
|
+
source: overview is scoped_sales extend {
|
|
83
|
+
# colspan=12
|
|
84
|
+
# label="Key figures"
|
|
85
|
+
# big_value
|
|
86
|
+
view: kpis is {
|
|
87
|
+
aggregate:
|
|
88
|
+
# label="Revenue"
|
|
89
|
+
# currency
|
|
90
|
+
total_sales
|
|
91
|
+
# label="Orders"
|
|
92
|
+
order_count
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# colspan=8
|
|
96
|
+
# break
|
|
97
|
+
# label="Revenue by month"
|
|
98
|
+
view: revenue_trend is sales_by_month
|
|
99
|
+
|
|
100
|
+
# colspan=4
|
|
101
|
+
# label="Revenue by state"
|
|
102
|
+
view: revenue_by_state is sales_by_state
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Model-level because there is no query of its own to hang a `#` tag on, and model-level for a second
|
|
107
|
+
reason: tiles run as separate queries, which is the only way a page can span unrelated sources. A
|
|
108
|
+
nest's pipeline starts from its own query's source and there is no way to combine two.
|
|
109
|
+
|
|
110
|
+
Three things the form costs, so you are not surprised by them:
|
|
111
|
+
|
|
112
|
+
- **A tile expression is a string in an annotation, so the compiler never checks it.** Rename a view
|
|
113
|
+
and the file still compiles; the tile fails at package load. Read the lint (step 6).
|
|
114
|
+
- **No per-parent-row grouping.** There is no parent query to repeat a grid over.
|
|
115
|
+
- **Filtering lives in what the tiles name**, not on the page. That is the shared include's job,
|
|
116
|
+
below.
|
|
117
|
+
|
|
118
|
+
### Also served: `# artifact` on a `query:`
|
|
119
|
+
|
|
120
|
+
One query whose result is the whole page, laid out by `@malloydata/render` from the query's own
|
|
121
|
+
`# dashboard` tag. This is Malloy's rendering feature, the same thing a notebook cell shows, not a
|
|
122
|
+
second way to build a dashboard, and it cannot span sources. Publisher serves it, so you will meet it
|
|
123
|
+
in existing packages, and the layout tags below are shared with it. Do not author a new dashboard
|
|
124
|
+
this way.
|
|
66
125
|
|
|
67
126
|
```malloy
|
|
68
127
|
##! experimental.givens
|
|
@@ -108,25 +167,16 @@ query: overview is order_items -> {
|
|
|
108
167
|
|
|
109
168
|
The `#"` line above the tag is a doc comment, and it is the page's description. If you leave `title=`
|
|
110
169
|
off the artifact tag, it becomes the title instead, so write it as one, not as a sentence about the
|
|
111
|
-
page. **It belongs to
|
|
170
|
+
page. **It belongs to a query, so it only works on the one-query form.** Putting a `#"` above a
|
|
112
171
|
model-level `##` tag fails the whole package load with "Object annotation not connected to any
|
|
113
|
-
object",
|
|
172
|
+
object", so a dashboard has no description as a result.
|
|
114
173
|
|
|
115
|
-
|
|
116
|
-
model-level (`##`) because there is no query of its own to hang a `#` tag on.
|
|
117
|
-
|
|
118
|
-
```malloy
|
|
119
|
-
##! experimental.givens
|
|
120
|
-
## artifact { title="Seasonality" tiles=["scoped_sales -> sales_by_month", "scoped_sales -> sales_by_year", "scoped_sales -> seasonality"] dashboard_columns=3 }
|
|
121
|
-
import { scoped_sales } from './_shared.malloy'
|
|
122
|
-
import { products } from '../storefront.malloy'
|
|
123
|
-
import { CATEGORY, SINCE } from '../givens.malloy'
|
|
124
|
-
```
|
|
174
|
+
### Where the filtering goes
|
|
125
175
|
|
|
126
|
-
A
|
|
176
|
+
A dashboard has no query, so the filtering it applies must live in what it composes: a source that
|
|
127
177
|
already has the givens applied. Put it in an untagged `dashboards/_shared.malloy`, which discovery
|
|
128
|
-
treats as a shared include rather than a dashboard. **It has to apply every given the
|
|
129
|
-
imports**: a given the
|
|
178
|
+
treats as a shared include rather than a dashboard. **It has to apply every given the dashboard
|
|
179
|
+
imports**: a given the dashboard imports but nothing references gets no control, silently, at reload
|
|
130
180
|
200 with no warning. Note `SINCE` is a `date` rather than a `filter<>`, so it compares with `>=`
|
|
131
181
|
rather than `~`. Save the include before you compile the dashboard that imports it, since an importer
|
|
132
182
|
compiled against a sibling that is not on disk fails with an `import-error`.
|
|
@@ -141,42 +191,56 @@ source: scoped_sales is order_items extend {
|
|
|
141
191
|
}
|
|
142
192
|
```
|
|
143
193
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
194
|
+
**`# dashboard { columns=N }` is the one spelling of the grid width**, on both forms, beside the
|
|
195
|
+
artifact tag. Anything else inside the artifact tag is a package warning naming it, which is what you
|
|
196
|
+
will see if you write `dashboard_columns=N`: nothing reads it, and the grid would otherwise fall back
|
|
197
|
+
to the default width in silence.
|
|
148
198
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
lays out from, but **a single query tagged `dashboard_columns` silently loses its whole layout**, and
|
|
152
|
-
the manifest reports the count either way: see "Losing the grid". A composite's tiles also keep their
|
|
153
|
-
own field names on their axes and column headers, and the Layout section's remedy, inlining the view,
|
|
154
|
-
is not open to you here: naming existing views is the whole point of the form. `tiles=` on a
|
|
155
|
-
single-query artifact tag is dropped the same way, silently.
|
|
199
|
+
A tile keeps its view's own field names on axes and column headers. `# label` titles the tile; to label
|
|
200
|
+
what is inside it, label the fields in the view.
|
|
156
201
|
|
|
157
202
|
## Layout: the four tags that make a page line up
|
|
158
203
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
204
|
+
Cards and tiles share one grid, and the same four tags work on both forms: on a `# dashboard` query
|
|
205
|
+
the renderer reads them off each nest, and on a dashboard's `tiles=[…]` Publisher reads them off the
|
|
206
|
+
view each tile names. Copy this recipe and use the same count on every dashboard in the package so
|
|
207
|
+
they read as one product:
|
|
162
208
|
|
|
163
209
|
1. **`columns=12`** on the `# dashboard` tag. Twelve divides by 2, 3, 4 and 6, so a row is even with
|
|
164
210
|
three cards or four.
|
|
165
211
|
2. **A `# colspan` on every card and tile, summing to 12 per row.** Four cards at 3, three at 4, two
|
|
166
212
|
tiles at 6, a full-width table at 12. Omit them and every item falls to a single column, a twelfth
|
|
167
|
-
of the width, which is too narrow for a line chart to draw in at all.
|
|
213
|
+
of the width, which is too narrow for a line chart to draw in at all. A colspan wider than
|
|
214
|
+
`columns` is clamped, and the package warnings say so.
|
|
168
215
|
3. **`# break` on the first tile after the cards.** Otherwise it flows into the columns left beside
|
|
169
216
|
the cards and the next tile wraps. Not needed per row: once a row sums to 12 the next item wraps
|
|
170
217
|
on its own.
|
|
171
|
-
4. **`# label="
|
|
172
|
-
nest, whose column headers are field names too. The heading is otherwise the view's or
|
|
173
|
-
name, and a wide table full of `total_sales` and `order_item_count` is the most visible
|
|
174
|
-
between a rough page and a finished one. A view
|
|
175
|
-
the tile, but its own field names still reach the chart axes and the column headers, so
|
|
176
|
-
if you want those
|
|
218
|
+
4. **`# label="..."` on every nest, tile view, and aggregate**, including the aggregates inside a table
|
|
219
|
+
nest, whose column headers are field names too. The heading is otherwise derived from the view's or
|
|
220
|
+
field's name, and a wide table full of `total_sales` and `order_item_count` is the most visible
|
|
221
|
+
thing between a rough page and a finished one. A view referenced **by name** is the exception: you
|
|
222
|
+
can label the tile, but its own field names still reach the chart axes and the column headers, so
|
|
223
|
+
label the fields in the view if you want those too.
|
|
224
|
+
|
|
225
|
+
On a dashboard, all four go on the view a tile names, which is why a thin re-declaration
|
|
226
|
+
(`view: revenue_trend is sales_by_month`) is the place to put them: the modelled view stays reusable
|
|
227
|
+
and each page decides its own widths. `# subtitle="..."` and `# borderless` go there too and are the
|
|
228
|
+
rest of the set; a tile reads all five exactly as a `# dashboard` nest child does.
|
|
229
|
+
|
|
230
|
+
**Do not forget `columns=` itself.** What you get without it differs by form, and neither is the page
|
|
231
|
+
you drew. On a dashboard it falls back to a narrow default and every colspan is clamped to it, which
|
|
232
|
+
is the usual reason a page you laid out comes out one item per row, and the package warnings name it.
|
|
233
|
+
On a `# dashboard` query there is no grid at all: the cards flow side by side at their natural widths
|
|
234
|
+
and every colspan is ignored. No package warning says so, because the renderer reports it at query
|
|
235
|
+
time. See "Losing the grid".
|
|
177
236
|
|
|
178
237
|
Then the traps:
|
|
179
238
|
|
|
239
|
+
- **A KPI row is authored differently on the two forms.** On a `# dashboard` query a top-level
|
|
240
|
+
`aggregate:` measure IS the card, and nesting a `# big_value` view to get one renders it embedded,
|
|
241
|
+
as full-width bars in a single tile. A dashboard has no top-level aggregates, since a tile is one
|
|
242
|
+
whole result, so there a `# big_value` view IS the KPI row and renders as one. This is the only
|
|
243
|
+
place the two forms need different Malloy for the same picture.
|
|
180
244
|
- **No `# size=fill` on a dashboard tile.** Inside a dashboard it measures against the container the
|
|
181
245
|
whole grid was handed, not the tile, so it yields a chart thousands of pixels tall. Tiles already
|
|
182
246
|
size to their colspan.
|
|
@@ -196,9 +260,9 @@ The last two are upstream renderer behavior, cheap to work around in the model.
|
|
|
196
260
|
|
|
197
261
|
The same tags govern a `# dashboard` **view** run in a notebook cell, since both surfaces render
|
|
198
262
|
through the same code, so a view laid out this way looks the same in a cell as on a dashboard page.
|
|
199
|
-
Height is the one thing the surface decides: a
|
|
200
|
-
|
|
201
|
-
|
|
263
|
+
Height is the one thing the surface decides: a one-query page renders at its natural height, a
|
|
264
|
+
dashboard's tiles are each capped, and in a notebook a chart cell is capped and a table cell hugs its
|
|
265
|
+
rows.
|
|
202
266
|
|
|
203
267
|
## The rules that actually bite
|
|
204
268
|
|
|
@@ -207,7 +271,7 @@ its rows.
|
|
|
207
271
|
collides with an imported `regions` source).
|
|
208
272
|
- **Importing a given is what makes it bindable.** Malloy's given namespace is per-file. A given the
|
|
209
273
|
dashboard file does not import gets no control and cannot be sent to it, even when the `where:`
|
|
210
|
-
that references it lives up an import chain. A
|
|
274
|
+
that references it lives up an import chain. A dashboard must import the givens its tiles use.
|
|
211
275
|
- **A suggest's source or query has to resolve in the dashboard file too.** `suggest { source=products … }`
|
|
212
276
|
means the dashboard imports `products`.
|
|
213
277
|
- **A model-level `##` tag must be on one line.** Wrapping one always breaks it, but how you find
|
|
@@ -318,15 +382,14 @@ either, for a different reason.
|
|
|
318
382
|
|
|
319
383
|
## Losing the grid
|
|
320
384
|
|
|
321
|
-
A
|
|
322
|
-
|
|
385
|
+
A one-query page can come out with its layout wrong in two visibly different ways, and the reload is
|
|
386
|
+
200 and the manifest reports the column count you asked for in both.
|
|
323
387
|
|
|
324
|
-
**Not a dashboard at all: one plain nested table**, every `# colspan` and `# break` dropped
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
is immune because its layout comes from the manifest rather than a re-parse.
|
|
388
|
+
**Not a dashboard at all: one plain nested table**, every `# colspan` and `# break` dropped, because a
|
|
389
|
+
`f'…'` filter literal in a `givens { … }` block shares a line with `# dashboard`. Put `# dashboard` on
|
|
390
|
+
its own line: writing it first on the line does not help, a plain `'Outerwear'` or a bare date is
|
|
391
|
+
fine, and a `tiles=[…]` dashboard is immune because its layout comes from the manifest rather than a
|
|
392
|
+
re-parse.
|
|
330
393
|
|
|
331
394
|
**A dashboard, but nothing lines up**: you wrote `# colspan` without `columns=N`, so the items flow
|
|
332
395
|
side by side at their natural widths instead of aligning to a grid.
|
|
@@ -355,7 +418,9 @@ Package warnings after a reload are the dashboard's test suite. Fix all of them:
|
|
|
355
418
|
- `filters by given "X", which this file does not import, so no control is shown for it`: the trap
|
|
356
419
|
under "Importing a given is what makes it bindable", which the lint now names for you, with the file
|
|
357
420
|
to fix.
|
|
358
|
-
- A tile that does not resolve to a real view
|
|
421
|
+
- A tile that does not resolve to a real view; a non-positive `# dashboard { columns }`; a tile view's
|
|
422
|
+
`# colspan` that is not a positive integer or is wider than the grid; and any property inside the
|
|
423
|
+
artifact tag Publisher does not read, `dashboard_columns=` included.
|
|
359
424
|
|
|
360
425
|
Findings carry a `severity`, but `warn` is the ordinary default and tells you nothing about how bad
|
|
361
426
|
one is. Read the text, not the severity and not the count. One message is worth recognising because
|
|
@@ -401,9 +466,8 @@ the warning list.
|
|
|
401
466
|
- Each control renders as the widget you intended (a select shows options; a slider is a slider),
|
|
402
467
|
and changing one changes the numbers.
|
|
403
468
|
- If you added a `# drill`, you clicked it and landed where you meant to, with the given seeded.
|
|
404
|
-
-
|
|
405
|
-
|
|
406
|
-
than leaving a gap. Nothing is clipped, no tile is thousands of pixels tall, and no legend or card
|
|
469
|
+
- Every card and tile carries a colspan, each row's colspans sum to `columns`, and the rows end flush
|
|
470
|
+
with each other. Nothing is clipped, no tile is thousands of pixels tall, and no legend or card
|
|
407
471
|
label ends in `…`.
|
|
408
472
|
|
|
409
473
|
## Reference
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-debug
|
|
3
3
|
description: Fix Malloy compile errors and understand error messages. Use when encountering errors in .malloy files, user says "fix this error", "malloy error", "compile error", "syntax error", or sees 20+ cascading errors.
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.12
|
|
5
5
|
---
|
|
6
6
|
<!--
|
|
7
7
|
Copyright (c) Credible Data Inc.
|
|
@@ -14,11 +14,12 @@ SPDX-License-Identifier: MIT
|
|
|
14
14
|
|
|
15
15
|
## Get Diagnostics
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Hosts expose errors differently, so take the best path you actually have:
|
|
18
18
|
|
|
19
|
-
**
|
|
19
|
+
1. **An editor-diagnostics tool**, if your host offers one - call it on the file and read the errors straight out.
|
|
20
|
+
2. **Otherwise, compile by running.** Run any query against the source with your query tool and read the error it returns. Every host that can run Malloy can do this, including chat surfaces with no editor.
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
Only ask the user to open the file in an editor when you know they have the model open in one. On a hosted chat surface there is no local checkout to open, and the query path above is the one that works.
|
|
22
23
|
|
|
23
24
|
## Strategy
|
|
24
25
|
|
|
@@ -38,8 +39,10 @@ SPDX-License-Identifier: MIT
|
|
|
38
39
|
| "Aggregate not allowed in where" | Use `having:` instead |
|
|
39
40
|
| 20+ random errors | Backtick reserved word (`` `Date` ``, `` `Hour` ``, `` `number` ``) |
|
|
40
41
|
| `Can't find field 'X' to set access modifier` | An `include {}` sits before the `extend { rename: }`. Rename first, then `include {}` naming the field by its new name (see `skill:malloy-gotchas-modeling` § Field Management) |
|
|
42
|
+
| `IO Error: No files found that match the pattern "data/x.csv"` | Data-file path, not the model. Relative `duckdb.table()` paths resolve against the DuckDB `workingDirectory`; Publisher sets it to the package root, but a relative `workingDirectory` in `malloy-config.json` resolves against the process cwd. Make it absolute (see `skill:malloy-gotchas-modeling` § Relative Data-File Paths). The "not defined" errors under it are cascade, not real |
|
|
41
43
|
| Import path errors | Check paths: `import "orders.malloy"`. All files should be in the same directory (flat layout) |
|
|
42
|
-
| `from()`
|
|
44
|
+
| `unexpected 'from'` | `from()` was removed from the language. Use the query directly: `source: x is q extend {...}`, or `source: x is (q -> {...}) extend {...}` |
|
|
45
|
+
| Query-based source errors | Verify the source query returns the expected columns, check that imported sources are defined |
|
|
43
46
|
| "Cannot redefine 'X'" | Field already exists from query-based source (`-> { group_by, aggregate }`). Remove the dimension, add only NEW derived fields in `extend {}`. Use `include {}` to add `#(doc)` tags to existing fields. |
|
|
44
47
|
|
|
45
48
|
## Gotchas Checklist
|
|
@@ -123,4 +126,4 @@ a / b a / nullif(b, 0)
|
|
|
123
126
|
| "Can't find source X" | Add `import "X.malloy"` at top of file (all files in same directory) |
|
|
124
127
|
| Wrong import path | All `.malloy` files should be in the package root (flat layout). Use `import "orders.malloy"`, not `import "../sources/orders.malloy"` |
|
|
125
128
|
| Circular imports | Source A imports Source B which imports Source A. Restructure to break the cycle |
|
|
126
|
-
|
|
|
129
|
+
| Query-based source "Can't find field" | Verify the source query's GROUP BY and aggregate fields match what you reference in `extend {}` |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-define
|
|
3
3
|
description: Propose a source plan and field definitions for a Malloy semantic model. Covers picking which sources to model and at what grain, then proposing the specific renames, dimensions, and measures per source, every proposal backed by querying the data.
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.12
|
|
5
5
|
---
|
|
6
6
|
<!--
|
|
7
7
|
Copyright (c) Credible Data Inc.
|
|
@@ -160,7 +160,7 @@ The user will:
|
|
|
160
160
|
- **Remove** fields they don't need.
|
|
161
161
|
- **Change** priorities.
|
|
162
162
|
|
|
163
|
-
Once the definitions are confirmed, write them into the `.malloy` model (see your modeling workflow). Use `#(doc)` annotations to document sources and fields, and
|
|
163
|
+
Once the definitions are confirmed, write them into the `.malloy` model (see your modeling workflow). Use `#(doc)` annotations to document sources and fields, and `given:` parameters to declare runtime-filterable dimensions where appropriate. `#(filter)` is deprecated in favour of native Malloy `given:` parameters. Do not add new `#(filter)` annotations; the two exceptions are `required` and `implicit`, which `given:` cannot cover yet. See `skill:malloy-model` § Legacy: Parameterizable Filters. Keep the confirmed definitions in the conversation; there is no separate plan-file store.
|
|
164
164
|
|
|
165
165
|
## Data-driven proposals
|
|
166
166
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-discover
|
|
3
3
|
description: Silent data discovery for Malloy modeling. Used at Step 1 of the modeling workflow. Scans tables, columns, distributions, and relationships without user interaction. The agent builds an internal picture before presenting anything.
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.12
|
|
5
5
|
---
|
|
6
6
|
<!--
|
|
7
7
|
Copyright (c) Credible Data Inc.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-document
|
|
3
3
|
description: 'Add documentation with #(doc) tags to Malloy models so fields and sources are described in plain language. Use when user asks to "add documentation", "add doc tags", "document the model", or wants fields and sources described for natural-language search and discovery. For declaring parameterizable filters with #(filter), see the malloy-model skill. Filters are a runtime/modeling construct (governance, latency, correctness), not a documentation tag.'
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.12
|
|
5
5
|
---
|
|
6
6
|
<!--
|
|
7
7
|
Copyright (c) Credible Data Inc.
|
|
@@ -15,7 +15,7 @@ Add `#(doc)` tags to describe sources and fields in plain language so they are e
|
|
|
15
15
|
| Tag | Purpose | Goes on |
|
|
16
16
|
|-----|---------|---------|
|
|
17
17
|
| `#(doc)` | Plain-language description for natural-language search | source, dimension, measure, view, join |
|
|
18
|
-
| `#(filter)` |
|
|
18
|
+
| `#(filter)` | Deprecated, prefer `given:`. Parameterizable filter (runtime/modeling concern, see `malloy-model`) | source |
|
|
19
19
|
|
|
20
20
|
`#(doc)` is a standard Malloy annotation. It documents a field or source with a human-readable description that downstream tools can surface and search against.
|
|
21
21
|
|
|
@@ -76,9 +76,11 @@ These are governed models: a threshold nobody confirmed is an assumption, and an
|
|
|
76
76
|
|
|
77
77
|
Do not hedge measured facts: `avg_energy is avg(energy)` needs no caveat. Hedge only where a domain expert could reasonably choose differently.
|
|
78
78
|
|
|
79
|
-
## #(filter): see `malloy-model`
|
|
79
|
+
## #(filter): deprecated, see `malloy-model`
|
|
80
80
|
|
|
81
|
-
`#(filter)` is
|
|
81
|
+
`#(filter)` is deprecated in favour of native Malloy `given:` parameters. Do not add new `#(filter)` annotations; the two exceptions are `required` and `implicit`, which `given:` cannot cover yet. See `skill:malloy-model` § Legacy: Parameterizable Filters.
|
|
82
|
+
|
|
83
|
+
`#(filter)` is also a `#(...)`-shaped annotation, but unlike `#(doc)` it's a **runtime/modeling construct**: it shapes governance, query latency, and correctness, not discoverability. The full reference (syntax, filter types, `required` / `implicit` flags, and when each applies) lives in `malloy-model` § Legacy: Parameterizable Filters alongside the other source-authoring constructs, next to the `given:` guidance that replaces it.
|
|
82
84
|
|
|
83
85
|
One rule worth knowing here: filters live on the source, never on the consumer. Ad-hoc reports and notebooks that import a source inherit its filters automatically; they do not (and cannot) declare new ones.
|
|
84
86
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: malloy-getting-started
|
|
3
3
|
description: First steps for using a Malloy Publisher deployment through its MCP tools. Use when connecting to Publisher for the first time, when you do not yet know the available environments, packages, or models, or when a user asks what data they can explore. Covers verifying the server, discovering data with malloy_getContext, and running a first grounded query.
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.12
|
|
5
5
|
---
|
|
6
6
|
<!--
|
|
7
7
|
Copyright (c) Credible Data Inc.
|
|
@@ -29,6 +29,56 @@ Two escape hatches worth knowing:
|
|
|
29
29
|
|
|
30
30
|
When a user is present, do not route around it by calling the REST API with curl. It appears to work, so the user never learns their session is missing the tools, and you lose what they are for: grounded discovery instead of guessed names, `malloy_compile` instead of throwaway queries, and `malloy_reloadPackage` instead of a restart. Say the tools are missing and let the user fix it in five seconds. Running unattended, with nobody who can reconnect you, is different: there the REST API is the supported interface, not a workaround. Discovery, query, compile, and reload all have REST equivalents (`malloy_searchDocs` and `malloy_getContext`'s plain-English ranking do not; read the bundled skills for syntax and ground from model metadata instead); the running server serves the full spec at `http://localhost:4000/api-doc.yaml`, and AGENTS.md carries the endpoint map.
|
|
31
31
|
|
|
32
|
+
## 0.5 Ask whether they also use the CLI or the VS Code extension
|
|
33
|
+
|
|
34
|
+
Publisher is often not the only thing reading the model. The Malloy CLI (`malloy-cli`) and the VS
|
|
35
|
+
Code extension compile the same files, and they do **not** get their connections from
|
|
36
|
+
`publisher.config.json` - they read `malloy-config.json`, found by walking up from the file being
|
|
37
|
+
compiled. So a package that Publisher serves correctly can fail to compile in the editor, on the
|
|
38
|
+
same machine, from the same files.
|
|
39
|
+
|
|
40
|
+
Ask before the user finds out the hard way:
|
|
41
|
+
|
|
42
|
+
> Are you also using the Malloy CLI or the VS Code extension on this package?
|
|
43
|
+
|
|
44
|
+
If yes, and the package reads **local data files**, it needs a `malloy-config.json`. Publisher
|
|
45
|
+
resolves a relative `duckdb.table('data/x.csv')` against the package root on its own, so nothing is
|
|
46
|
+
configured for it; the other two hosts resolve it against the DuckDB connection's
|
|
47
|
+
`workingDirectory`, which has to be set.
|
|
48
|
+
|
|
49
|
+
**Make that path absolute.** A relative `workingDirectory` is resolved against the process's current
|
|
50
|
+
directory, not the config file's directory and not the VS Code workspace root, so the same config
|
|
51
|
+
compiles from one directory and fails from another:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
// malloy-config.json, beside the model
|
|
55
|
+
{
|
|
56
|
+
"connections": {
|
|
57
|
+
"duckdb": {
|
|
58
|
+
"is": "duckdb",
|
|
59
|
+
"workingDirectory": "/abs/path/to/package",
|
|
60
|
+
"securityPolicy": "none"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Point it at the directory the model's table paths are written relative to - the one holding `data/`.
|
|
67
|
+
Leave the model's own paths relative so Publisher still serves it; only the config carries the
|
|
68
|
+
absolute path. When this is wrong the editor reports `IO Error: No files found that match the
|
|
69
|
+
pattern "data/x.csv"` on the `source:` line, followed by a "not defined" error for every field of
|
|
70
|
+
that source; those are cascade, not real. The `malloy-gotchas-modeling` skill covers the mechanism
|
|
71
|
+
under § Relative Data-File Paths.
|
|
72
|
+
|
|
73
|
+
**Remote Credible connections are a different case.** With the Credible extension running and signed
|
|
74
|
+
in, the data is reached through a `publisher` proxy connection - the connection type that forwards
|
|
75
|
+
SQL to a remote Publisher dataplane, and the same type the CLI and the VS Code extensions use - and
|
|
76
|
+
the extension supplies it, so there is nothing to hand-write and no `workingDirectory` involved.
|
|
77
|
+
`workingDirectory` only ever matters for local files that DuckDB opens itself. Worth knowing: those
|
|
78
|
+
access tokens are user-scoped and short-lived, and nothing refreshes them mid-session, so queries
|
|
79
|
+
that start failing auth after a long session mean the token expired, not that the model broke. See
|
|
80
|
+
`docs/connections.md` § Publisher proxy connections.
|
|
81
|
+
|
|
32
82
|
## 1. Discover what exists (never guess names)
|
|
33
83
|
|
|
34
84
|
`malloy_getContext` is progressive. Call it with as much as you know:
|