@graphit/cli 0.1.36 → 0.1.39

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.
@@ -1,4 +1,5 @@
1
1
  ---
2
+ skill_version: "0.1.39"
2
3
  alwaysApply: false
3
4
  description: "Build Graphit HTML dashboards with KB-aware queries, entity wrapping, and cached data sources"
4
5
  globs: []
@@ -8,6 +9,24 @@ globs: []
8
9
 
9
10
  Build custom HTML dashboards from real data using the Graphit CLI.
10
11
 
12
+ ## Session Start
13
+
14
+ Run `graphit plugin status` at the start of every Graphit session and whenever the user asks about Graphit updates, plugin health, or stale instructions. This command is the source of truth for CLI, plugin-bundle, skill, ref, hook, and legacy copied-file version health; do not invent a manual version check.
15
+ If it reports action needed, tell the user the exact remediation it prints before proceeding.
16
+ If `graphit plugin status` fails with "command not found" or "unknown command", the CLI is too old. Tell the user to update immediately: `npm update -g @graphit/cli`. Do not proceed with an outdated CLI.
17
+
18
+ ## Install / Update Model
19
+
20
+ The Graphit plugin bundle is the default and source of truth for Claude Code and Codex. It contains the CLI, skills, refs, hooks, status script, and manifests. Claude Code/Codex users should update Graphit through their assistant plugin manager, not by running copied-skill setup.
21
+
22
+ `graphit setup` is only for legacy/fallback copied-file installs, mainly Cursor or environments without plugin support. If `graphit plugin status` reports Claude Code/Codex copied snapshots, tell the user to remove them with `graphit setup --remove-legacy-copies` after confirming the plugin is installed. Use `graphit setup --legacy-copy` only when the plugin path is unavailable.
23
+
24
+ ## CLI Health Gate
25
+
26
+ ALWAYS run `graphit plugin status` before diagnosing, retrying, or inventing a workaround when Graphit CLI behavior looks wrong. This includes unknown commands, unrecognized flags, missing commands described in this rule, stale-looking output, copied-skill warnings, non-zero exits with unclear messages, or the user saying Graphit/CLI/plugin/skill is not working.
27
+ If `graphit plugin status` reports action needed, stop and tell the user the exact remediation first. Do not continue with stale instructions unless the user explicitly asks you to proceed anyway.
28
+ Do NOT suggest updating for normal operational failures (expired auth, bad SQL, entity not found).
29
+
11
30
  ## HARD CONSTRAINTS (violating these produces a broken dashboard)
12
31
 
13
32
  ### 1. ZERO external resources
@@ -18,14 +37,17 @@ Your HTML must NEVER contain:
18
37
  - `<img src="https://...">` - no external images
19
38
 
20
39
  If you use ANY `src=` or `href=` pointing to a URL, the dashboard will be blank.
21
- All CSS in `<style>`, all JS in `<script>`, all fonts from system stack. The iframe has a built-in runtime (`graphit.chart`, `graphit.table`, `graphit.kpi`) for standard visualizations - use it instead of importing libraries.
40
+ All CSS in `<style>`, all JS in `<script>`, all fonts from system stack. The iframe has a built-in runtime (`graphit.chart`, `graphit.table`, `graphit.kpi`, `graphit.presentation`) for standard visualizations - use it instead of importing libraries.
22
41
 
23
42
  ### 2. ALWAYS query through data sources
24
43
  NEVER query the warehouse directly when a cached data source covers the table. Data sources return in ~100ms. Warehouse queries take ~10s and cost Snowflake credits.
25
44
 
26
- Run `graphit ds list` FIRST. If a DS covers your table, use `graphit query "SQL" --ds <id>`. Only use `--warehouse` if NO data source exists and the user approves.
45
+ **Before writing ANY query:**
46
+ 1. Run `graphit ds list` to see what data sources exist
47
+ 2. If a DS covers your table, use `graphit query "SQL" --ds <id>` (DuckDB syntax)
48
+ 3. Only use `graphit query "SQL" --warehouse --connection <id>` if NO data source exists and the user approves
27
49
 
28
- **Use the DS name in SQL, not the source table name.** Write `FROM MARKETING_UA_DS`, not `FROM MARKETING_UA`. The DS name is what users see in the platform. DuckDB resolves both, but the DS name keeps SQL consistent with the UI.
50
+ **Use the data source name in SQL** (e.g. `FROM MARKETING_UA_DS`), not the raw source table. The DS is a KB table - governance rules target it directly, and users recognize DS names from the platform.
29
51
 
30
52
  ### 3. EVERY element must have entity wrapping
31
53
  Without `data-graphit-*` attributes, elements are invisible to the platform. Every chart, KPI card, table, and text section needs ALL FOUR attributes:
@@ -48,7 +70,7 @@ Without `data-graphit-*` attributes, elements are invisible to the platform. Eve
48
70
 
49
71
  KB asset references are derived automatically from `{{metric:X}}` / `{{dim:X}}` templates in your SQL.
50
72
 
51
- **SQL must be complete and executable.** The platform runs `data-graphit-sql` against the data source when a user opens the entity's details panel. Write the full query from the `graphit.resolve()` call - never abbreviate, truncate, or use placeholders (`FROM ...`, `SELECT ...`, ellipsis). It MUST use the real DS table name and only columns that exist in the DS - never invented summary columns, CTE aliases, JS variable names, or prose. If the chart's resolve call uses a CTE, put the full WITH query. If JS builds SQL dynamically, store one representative executable variant (e.g. the default date range).
73
+ **SQL must be complete and executable.** The platform runs `data-graphit-sql` against the data source when a user opens the entity's details panel. Write the full query from the `graphit.resolve()` call - never abbreviate, truncate, or use placeholders. It MUST use the real DS table name and only columns that exist in the DS.
52
74
 
53
75
  **Label = visible title.** The `data-graphit-label` MUST match the card's visible heading exactly.
54
76
 
@@ -65,13 +87,63 @@ NEVER embed query results as static JS variables. The dashboard iframe provides
65
87
  **Wrong:** Embedding results as `const data = [{...}, ...]` in the HTML.
66
88
  **Right:** Using `graphit.resolve({sql, dataSourceId})` in a `<script>` block so data refreshes automatically.
67
89
 
90
+ ### 6. NEVER build a dashboard on ad-hoc SQL when KB assets are missing
91
+ The KB-readiness gate in Workflow Step 4 is BLOCKING. When you check the KB and find it is missing metrics or dimensions the dashboard needs, you MUST create them before writing any HTML. Do not offer to skip. Do not ask "should I use ad-hoc SQL instead?" Do not frame it as the user's choice. The gate exists because ad-hoc SQL bypasses governance, breaks provenance, and produces untrustworthy graphs. The only question to ask is "here's my KB plan - approve?" not "should I follow my own instructions?"
92
+
93
+ **Wrong:** "The KB has no metrics defined for caching performance. Should I build the dashboard with ad-hoc SQL or create KB assets first? Your call."
94
+ **Right:** "The KB is missing 3 metrics this dashboard needs: RESULT_CACHE_HIT_RATE, DS_QUERY_LATENCY, QUERY_FAILURE_RATE. Creating them now - here's the plan: [tree]. Approve?"
95
+
96
+ ---
97
+
98
+ ## How to Work (governs both workflows below)
99
+
100
+ You are a colleague building WITH the user, not a batch job that explores in silence and returns a finished product. Two habits make the difference: **short iterations** and **narration**.
101
+
102
+ **Short iterations.** Do one thing, show it, let the user react, then do the next: explore the KB and report what you found; validate one query and show the rows; build one section and show it. Each small step is a cheap chance for the user to redirect before you have built in the wrong direction.
103
+
104
+ **Always narrate.** The user cannot see your command output: the KB you listed, the SQL you ran, the rows that came back are invisible unless you surface them. After each step, say what you found, what it means, and what you are about to do next. Exception: if the user says "just build it" or "go", drop the commentary and work straight through.
105
+
106
+ **Workflow gates are not optional.** When a step says BLOCKING or STOP, execute it. Do not offer to skip, do not say "your call", do not reframe it as optional. The KB-readiness gate (Step 4) is the most common one: if the KB is missing metrics or dimensions the dashboard needs, create them before writing HTML. The only question to ask is "here's my KB plan - approve?" not "should I follow the plan?"
107
+
108
+ - **Wrong:** "The KB is empty. Should I skip KB creation and use ad-hoc SQL, or build assets first?"
109
+ - **Right:** "The KB is empty. Here are the 7 metrics and 4 dimensions this dashboard needs: [tree]. Approve so I can create them?"
110
+
111
+ The difference in practice:
112
+ - **Weak (solo):** silently list the KB, silently run several queries, then save a complete dashboard and announce "Done."
113
+ - **Strong (collaborative):** "Found a **Marketing UA** data source with `{{metric:CPI}}` and `{{metric:ROAS}}` already defined. Starting with a spend-vs-installs trend - querying now." Then, after showing rows: "Spend tracks installs except in March. Want that as the first graph, or should I look at ROAS first?"
114
+
115
+ ---
116
+
117
+ ## Workflow: Dashboard Build
118
+
119
+ 1. **Understand.** Ask what the dashboard should answer. Don't query until you know the goal - one clarifying question beats a wrong dashboard.
120
+ 2. **Scope to the domain, then work down: domain -> data source -> assets.** Start narrow, not broad. Ask the user which business domain this dashboard is about (or infer it and confirm). Then `graphit kb explore domain <NAME>` to see that domain's data sources and the metrics and dimensions defined on them. Reach for broad `graphit kb search` only as a fallback. Tell the user what you found - the data source, the metrics and dimensions you'll use, and the graphs you plan - before building.
121
+ 3. **Understand the business question.** Before touching SQL, apply the domain lenses to classify the user's goal. Match column names and user intent against the five lens detection signals (Marketing, Finance, Product/Growth, Operational, Sales). Once the lens is identified: check its canonical metrics and clarification questions. Ask at most ONE clarifying question using collaborative phrasing - state your assumption and offer to redirect. Map the user's goal to specific metric and dimension concepts the dashboard needs - name them. Show the user the concept list, then check it against the KB.
122
+ 4. **KB-readiness gate (BLOCKING).** Check the KB against the specific concepts from step 3 - not a vague "does the KB have stuff?" but "does the KB have the ROAS, CPI, and LTV:CAC that this marketing dashboard needs?" Show a compact gap table: which concepts exist (with formula) and which are missing. If covered, proceed to step 5. If missing key assets, STOP - do not build on raw ad-hoc SQL. Propose creating the assets, route to KB Build workflow first, return here after.
123
+ 5. **Pick the data source, and handle gaps.** Use the cached data source in that domain (~100ms); use its name in SQL (`FROM MARKETING_UA_DS`). If something is missing, look for relationships (`graphit kb list relationships`) before proposing a new data source.
124
+ 6. **Validate each query, and show the result.** Write SQL with `{{metric:NAME}}` / `{{dim:NAME}}` reference syntax, run with `--verbose`, and for EVERY query show the user: the reference-syntax query, a small markdown table of rows, the row count, and the trust tier. If zero rows or nulls, diagnose.
125
+ 7. **Get approval, then build.** Once the user is happy with data and plan, assemble the HTML: `graphit.resolve()` for live data, `graphit.chart/table/kpi` for rendering, every entity wrapped, all CSS in `<style>`, all JS in `<script>`. For large dashboards, add entities incrementally.
126
+ 8. **Save - prefer entity updates - then hand off.** New dashboard: `graphit dashboard update-html <id> --file <path>`. Existing: prefer `graphit dashboard update-entity <id> <entity_id>`. If `entity_sql_warnings` appear, fix and re-save. Give the user the dashboard URL.
127
+
128
+ ## Workflow: KB Build / Onboarding
129
+
130
+ When the user wants to build or populate their KB from files, schemas, or scratch. Consult companion rules: graphit-kb-graph-structure (graph model), graphit-kb-traversal (tool selection), graphit-kb-actions (CLI commands), graphit-kb-awareness (when to propose assets), graphit-parameterized-metrics (template metrics), graphit-data-sources (shaping sources for speed).
131
+
132
+ 1. **Audit current KB state FIRST.** `graphit kb list domains`, then `graphit kb explore domain <NAME>` for each (returns full tree in one call). Add `graphit kb list synonyms` and `graphit kb list relationships` for globals. Present tree summary.
133
+ 2. **Analyze input.** Read the user's files/schema. Classify every concept by asset type (see graphit-kb-explanation for definitions, graphit-kb-awareness for signals).
134
+ 3. **Present a tree plan** showing Domain > Table > Topic > Asset hierarchy. Mark existing assets with (exists), new ones with **NEW**. Include global items (synonyms, relationships) at the bottom. Propose parameterized templates for variant metrics (D7/D30/D90).
135
+ 4. **Wait for approval.** Do not create anything until confirmed.
136
+ 5. **Execute top-down.** Create in order: domains, topics, metrics (with --topics), dimensions, rules, synonyms, relationships, then attachments (domain->table, secondary_tables). Each create validates against real data and returns sample results; if validation fails (422), fix the formula before retrying. Use `--skip-validate` for batch speed.
137
+ 6. **After each metric/dimension/rule create**, present the `validation` section: show the sample query, render sample data as a table, surface warnings. If validation was skipped, say why. If it failed (422), show the error and fix.
138
+ 7. **Verify.** Re-traverse with `graphit kb explore domain <NAME>`, confirm counts match plan.
139
+
68
140
  ---
69
141
 
70
142
  ## Presenting Results to the User
71
143
 
72
144
  You are the rendering layer - format and present every CLI result using markdown. Never silently consume output.
73
145
 
74
- **Formatting fundamentals:** Bold every KB asset/table/DS name (**CPI**, **MARKETING_UA_DS**). Markdown tables for tabular data. Code blocks (```sql) for every SQL query. Format numbers: commas (12,400), $ for currency, % for rates. Narrate between steps.
146
+ **Formatting fundamentals:** Bold every KB asset/table/DS name (**CPI**, **MARKETING_UA_DS**). Markdown tables for tabular data. Code blocks (```sql) for every SQL query. Format numbers (commas, $, %). Narrate between steps.
75
147
 
76
148
  **After `graphit query`** - ground in KB, show five sections:
77
149
  1. **KB Assets:** bold names of all referenced metrics/dimensions/tables
@@ -81,49 +153,91 @@ You are the rendering layer - format and present every CLI result using markdown
81
153
  5. **Governance:** tier, KB refs, rules enforced (**bold names**)
82
154
  - For ad-hoc queries: show query + results + governance, suggest KB reference equivalent
83
155
 
84
- **After `graphit kb list`** - count summary + table with bold names:
85
- - `**12 metrics** across 3 tables:` then table with **bold name**, table, calculation, params
86
- - Footer summarizing parameterized vs pre-baked
87
-
88
- **After `graphit kb get`** - entity heading + key-value table:
89
- - `### **CPI** (metric, verified)` with description in italics
90
- - Key-value table: Table, Calculation, Parameters, Topics, Dimensions
91
-
156
+ **After `graphit kb list`** - count summary + table with bold names
157
+ **After `graphit kb get`** - entity heading + key-value table
92
158
  **After `graphit kb search`** - result count + table with type column
93
159
  **After `graphit kb explore`** - tree structure: Asset > Tables > Dimensions > Rules
94
160
  **After `graphit ds list`** - table with Name, ID, Rows, Status, Governed + recommend which DS to use
95
- **After `graphit ds create`** - shows creation progress (materializing -> scanning schema -> verification link). User must verify on the platform before the DS is usable in KB.
96
- **After `graphit ds verify <id>`** - scans schema (if not already scanned) and prints verification link. Use for existing unverified data sources.
97
- **After `graphit ds refresh --all`** - live status table showing each DS name, status (refreshing/ready/error), and row count. Suggest `--skip-empty` if many 0-row sources exist.
98
- **After `graphit governance status`** - mode + conformance table (Governed/Ad-hoc/Blocked with counts and %)
161
+ **After `graphit ds create`** - shows creation progress (materializing -> scanning schema -> verification link)
162
+ **After `graphit ds verify <id>`** - scans schema and prints verification link
163
+ **After `graphit ds refresh --all`** - live status table showing each DS name, status, row count
164
+ **After `graphit governance status`** - mode + conformance table
99
165
  **After errors** - bold error message + actionable fix suggestion
100
166
 
101
167
  **Never:** run queries silently, present raw JSON, skip governance footer, omit SQL code blocks, show tables without bold asset names.
102
168
 
103
169
  ---
104
170
 
105
- ## Workflow: Dashboard Build
106
-
107
- 1. **Ask the user** what dashboard they want.
108
- 2. **Explore KB** to understand available metrics, dimensions, tables, and rules.
109
- 3. **Find a data source** (`graphit ds list`) - prefer cached data sources over live warehouse.
110
- 4. **Query data to validate** - run queries via the CLI to verify SQL and preview results.
111
- 5. **Build HTML** - write `graphit.resolve()` calls for live data + `graphit.chart/table/kpi` for rendering. All CSS in `<style>`, all JS in `<script>`.
112
- 6. **Save** with `graphit dashboard update-html <id> --file <path>`. If the response contains `entity_sql_warnings`, an entity's `data-graphit-sql` is missing, matches no data source, or fails against the DS schema - fix the flagged entities and save again before finishing.
113
- 7. Give the user the dashboard URL.
114
- 8. **Export** with `graphit dashboard export <id> --format pdf`. Presentations export as multi-page PDF automatically. For custom multi-page layouts, add `data-graphit-page="N"` (0-indexed) to each section.
115
-
116
- ## Workflow: KB Build / Onboarding
117
-
118
- When the user wants to build or populate their KB from files, schemas, or scratch. Consult companion rules: graphit-kb-graph-structure (graph model), graphit-kb-traversal (tool selection), graphit-kb-actions (CLI commands), graphit-kb-awareness (when to propose assets), graphit-parameterized-metrics (template metrics), graphit-data-sources (shaping sources for speed: pre-aggregate to grain, narrow columns, keep high-cardinality dimensions out of the base).
171
+ ## Commands
172
+
173
+ | Command | Description |
174
+ |---------|-------------|
175
+ | `graphit auth login` | Authenticate with Graphit |
176
+ | `graphit auth status` | Show current auth status |
177
+ | `graphit auth logout` | Clear stored credentials |
178
+ | `graphit plugin status` | Check plugin bundle, CLI, skill, refs, hooks, copied legacy files, and update health |
179
+ | `graphit setup` | Legacy copied-file fallback for Cursor/non-plugin environments |
180
+ | `graphit setup --remove-legacy-copies` | Remove old Claude Code/Codex copied snapshots so the plugin bundle is source of truth |
181
+ | `graphit kb list <type>` | List entities: metric, dimension, table, rule, domain, synonym, template, relationship, topic |
182
+ | `graphit kb get <type> <name>` | Full entity details by name |
183
+ | `graphit kb search <query>` | Search across all KB types (optional `--type` filter) |
184
+ | `graphit kb explore metric <name>` | Metric -> tables -> dimensions graph |
185
+ | `graphit kb explore domain <name>` | Domain -> tables -> assets full tree (preferred starting point) |
186
+ | `graphit kb create metric --name X --sql "..." --table T` | Create a metric (optional `--default-dimensions "D1,D2"`). Validates against real data; blocks on failure (422). Use `--skip-validate` to bypass. |
187
+ | `graphit kb create dimension --name X --expr "..." --table T` | Create a dimension (type auto-inferred; override with `--type` / `--output-type`). Validates; shows cardinality + NULL rate. |
188
+ | `graphit kb create rule --name X --sql "..." --table T` | Create a rule. Validates as WHERE clause; warns if zero rows match. |
189
+ | `graphit kb create synonym --term X --canonical Y --type metric` | Create a synonym (type: metric, column, table) |
190
+ | `graphit kb create domain --name X` | Create a domain (optional `--color "#hex"`) |
191
+ | `graphit kb create relationship --name X --primary-table T --primary-column C --related-table T2 --related-column C2` | Create a JOIN relationship |
192
+ | `graphit kb create topic --name X` | Create a topic (business-concept tag) |
193
+ | `graphit kb create template --name X --file template.html` | Save a reusable chart template (--file or --render-code) |
194
+ | `graphit kb update metric NAME --topics "A,B"` | Attach topics to a metric (also works on dimension, rule) |
195
+ | `graphit kb update metric NAME --default-dimensions "D1,D2"` | Set default grouping dimensions for a metric |
196
+ | `graphit kb update metric NAME --secondary-tables "T1,T2"` | Reference metric onto additional tables (also dimension, rule) |
197
+ | `graphit kb update metric NAME --parameters '<json>'` | Set parameterized metric template (JSON array, or `--parameters-file`) |
198
+ | `graphit kb update table NAME --domain DOMAIN` | Assign domain to table (cascades to all assets on table) |
199
+ | `graphit kb update domain NAME --color "#hex"` | Update domain color |
200
+ | `graphit kb update synonym TERM --canonical Y` | Update synonym target |
201
+ | `graphit kb update relationship NAME --primary-column C` | Update relationship columns |
202
+ | `graphit kb update topic NAME --description "..."` | Update topic description |
203
+ | `graphit kb update template NAME --file template.html` | Update template render code |
204
+ | `graphit kb update <type> <name> --description "..."` | Update description (all types) |
205
+ | `graphit kb delete <type> <name> --yes` | Delete any entity (all types supported) |
206
+ | `graphit ds list` | List cached data sources (use these for fast queries) |
207
+ | `graphit ds create --name "..." --sql "..."` | Create DS, poll until ready, auto-scan schema, print verification link |
208
+ | `graphit ds create --name "..." --sql "..." --skip-scan` | Create DS without auto-scan |
209
+ | `graphit ds verify <id>` | Scan schema and print verification link for an unverified DS |
210
+ | `graphit ds refresh --all` | Refresh all data sources, wait for completion with live status |
211
+ | `graphit ds refresh --all --skip-empty` | Refresh non-empty data sources only |
212
+ | `graphit ds refresh --all --no-wait` | Trigger all refreshes without waiting |
213
+ | `graphit ds refresh <id> [id2...]` | Refresh one or more data sources by ID |
214
+ | `graphit ds update <id> --governed-mode on\|off` | Enable/disable governed mode on a data source |
215
+ | `graphit ds update <id> --max-rows N` | Set max rows cap on a data source |
216
+ | `graphit query "<sql>" --ds <id>` | Query cached data source (~100ms) |
217
+ | `graphit query "<sql>" --ds <id> --override-rules RULE1 RULE2` | Query with governance rule overrides |
218
+ | `graphit query "<sql>" --ds <id> --verbose` | Show expanded SQL and trust tier |
219
+ | `graphit query "<sql>" --warehouse --connection <id>` | Query live Snowflake (~10s) |
220
+ | `graphit governance status` | Show governance mode and conformance stats |
221
+ | `graphit governance set <mode>` | Set governance mode (observe/warn/strict) |
222
+ | `graphit governance audit` | View recent governance audit events |
223
+ | `graphit dashboard create --name "..."` | Create dashboard (returns ID) |
224
+ | `graphit dashboard get-html <id>` | Get current HTML content of a dashboard |
225
+ | `graphit dashboard update-html <id> --file <path>` | Upload HTML to dashboard (full page replace) |
226
+ | `graphit dashboard update-entity <id> <entity_id> --file <path>` | Update a single entity's inner HTML (optional `--title`, `--stdin`) |
227
+ | `graphit dashboard list` | List dashboards with sharing metadata (permission, visibility, teams, is_locked) |
228
+ | `graphit dashboard list --view mine` | Only dashboards you own |
229
+ | `graphit dashboard list --view shared` | Only dashboards shared with you |
230
+ | `graphit dashboard list --team <id>` | Only dashboards shared with a specific team |
231
+ | `graphit team list` | List teams you belong to (org admins see all) |
232
+ | `graphit dashboard export <id>` | Export as PNG (default) or PDF (`--format pdf`, `--output <path>`). Presentations auto-export as multi-page PDF. Custom multi-page: `data-graphit-page="N"` (0-indexed). |
233
+ | `graphit metadata schemas --connection <id>` | List Snowflake schemas |
234
+ | `graphit metadata tables --schema <name> --connection <id>` | List tables in a Snowflake schema |
235
+ | `graphit connector list` | List active connections |
236
+ | `graphit connector add snowflake-keypair --account X --user Y --key <path> --warehouse W` | Add Snowflake keypair connection (admin only). OAuth and GitHub connections are configured via the web app. |
237
+ | `graphit connector test <id>` | Test a connection |
238
+ | `graphit connector remove <id> --yes` | Remove a connection (admin only) |
119
239
 
120
- 1. **Audit current KB state FIRST.** Traverse, don't just list: `graphit kb list domains`, then `graphit kb explore domain <NAME>` for each (returns full tree in one call). Add `graphit kb list synonyms` and `graphit kb list relationships` for globals. Present tree summary.
121
- 2. **Analyze input.** Read the user's files/schema. Classify every concept by asset type (see graphit-kb-explanation for definitions, graphit-kb-awareness for signals).
122
- 3. **Present a tree plan** showing Domain > Table > Topic > Asset hierarchy. Mark existing assets with (exists), new ones with **NEW**. Include global items (synonyms, relationships) at the bottom. Propose parameterized templates for variant metrics (D7/D30/D90).
123
- 4. **Wait for approval.** Do not create anything until confirmed.
124
- 5. **Execute top-down.** Create in order: domains, topics, metrics (with --topics), dimensions, rules, synonyms, relationships, then attachments (domain->table, secondary_tables). Each create validates the formula against real data and returns sample results; if validation fails (422), fix the formula before retrying. Use `--skip-validate` for batch speed.
125
- 6. **After each metric/dimension/rule create**, present the `validation` section to the user: show the sample query, render the sample data as a table, and surface any warnings. For metrics show the computed values, for dimensions show cardinality (top values + counts), for rules show matching row count. If validation was skipped, say why. If it failed (422), show the error and fix the formula before retrying.
126
- 7. **Verify.** Re-traverse with `graphit kb explore domain <NAME>`, confirm counts match plan.
240
+ ---
127
241
 
128
242
  ## Query Governance and Reference Syntax
129
243
 
@@ -146,6 +260,8 @@ graphit ds update <id> --governed-mode on # enable governance on DS
146
260
 
147
261
  Reference syntax in `graphit.resolve()` calls works the same way - server expands at query time. Trust tiers: **governed** (KB refs), **verified** (matches KB), **ad-hoc** (inline). Strict mode blocks ad-hoc on governed DSes.
148
262
 
263
+ ---
264
+
149
265
  ## graphit.resolve() - Live Data API
150
266
 
151
267
  ```js
@@ -164,7 +280,7 @@ const result = await graphit.resolve({
164
280
 
165
281
  ### First-paint loading state
166
282
 
167
- The HTML paints before the SDK connects, so bake a pure-CSS spinner overlay into the page; the SDK adopts it and removes it when that element's `graphit.resolve()` settles (success or error). Add once to the page `<style>`:
283
+ The HTML paints before the SDK connects, so bake a pure-CSS spinner overlay into the page; the SDK adopts it and removes it when that element's `graphit.resolve()` settles. Add once to the page `<style>`:
168
284
 
169
285
  ```css
170
286
  @keyframes gh-spin{to{transform:rotate(360deg)}}
@@ -173,20 +289,21 @@ The HTML paints before the SDK connects, so bake a pure-CSS spinner overlay into
173
289
  .gh-loading-spin{animation:gh-spin .7s linear infinite}
174
290
  ```
175
291
 
176
- Add the overlay inside EVERY element you pass as `target:` - and ONLY those elements (a static text/title section with no resolve call would spin forever). Keep the class names exactly as shown; they are the contract the SDK uses to adopt and remove the overlay. NEVER write text placeholders ("Loading...", "Fetching data...") - they never animate and make slow loads look stuck. See the canonical pattern below for the overlay markup.
292
+ Add the overlay inside EVERY element you pass as `target:` - and ONLY those elements. Keep the class names exactly as shown; they are the contract the SDK uses. NEVER write text placeholders ("Loading...") - they never animate and make slow loads look stuck. See the canonical pattern below for the overlay markup.
177
293
 
178
294
  ### Runtime chart helpers
179
295
 
180
296
  | Helper | Usage |
181
297
  |---|---|
182
- | `graphit.chart(el, {type, data, x, y, ...})` | Bar, line, area, donut, scatter, stacked-bar, heatmap, funnel, gauge, sparkline |
183
- | `graphit.table(el, {data, columns?, maxRows?})` | Styled HTML table. `columns` is a `string[]` of data keys (NOT objects), defaults to `Object.keys(data[0])` |
184
- | `graphit.kpi(el, {value, label?, format?})` | KPI card with optional delta |
185
- | `graphit.filter(id, {label, field?, default?})` | Headless filter (zero DOM). Returns `{get, set, subscribe}` handle |
186
- | `graphit.param(id, {label, default?, options?})` | Headless parameter (zero DOM). Same handle API |
187
- | `graphit.bind(el, {sql, dataSourceId, params, deps?, render})` | Auto re-resolve on filter/param change |
298
+ | `graphit.chart(el, {type, data, x, y, ...})` | Bar, horizontal-bar, line, area, donut, scatter, stacked-bar, heatmap, funnel, gauge, sparkline |
299
+ | `graphit.table(el, {data, columns?, maxRows?})` | Styled HTML table. `columns` is a `string[]` of data keys (NOT objects) |
300
+ | `graphit.kpi(el, {value, label?, format?})` | KPI card with optional delta (`compareValue`, `compareLabel`) |
301
+ | `graphit.presentation(el)` | Full-screen slide deck. Returns builder: `.slide({bg, layout, html})` then `.start()`. See graphit-presentations rule. |
302
+ | `graphit.filter(id, {label, field?, default?})` | Headless filter (zero DOM). Returns `{get, set, subscribe}` handle. See graphit-filters rule. |
303
+ | `graphit.param(id, {label, default?, options?})` | Headless parameter (zero DOM). Same handle API. |
304
+ | `graphit.bind(el, {sql, dataSourceId, params, deps?, render})` | Auto re-resolve on filter/param change. See graphit-filters rule. |
188
305
 
189
- `graphit.chart` types: `"bar"`, `"line"`, `"area"`, `"donut"` (alias `"pie"`), `"scatter"` (alias `"bubble"`), `"stacked-bar"` (alias `"stacked"`), `"heatmap"`, `"funnel"`, `"gauge"`, `"sparkline"`. Config: `x` (category field), `y` (value field), `series` (group-by), `title`, `height` (140-900px), `valueFormat` (`"currency"` | `"percent"` | `"number"`), `colors` (array). Scatter adds: `size`, `label`. Gauge adds: `min`, `max`, `format`. Sparkline adds: `width`, `showValue`.
306
+ `graphit.chart` types: `"bar"`, `"horizontal-bar"` (alias `"hbar"`), `"line"`, `"area"`, `"donut"` (alias `"pie"`), `"scatter"` (alias `"bubble"`), `"stacked-bar"` (alias `"stacked"`), `"heatmap"`, `"funnel"`, `"gauge"`, `"sparkline"`. Config: `x`, `y`, `series`, `title`, `height` (140-900px), `valueFormat` (`"currency"` | `"percent"` | `"number"`), `colors`. Dual axis (bar/line/area): `y2`, `y2Format`, `y2Label`; `y2` and `series` are mutually exclusive. Scatter adds: `size`, `label`. Gauge: `min`, `max`, `format`. Sparkline: `width`, `showValue`.
190
307
 
191
308
  ### Canonical pattern - entity with live data
192
309
 
@@ -214,4 +331,4 @@ Add the overlay inside EVERY element you pass as `target:` - and ONLY those elem
214
331
  </script>
215
332
  ```
216
333
 
217
- For detailed chart selection logic, dashboard planning, SQL reference, domain-specific lenses, Graphit visual style, and chart pattern implementations, see the companion rule files (graphit-planning, graphit-sql, graphit-lenses, graphit-style, graphit-kb, graphit-patterns).
334
+ For detailed chart selection, dashboard planning, SQL reference, domain lenses, visual style, KB structure, chart patterns, governance, presentations, filters, and data source shaping, see the companion rule files.