cassis-cli 3.1.1__tar.gz → 3.2.0__tar.gz

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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cassis-cli
3
- Version: 3.1.1
3
+ Version: 3.2.0
4
4
  Summary: Validate, test and evaluate your Cassis context from your terminal, then publish it
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -24,7 +24,7 @@ Description-Content-Type: text/markdown
24
24
 
25
25
  Validate, test and evaluate your context from your terminal, then publish it. The same commands gate your pull requests in CI:
26
26
 
27
- - `cassis context check` validates the context files in your repository with the exact same checks as the Cassis GitHub PR check (YAML parsing, round-trip, import validation), so you can gate merges in any CI system, not just GitHub. It then prints advisory **context quality warnings** for a tree that parsed: tables not assigned to any domain, joins/metrics pointing at unknown tables or columns, missing table/column descriptions (the same findings `context test` reports, without the agent run). In a checkout bound to a project (`project.yml`, `--project`, or `CASSIS_PROJECT_ID`), it also cross-checks the tree against the project's source schema: references to tables or columns the warehouse doesn't have print as **warnings** too, advisory only (the object may simply not be built or synced yet). Warnings never fail the check.
27
+ - `cassis context check` validates the context files in your repository with the exact same checks as the Cassis GitHub PR check (YAML parsing, round-trip, import validation), so you can gate merges in any CI system, not just GitHub. It then prints advisory **context quality warnings** for a tree that parsed: tables not assigned to any domain, joins/metrics pointing at unknown tables or columns, missing table/column descriptions, `enum_values` the column's type can't store (the same findings `context test` reports, without the agent run). In a checkout bound to a project (`project.yml`, `--project`, or `CASSIS_PROJECT_ID`), it also cross-checks the tree against the project's source schema: references to tables or columns the warehouse doesn't have print as **warnings** too, advisory only (the object may simply not be built or synced yet). Warnings never fail the check.
28
28
  - `cassis schema pull` downloads the data source's full source schema (as Cassis last introspected it) into `<base-path>/.schema.json`, a **gitignored** local snapshot (the command maintains the ignore entry) with a `pulled_at` stamp. The warehouse stays authoritative; the snapshot is a cache for offline/bulk work, e.g. a coding agent grepping table and column names during a modeling pass instead of paging through the MCP `get_source_schema` tool. Re-run to refresh.
29
29
  - `cassis context fmt` rewrites the context files in canonical form (think `black`/`gofmt` for your context), so hand or agent edits pass the round-trip check.
30
30
  - `cassis context upload` uploads the context files to a Cassis project (full replace) and, by default, publishes them immediately as a new version, so a merge to your main branch can go live in one CI step. It runs from a git checkout whose context files are committed, and the published version records that commit, even when the upload changes nothing, so `cassis status` can tell whether a checkout matches what is live.
@@ -55,7 +55,7 @@ The context tree under `<base-path>` (default `cassis/`) is:
55
55
 
56
56
  - **Project identity**: `project.yml`, the Cassis project id and format version. Written by `pull` and by server-side publish (the places that know the id); a local `fmt` won't create it.
57
57
  - **Domains**: Markdown files. Every domain is the `README.md` of its folder: `domains/README.md` for the root, `domains/<path>/README.md` for each sub-domain. Each has a small YAML frontmatter block (`type`, `title`, `description`) and a Markdown body carrying the domain's `context_md`; a generated section at the bottom links the domain's tables and metrics (kept current by `fmt`/`pull`: edit your prose above it, and the PR check fails if the links are stale, so re-run `fmt`). The layout is a Cassis profile inspired by [OKF](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf): the files render on GitHub and read in any Markdown editor, but Cassis validates them strictly (unknown keys are flagged, not preserved).
58
- - **Tables, joins, metrics**: YAML, unchanged: `tables/<schema>/<table>.yml`, `joins.yml`, `metrics/<name>.yml`.
58
+ - **Tables, joins, metrics**: YAML, unchanged: `tables/<schema>/<table>.yml`, `joins.yml`, `metrics/<name>.yml`. A column can list the values it stores as `enum_values` (items `{value, description?}`, values quoted exactly as stored); see `cassis/AGENTS.md`.
59
59
 
60
60
  **Migrating an existing repo** (domains were YAML `_project.yml` / `_domain.yml` before cassis-cli 1.1.0): upgrade and run `cassis context fmt` (or `cassis context pull` if you have no local edits). It rewrites the domain files to Markdown and removes the old ones. Review the diff and commit. Cassis reads the old YAML domain files too, so an un-migrated repo keeps working until you convert it. **Uploading requires cassis-cli ≥ 1.1.0**: the server rejects an older CLI (which would drop the Markdown domain files) with a clear upgrade error.
61
61
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Validate, test and evaluate your context from your terminal, then publish it. The same commands gate your pull requests in CI:
4
4
 
5
- - `cassis context check` validates the context files in your repository with the exact same checks as the Cassis GitHub PR check (YAML parsing, round-trip, import validation), so you can gate merges in any CI system, not just GitHub. It then prints advisory **context quality warnings** for a tree that parsed: tables not assigned to any domain, joins/metrics pointing at unknown tables or columns, missing table/column descriptions (the same findings `context test` reports, without the agent run). In a checkout bound to a project (`project.yml`, `--project`, or `CASSIS_PROJECT_ID`), it also cross-checks the tree against the project's source schema: references to tables or columns the warehouse doesn't have print as **warnings** too, advisory only (the object may simply not be built or synced yet). Warnings never fail the check.
5
+ - `cassis context check` validates the context files in your repository with the exact same checks as the Cassis GitHub PR check (YAML parsing, round-trip, import validation), so you can gate merges in any CI system, not just GitHub. It then prints advisory **context quality warnings** for a tree that parsed: tables not assigned to any domain, joins/metrics pointing at unknown tables or columns, missing table/column descriptions, `enum_values` the column's type can't store (the same findings `context test` reports, without the agent run). In a checkout bound to a project (`project.yml`, `--project`, or `CASSIS_PROJECT_ID`), it also cross-checks the tree against the project's source schema: references to tables or columns the warehouse doesn't have print as **warnings** too, advisory only (the object may simply not be built or synced yet). Warnings never fail the check.
6
6
  - `cassis schema pull` downloads the data source's full source schema (as Cassis last introspected it) into `<base-path>/.schema.json`, a **gitignored** local snapshot (the command maintains the ignore entry) with a `pulled_at` stamp. The warehouse stays authoritative; the snapshot is a cache for offline/bulk work, e.g. a coding agent grepping table and column names during a modeling pass instead of paging through the MCP `get_source_schema` tool. Re-run to refresh.
7
7
  - `cassis context fmt` rewrites the context files in canonical form (think `black`/`gofmt` for your context), so hand or agent edits pass the round-trip check.
8
8
  - `cassis context upload` uploads the context files to a Cassis project (full replace) and, by default, publishes them immediately as a new version, so a merge to your main branch can go live in one CI step. It runs from a git checkout whose context files are committed, and the published version records that commit, even when the upload changes nothing, so `cassis status` can tell whether a checkout matches what is live.
@@ -33,7 +33,7 @@ The context tree under `<base-path>` (default `cassis/`) is:
33
33
 
34
34
  - **Project identity**: `project.yml`, the Cassis project id and format version. Written by `pull` and by server-side publish (the places that know the id); a local `fmt` won't create it.
35
35
  - **Domains**: Markdown files. Every domain is the `README.md` of its folder: `domains/README.md` for the root, `domains/<path>/README.md` for each sub-domain. Each has a small YAML frontmatter block (`type`, `title`, `description`) and a Markdown body carrying the domain's `context_md`; a generated section at the bottom links the domain's tables and metrics (kept current by `fmt`/`pull`: edit your prose above it, and the PR check fails if the links are stale, so re-run `fmt`). The layout is a Cassis profile inspired by [OKF](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf): the files render on GitHub and read in any Markdown editor, but Cassis validates them strictly (unknown keys are flagged, not preserved).
36
- - **Tables, joins, metrics**: YAML, unchanged: `tables/<schema>/<table>.yml`, `joins.yml`, `metrics/<name>.yml`.
36
+ - **Tables, joins, metrics**: YAML, unchanged: `tables/<schema>/<table>.yml`, `joins.yml`, `metrics/<name>.yml`. A column can list the values it stores as `enum_values` (items `{value, description?}`, values quoted exactly as stored); see `cassis/AGENTS.md`.
37
37
 
38
38
  **Migrating an existing repo** (domains were YAML `_project.yml` / `_domain.yml` before cassis-cli 1.1.0): upgrade and run `cassis context fmt` (or `cassis context pull` if you have no local edits). It rewrites the domain files to Markdown and removes the old ones. Review the diff and commit. Cassis reads the old YAML domain files too, so an un-migrated repo keeps working until you convert it. **Uploading requires cassis-cli ≥ 1.1.0**: the server rejects an older CLI (which would drop the Markdown domain files) with a clear upgrade error.
39
39
 
@@ -31,7 +31,7 @@ GUIDE_FILENAME = "AGENTS.md"
31
31
  # Monotonic version of the doctrine text below. Bump it whenever
32
32
  # ontology_design_guide.md changes (a backend test enforces the pairing) — it
33
33
  # is what lets an older writer recognize a newer guide and leave it alone.
34
- DOCTRINE_VERSION = 9
34
+ DOCTRINE_VERSION = 10
35
35
 
36
36
  # Must stay byte-identical to backend/app/services/ontology_guide.py::_BANNER —
37
37
  # the server-side git export writes the same file, and differing banners would
@@ -22,7 +22,7 @@ with domains as Markdown and everything else as YAML:
22
22
  | **Root context** (`domains/README.md` body) | One free-text block, always in the agent's prompt | markdown |
23
23
  | **Domains** | A navigable tree grouping the business by subject area | `path`, `display_name`, `description`, `context_md` |
24
24
  | **Tables** | A physical warehouse table (introspected) or a virtual one (SQL-defined) placed in a domain | `name` (`schema.TABLE`), `description`, `synonyms`, `grain`, columns |
25
- | **Columns** | Enrichment on a table's columns | `description`, `unit`, `synonyms` |
25
+ | **Columns** | Enrichment on a table's columns | `description`, `unit`, `synonyms`, `enum_values` |
26
26
  | **Joins** | A known way two tables relate | `from_schema`/`from_table`, `to_schema`/`to_table`, `column_pairs`, `condition_sql`, `cardinality`, `description` |
27
27
  | **Metrics** | A reusable business measure | `name`, `display_name`, `expression`, `table_schema`/`table_name`, `filters`, `unit`, `synonyms`, `notes`, `precomputed_in` |
28
28
 
@@ -50,8 +50,8 @@ edit surface: you edit the files, open a pull request, and merging syncs and
50
50
  publishes it.
51
51
 
52
52
  Physical tables and their columns come from schema introspection — you never
53
- invent them; you *enrich* them (place them in a domain, describe them, set units
54
- and synonyms). The one exception is a virtual table, which you define with a
53
+ invent them; you *enrich* them (place them in a domain, describe them, set units,
54
+ synonyms and stored values). The one exception is a virtual table, which you define with a
55
55
  `sql` body (see §5).
56
56
 
57
57
  The one governing principle everything below serves:
@@ -106,7 +106,7 @@ and must match the warehouse (see §7).
106
106
  Put each fact at the lowest layer that fully owns it:
107
107
 
108
108
  ```
109
- column synonym / column description single-column facts: meaning, encoding, unit, date format, nulls
109
+ column enum_values / synonym / description single-column facts: stored values, meaning, encoding, unit, date format, nulls
110
110
  → table description single-table facts: scope, mandatory filters, "use this not that"
111
111
  → domain context_md cross-table routing, disambiguation, vocabulary spanning tables
112
112
  → root context truly global rules only: corporate identity, entity hierarchy, global conventions
@@ -223,11 +223,31 @@ in the `sql` per §7.
223
223
 
224
224
  ## 6. Columns
225
225
 
226
- Column enrichment is `description`, `unit`, and `synonyms` — you cannot add or
227
- rename columns (they come from introspection). The agent sees a column's name,
228
- type, `unit` and `synonyms` structurally; the `description` carries what those
229
- don't: meaning, possible values, encoding, date format, null behavior, any
230
- mandatory filter.
226
+ Column enrichment is `description`, `unit`, `synonyms` and `enum_values` — you
227
+ cannot add or rename columns (they come from introspection). The agent sees a
228
+ column's name, type, `unit`, `synonyms` and `enum_values` structurally; the
229
+ `description` carries what those don't: meaning, encoding, date format, null
230
+ behavior, any mandatory filter.
231
+
232
+ - **Stored values go in `enum_values`, not in the description.** A categorical
233
+ column with a small, stable set (a status, type, tier, code) lists every value
234
+ it stores in `enum_values`, verbatim and case-exact, in a meaningful order
235
+ (ordinal sets keep their order). A value's meaning goes in that value's own
236
+ `description`; the column `description` says what the column *means* and never
237
+ lists values. Free text, identifiers and high-cardinality columns get no
238
+ `enum_values`; a few notable codes in a large column stay in the description.
239
+ How to get the list right, and what to do with value lists already written in
240
+ prose, is §10.
241
+
242
+ ```yaml
243
+ columns:
244
+ - description: Lifecycle stage of the subscription.
245
+ enum_values:
246
+ - value: ACTIVE
247
+ - value: CANCELLED
248
+ description: Cancelled by the customer; access runs to period end.
249
+ name: status
250
+ ```
231
251
 
232
252
  - **Prioritize the trap columns.** Disambiguate similarly-named columns
233
253
  (`created_at` vs `updated_at`, `amount` vs `net_amount`), numeric-encoded
@@ -370,7 +390,9 @@ warehouse's stored case**, or generated SQL fails with errors like
370
390
  `grain`, join endpoints (`from_schema`/`from_table`/…), `column_pairs` and
371
391
  `condition_sql`, and metric `table_schema`/`table_name`/`expression`/`filters`. Logical fields — domain paths, display names, descriptions,
372
392
  **synonyms**, `context_md` — stay natural language; the matching layer there is
373
- case-insensitive and should read naturally.
393
+ case-insensitive and should read naturally. A column's `enum_values` are data
394
+ literals, not identifiers, but they are matched exactly too: write each value
395
+ as stored, case included.
374
396
  - **Schema-qualify everything.** Table references in SQL and prose carry the
375
397
  `schema.TABLE` form (`dbt_core.fct_orders`), so a scope rule about `raw.users`
376
398
  never accidentally catches `core.users`, and a prefix that doesn't match what
@@ -383,12 +405,22 @@ warehouse's stored case**, or generated SQL fails with errors like
383
405
  An inaccurate example primes the agent **more strongly** than a correct prose
384
406
  description, so a wrong example is worse than none.
385
407
 
386
- - **Use real stored enum values verbatim.** Never hand-wave a list with "etc." —
387
- the agent reads `etc.` as license to invent values. If you don't have the exact
388
- values, omit the list rather than approximate it. A `DISTINCT` over the column
389
- *is* the list of stored values: write it plainly ("Stored values: 'EDITOR'"),
390
- with no "observed so far" hedge and no counts. When two columns supposedly
391
- share an enum, verify they're identical before encoding both.
408
+ - **`enum_values` is the complete set of stored values, verbatim.** The agent
409
+ treats it as closed: filter literals come from it, exact case, and a value it
410
+ doesn't list does not exist. Verify the set against the source before writing
411
+ it — a `SELECT DISTINCT` over the column, or a `CHECK ... IN (...)` constraint
412
+ the schema shows — and write it plainly, with no "observed so far" hedge and no
413
+ counts. If you don't have the exact set, leave `enum_values` out rather than
414
+ approximate it: a partial list is worse than none, because the agent stops
415
+ looking for other values. When two columns supposedly share an enum, verify
416
+ they're identical before encoding both.
417
+ - **Move value lists out of prose.** Older descriptions list values in text
418
+ ("Possible values: …", "Values:", "One of:", "Stored values: 'EDITOR'"). When
419
+ you touch a table and find one, move the list into that column's `enum_values`
420
+ and delete it from the description in the same change, verifying it against
421
+ the source first when you can. A hedged or open-ended prose list ("etc.",
422
+ "includes", "e.g.", "and legacy …") is **not** the complete set: verify it, or
423
+ drop it without promoting it. Never turn an approximation into `enum_values`.
392
424
  - **Be wary of analogies to external products** — they mislead the moment the
393
425
  real mechanic diverges.
394
426
  - **Don't describe things that don't exist.** Every table, column, and value you
@@ -430,10 +462,10 @@ description, so a wrong example is worse than none.
430
462
  definitions, not what the data shows today. Row counts, distinct counts, shares,
431
463
  distributions, funnel rates and "as of" / "currently" / "observed" statements go
432
464
  stale silently, and the answering agent repeats them as fact. Query the data to
433
- *verify* a stable fact (stored enum values, a date format, null behaviour) and
434
- write only the fact: "Stored values: 'EDITOR', 'ADMIN'", not "only 'EDITOR'
435
- observed (6 of 6, 100%)". Complete value lists and constants the business fixes
436
- (a 14-day trial) are facts, not measurements.
465
+ *verify* a stable fact (a column's stored values, a date format, null
466
+ behaviour) and write only the fact: the values in `enum_values`, not "only
467
+ 'EDITOR' observed (6 of 6, 100%)" in prose. Complete value sets and constants
468
+ the business fixes (a 14-day trial) are facts, not measurements.
437
469
  - **Ask for the business meaning; don't guess.** A term like "active user" or
438
470
  "last month" has a project-specific definition (time window, criteria, filters).
439
471
  Encode the business's actual definition, not a textbook default.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cassis-cli"
3
- version = "3.1.1"
3
+ version = "3.2.0"
4
4
  description = "Validate, test and evaluate your Cassis context from your terminal, then publish it"
5
5
  readme = "README.md"
6
6
  license = { text = "Apache-2.0" }
File without changes
File without changes
File without changes