@graphit/cli 0.1.16 → 0.1.18

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.
@@ -111,6 +111,24 @@ SELECT UNNEST(generate_series(
111
111
 
112
112
  The outer SELECT can ONLY reference columns the subquery exposes (its aliases). Base-table columns aggregated away in the subquery do NOT exist at the outer level.
113
113
 
114
+ ## Cache-Friendly SQL (Canvas Resolve)
115
+
116
+ Canvas `graphit.resolve()` queries that follow these shapes serve from a semantic cache in ~10ms on filter changes instead of a full DuckDB recompute (5-37s on wide data sources). Write resolve SQL in this style by default.
117
+
118
+ **Shape rules:**
119
+ - Single table (no JOIN/UNION)
120
+ - WHERE as flat AND of `column = literal`, `column IN (...)`, `column BETWEEN ... AND ...` conjuncts
121
+ - Bare aggregates only: `SUM(col)`, `COUNT(*)`, `MIN(col)`, `MAX(col)` - no wrapping functions (`ROUND(SUM(x))`), no aggregate arithmetic (`SUM(a)/NULLIF(SUM(b),0)`), no `AVG` (v2)
122
+ - Literal dates (`>= '2026-01-01'`), never `CURRENT_DATE` expressions
123
+ - GROUP BY column names or ordinals; ORDER BY / LIMIT allowed (outer only)
124
+ - CTEs are fine when the CTE body follows the same rules
125
+
126
+ **Shapes that skip the cache** (fall back to normal execution, still correct):
127
+ - `COUNT(DISTINCT x)`, window functions, HAVING, QUALIFY
128
+ - OR / NOT in WHERE
129
+ - Ratio metrics (`SUM(a)/NULLIF(SUM(b),0)`) - compute client-side or use two resolves
130
+ - `CURRENT_DATE`-relative predicates
131
+
114
132
  ## Data Source Routing
115
133
 
116
134
  | Situation | Command | Speed |
@@ -119,3 +137,91 @@ The outer SELECT can ONLY reference columns the subquery exposes (its aliases).
119
137
  | No data source | `graphit query "SQL" --warehouse --connection <id>` | ~10s, Snowflake |
120
138
 
121
139
  Always prefer cached data sources. Check with `graphit ds list`. If no data source covers the table, suggest creating one for future speed.
140
+
141
+ ## Presenting Query Results
142
+
143
+ After every `graphit query`, present results grounded in the KB. Always show which KB assets were used - this is what makes governed queries valuable.
144
+
145
+ **When using KB reference syntax** (`{{metric:X}}`, `{{dim:X}}`), show all five sections:
146
+
147
+ ~~~
148
+ **KB Assets:** dimension **CAMPAIGN_CATEGORY**, metric **TOTAL_INSTALLS**, metric **CPI**, table **MARKETING_UA_DS**
149
+
150
+ **Query:**
151
+ ```sql
152
+ SELECT
153
+ {{dim:CAMPAIGN_CATEGORY}} AS category,
154
+ {{metric:TOTAL_INSTALLS}} AS installs,
155
+ {{metric:CPI}} AS cpi
156
+ FROM MARKETING_UA_DS
157
+ WHERE ACTIVITY_TIME >= '2026-01-01'
158
+ GROUP BY {{dim:CAMPAIGN_CATEGORY}}
159
+ ORDER BY installs DESC
160
+ ```
161
+
162
+ **Resolved SQL:**
163
+ ```sql
164
+ SELECT
165
+ CASE WHEN IS_RETARGETING THEN 'Retargeting'
166
+ WHEN IS_CTV THEN 'Connected TV'
167
+ ELSE 'User Acquisition' END AS category,
168
+ SUM(INSTALLS) AS installs,
169
+ SUM(APPSFLYER_COST) / NULLIF(SUM(INSTALLS), 0) AS cpi
170
+ FROM MARKETING_UA_DS
171
+ WHERE ACTIVITY_TIME >= '2026-01-01'
172
+ GROUP BY 1
173
+ ORDER BY installs DESC
174
+ ```
175
+
176
+ **Results** (3 rows via **ds_abc123**):
177
+
178
+ | Category | Installs | CPI |
179
+ |---|---:|---:|
180
+ | User Acquisition | 80,605 | $0.79 |
181
+ | Retargeting | 12,300 | $1.24 |
182
+ | Connected TV | 3,100 | $2.80 |
183
+
184
+ **Governance:** governed - 3 KB refs, 2 rules enforced (**EXCLUDE_ORGANIC**, **MIN_SPEND**). Max rows: 1,000.
185
+ ~~~
186
+
187
+ **When using inline SQL** (no `{{metric:X}}`), show query + results + governance:
188
+
189
+ ~~~
190
+ **Query:**
191
+ ```sql
192
+ SELECT media_source, SUM(spend) AS spend FROM MARKETING_UA_DS GROUP BY 1
193
+ ```
194
+
195
+ **Results** (6 rows via **ds_abc123**):
196
+
197
+ | Media Source | Spend |
198
+ |---|---:|
199
+ | Facebook | $42,100 |
200
+ | Google UAC | $38,500 |
201
+
202
+ **Governance:** ad-hoc - 0 KB refs. Consider using `{{metric:TOTAL_SPEND}}` for governed tier.
203
+ ~~~
204
+
205
+ For ad-hoc queries, suggest the KB reference equivalent when one exists. This nudges users toward governed queries.
206
+
207
+ **Always use `--verbose`** to get the resolved SQL. If the user didn't pass it, re-run with `--verbose` so you can show both the reference query and the expanded SQL.
208
+
209
+ Zero rows: explain what you checked and hypothesize why (wrong date range, filter too strict, table empty).
210
+
211
+ ## Presenting Data Source Results
212
+
213
+ After `graphit ds list`:
214
+
215
+ ~~~
216
+ **3 data sources:**
217
+
218
+ | Name | ID | Rows | Status | Governed |
219
+ |---|---|---:|---|---|
220
+ | **MARKETING_UA_DS** | ds_abc123 | 1,247,832 | active | yes |
221
+ | **PLAYER_QUALITY** | ds_def456 | 892,104 | active | no |
222
+ | **REVENUE_EVENTS** | ds_ghi789 | 3,412,006 | stale | yes |
223
+
224
+ Using **MARKETING_UA_DS** (ds_abc123) which covers spend, installs, and ROAS columns.
225
+ ~~~
226
+
227
+ End with a recommendation of which DS to use, or note if none covers the needed table.