@google-cloud/kcmd 0.0.0-stage → 0.2.0
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/LICENSE +203 -0
- package/README.md +264 -2
- package/build/ts/kcmd/cli.js +20252 -0
- package/build/ts/kcmd/gcp/alloydb.d.ts +12 -0
- package/build/ts/kcmd/gcp/alloydb.js +70 -0
- package/build/ts/kcmd/gcp/api.d.ts +29 -0
- package/build/ts/kcmd/gcp/api.js +162 -0
- package/build/ts/kcmd/gcp/biglake.d.ts +18 -0
- package/build/ts/kcmd/gcp/biglake.js +59 -0
- package/build/ts/kcmd/gcp/bigquery.d.ts +57 -0
- package/build/ts/kcmd/gcp/bigquery.js +134 -0
- package/build/ts/kcmd/gcp/context.d.ts +10 -0
- package/build/ts/kcmd/gcp/context.js +74 -0
- package/build/ts/kcmd/gcp/crm.d.ts +13 -0
- package/build/ts/kcmd/gcp/crm.js +91 -0
- package/build/ts/kcmd/gcp/dataplex.d.ts +147 -0
- package/build/ts/kcmd/gcp/dataplex.js +406 -0
- package/build/ts/kcmd/gcp/index.d.ts +3 -0
- package/build/ts/kcmd/gcp/index.js +21 -0
- package/build/ts/kcmd/gcp/spanner.d.ts +73 -0
- package/build/ts/kcmd/gcp/spanner.js +126 -0
- package/build/ts/kcmd/index.d.ts +7 -0
- package/build/ts/kcmd/index.js +46 -0
- package/build/ts/kcmd/layout.d.ts +16 -0
- package/build/ts/kcmd/layout.js +31 -0
- package/build/ts/kcmd/layouts/documents.d.ts +24 -0
- package/build/ts/kcmd/layouts/documents.js +264 -0
- package/build/ts/kcmd/layouts/okf.d.ts +31 -0
- package/build/ts/kcmd/layouts/okf.js +386 -0
- package/build/ts/kcmd/layouts/semantic-model.d.ts +74 -0
- package/build/ts/kcmd/layouts/semantic-model.js +621 -0
- package/build/ts/kcmd/layouts/standard.d.ts +13 -0
- package/build/ts/kcmd/layouts/standard.js +108 -0
- package/build/ts/kcmd/manifest.d.ts +34 -0
- package/build/ts/kcmd/manifest.js +262 -0
- package/build/ts/kcmd/metadata.d.ts +25 -0
- package/build/ts/kcmd/metadata.js +8 -0
- package/build/ts/kcmd/okf/catalog_residue.d.ts +14 -0
- package/build/ts/kcmd/okf/catalog_residue.js +124 -0
- package/build/ts/kcmd/okf/concept.d.ts +14 -0
- package/build/ts/kcmd/okf/concept.js +110 -0
- package/build/ts/kcmd/okf/concept_to_entry.d.ts +10 -0
- package/build/ts/kcmd/okf/concept_to_entry.js +281 -0
- package/build/ts/kcmd/okf/init_okf_workspace.d.ts +15 -0
- package/build/ts/kcmd/okf/init_okf_workspace.js +113 -0
- package/build/ts/kcmd/okf/links.d.ts +23 -0
- package/build/ts/kcmd/okf/links.js +468 -0
- package/build/ts/kcmd/okf/okf_metadata.d.ts +12 -0
- package/build/ts/kcmd/okf/okf_metadata.js +99 -0
- package/build/ts/kcmd/semantic/bigquery.d.ts +22 -0
- package/build/ts/kcmd/semantic/bigquery.js +469 -0
- package/build/ts/kcmd/semantic/binding.d.ts +3 -0
- package/build/ts/kcmd/semantic/binding.js +92 -0
- package/build/ts/kcmd/semantic/catalog_entry.d.ts +24 -0
- package/build/ts/kcmd/semantic/catalog_entry.js +35 -0
- package/build/ts/kcmd/semantic/converters/owl/convert.d.ts +26 -0
- package/build/ts/kcmd/semantic/converters/owl/convert.js +41 -0
- package/build/ts/kcmd/semantic/converters/owl/model.d.ts +98 -0
- package/build/ts/kcmd/semantic/converters/owl/model.js +30 -0
- package/build/ts/kcmd/semantic/converters/owl/parse.d.ts +11 -0
- package/build/ts/kcmd/semantic/converters/owl/parse.js +634 -0
- package/build/ts/kcmd/semantic/converters/owl/to_ir.d.ts +19 -0
- package/build/ts/kcmd/semantic/converters/owl/to_ir.js +390 -0
- package/build/ts/kcmd/semantic/deploy_bigquery.d.ts +20 -0
- package/build/ts/kcmd/semantic/deploy_bigquery.js +226 -0
- package/build/ts/kcmd/semantic/deploy_knowledge_catalog.d.ts +104 -0
- package/build/ts/kcmd/semantic/deploy_knowledge_catalog.js +1367 -0
- package/build/ts/kcmd/semantic/deploy_spanner.d.ts +15 -0
- package/build/ts/kcmd/semantic/deploy_spanner.js +150 -0
- package/build/ts/kcmd/semantic/deployment_target.d.ts +93 -0
- package/build/ts/kcmd/semantic/deployment_target.js +379 -0
- package/build/ts/kcmd/semantic/graph_ddl.d.ts +44 -0
- package/build/ts/kcmd/semantic/graph_ddl.js +656 -0
- package/build/ts/kcmd/semantic/import_model.d.ts +72 -0
- package/build/ts/kcmd/semantic/import_model.js +1698 -0
- package/build/ts/kcmd/semantic/ir.d.ts +589 -0
- package/build/ts/kcmd/semantic/ir.js +247 -0
- package/build/ts/kcmd/semantic/kc_actions.d.ts +45 -0
- package/build/ts/kcmd/semantic/kc_actions.js +531 -0
- package/build/ts/kcmd/semantic/kc_constraints.d.ts +44 -0
- package/build/ts/kcmd/semantic/kc_constraints.js +279 -0
- package/build/ts/kcmd/semantic/kc_converter.d.ts +37 -0
- package/build/ts/kcmd/semantic/kc_converter.js +839 -0
- package/build/ts/kcmd/semantic/kc_custom_types.d.ts +63 -0
- package/build/ts/kcmd/semantic/kc_custom_types.js +751 -0
- package/build/ts/kcmd/semantic/kc_entries.d.ts +155 -0
- package/build/ts/kcmd/semantic/kc_entries.js +284 -0
- package/build/ts/kcmd/semantic/kc_ids.d.ts +102 -0
- package/build/ts/kcmd/semantic/kc_ids.js +188 -0
- package/build/ts/kcmd/semantic/knowledge_catalog.d.ts +29 -0
- package/build/ts/kcmd/semantic/knowledge_catalog.js +960 -0
- package/build/ts/kcmd/semantic/loader.d.ts +258 -0
- package/build/ts/kcmd/semantic/loader.js +3576 -0
- package/build/ts/kcmd/semantic/names.d.ts +10 -0
- package/build/ts/kcmd/semantic/names.js +85 -0
- package/build/ts/kcmd/semantic/osi_converter.d.ts +60 -0
- package/build/ts/kcmd/semantic/osi_converter.js +910 -0
- package/build/ts/kcmd/semantic/parameters.d.ts +19 -0
- package/build/ts/kcmd/semantic/parameters.js +171 -0
- package/build/ts/kcmd/semantic/pull_kc.d.ts +10 -0
- package/build/ts/kcmd/semantic/pull_kc.js +272 -0
- package/build/ts/kcmd/semantic/resolve_inheritance.d.ts +59 -0
- package/build/ts/kcmd/semantic/resolve_inheritance.js +346 -0
- package/build/ts/kcmd/semantic/resolve_profiles.d.ts +291 -0
- package/build/ts/kcmd/semantic/resolve_profiles.js +2003 -0
- package/build/ts/kcmd/semantic/runtime/agent_tools.d.ts +93 -0
- package/build/ts/kcmd/semantic/runtime/agent_tools.js +243 -0
- package/build/ts/kcmd/semantic/runtime/dialect.d.ts +13 -0
- package/build/ts/kcmd/semantic/runtime/dialect.js +39 -0
- package/build/ts/kcmd/semantic/runtime/runtime.d.ts +88 -0
- package/build/ts/kcmd/semantic/runtime/runtime.js +301 -0
- package/build/ts/kcmd/semantic/runtime/store.d.ts +112 -0
- package/build/ts/kcmd/semantic/runtime/store.js +344 -0
- package/build/ts/kcmd/semantic/skills.d.ts +110 -0
- package/build/ts/kcmd/semantic/skills.js +697 -0
- package/build/ts/kcmd/semantic/source_dialect.d.ts +17 -0
- package/build/ts/kcmd/semantic/source_dialect.js +311 -0
- package/build/ts/kcmd/semantic/source_entries.d.ts +12 -0
- package/build/ts/kcmd/semantic/source_entries.js +341 -0
- package/build/ts/kcmd/semantic/spanner.d.ts +18 -0
- package/build/ts/kcmd/semantic/spanner.js +60 -0
- package/build/ts/kcmd/semantic/sql_expr_utils.d.ts +23 -0
- package/build/ts/kcmd/semantic/sql_expr_utils.js +394 -0
- package/build/ts/kcmd/semantic/sql_identifiers.d.ts +6 -0
- package/build/ts/kcmd/semantic/sql_identifiers.js +267 -0
- package/build/ts/kcmd/semantic/sql_parser.d.ts +47 -0
- package/build/ts/kcmd/semantic/sql_parser.js +400 -0
- package/build/ts/kcmd/semantic/transpile.d.ts +76 -0
- package/build/ts/kcmd/semantic/transpile.js +581 -0
- package/build/ts/kcmd/semantic/validate.d.ts +70 -0
- package/build/ts/kcmd/semantic/validate.js +2266 -0
- package/build/ts/kcmd/semantic/yaml_options.d.ts +6 -0
- package/build/ts/kcmd/semantic/yaml_options.js +58 -0
- package/build/ts/kcmd/semantic/yaml_update.d.ts +26 -0
- package/build/ts/kcmd/semantic/yaml_update.js +782 -0
- package/build/ts/kcmd/snapshot.d.ts +37 -0
- package/build/ts/kcmd/snapshot.js +386 -0
- package/build/ts/kcmd/source.d.ts +31 -0
- package/build/ts/kcmd/source.js +119 -0
- package/build/ts/kcmd/sources/bq-dataset.d.ts +17 -0
- package/build/ts/kcmd/sources/bq-dataset.js +131 -0
- package/build/ts/kcmd/sources/entrygroup.d.ts +21 -0
- package/build/ts/kcmd/sources/entrygroup.js +83 -0
- package/build/ts/kcmd/sources/kb.d.ts +21 -0
- package/build/ts/kcmd/sources/kb.js +82 -0
- package/build/ts/kcmd/sources/semantic-model.d.ts +18 -0
- package/build/ts/kcmd/sources/semantic-model.js +48 -0
- package/build/ts/kcmd/sync.d.ts +35 -0
- package/build/ts/kcmd/sync.js +734 -0
- package/package.json +62 -4
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI-first annotations, from the open format's `ai_context`.
|
|
3
|
+
*
|
|
4
|
+
* The format allows either a bare instructions string (shorthand) or a
|
|
5
|
+
* structured object; the loader normalizes both to this one shape, so the IR
|
|
6
|
+
* always sees the structured form. The parts are grouped in a single object
|
|
7
|
+
* (mirroring the format, e.g. Apache Ossie's `ai_context`) rather than scattered
|
|
8
|
+
* as sibling fields, so nothing is lost and an emitter can still route each part
|
|
9
|
+
* to its own destination (e.g. `instructions` -> a Guidelines aspect,
|
|
10
|
+
* `synonyms` -> glossary links).
|
|
11
|
+
*/
|
|
12
|
+
export interface AiContext {
|
|
13
|
+
instructions?: string;
|
|
14
|
+
synonyms?: string[];
|
|
15
|
+
examples?: string[];
|
|
16
|
+
additionalProperties?: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A vendor-scoped extension block, carried verbatim from the open format's
|
|
20
|
+
* `custom_extensions` (e.g. Apache Ossie's `OSICustomExtension`).
|
|
21
|
+
*
|
|
22
|
+
* `data` is opaque to the IR — a vendor-serialized payload (typically a JSON
|
|
23
|
+
* string) — and is preserved unparsed so nothing is lost and a 1P round-trip
|
|
24
|
+
* stays lossless. Typed views over specific vendors are derived by the
|
|
25
|
+
* consumers that need them, from this same source.
|
|
26
|
+
*/
|
|
27
|
+
export interface CustomExtension {
|
|
28
|
+
vendorName: string;
|
|
29
|
+
data: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A semantic model: a graph of entities (nodes) connected by relationships
|
|
33
|
+
* (edges), with model-level metrics defined over them.
|
|
34
|
+
*
|
|
35
|
+
* The IR is primarily semantics. The loader reads a model's named
|
|
36
|
+
* `deployments:` list onto `deployments`. In the Google flavor it also folds
|
|
37
|
+
* their target URIs into a model-level GOOGLE `custom_extensions` block for the
|
|
38
|
+
* consumers that read it. A vanilla model lists its deployments in its GOOGLE
|
|
39
|
+
* block, which the loader reads and does not fold.
|
|
40
|
+
*/
|
|
41
|
+
export interface SemanticModel {
|
|
42
|
+
name: string;
|
|
43
|
+
description?: string;
|
|
44
|
+
aiContext?: AiContext;
|
|
45
|
+
entities: Entity[];
|
|
46
|
+
relationships: Relationship[];
|
|
47
|
+
metrics: Metric[];
|
|
48
|
+
actions?: Action[];
|
|
49
|
+
constraints?: Constraint[];
|
|
50
|
+
customExtensions?: CustomExtension[];
|
|
51
|
+
version?: '0.2.0.dev0' | '0.2.0.dev0/google';
|
|
52
|
+
profiles?: ProfileSpec[];
|
|
53
|
+
deployments?: DeploymentSpec[];
|
|
54
|
+
excludedMetrics?: string[];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* An entity: a node in the semantic graph. Backed by a physical table
|
|
58
|
+
* (`dataSource`), identified by `keys`, and carrying its dimension `fields`.
|
|
59
|
+
*/
|
|
60
|
+
export interface Entity {
|
|
61
|
+
name: string;
|
|
62
|
+
dataSource: string;
|
|
63
|
+
authoredSource?: string;
|
|
64
|
+
sourceDialect?: string;
|
|
65
|
+
keys: string[];
|
|
66
|
+
uniqueKeys?: string[][];
|
|
67
|
+
extends?: string[];
|
|
68
|
+
abstract?: boolean;
|
|
69
|
+
description?: string;
|
|
70
|
+
aiContext?: AiContext;
|
|
71
|
+
fields: Field[];
|
|
72
|
+
customExtensions?: CustomExtension[];
|
|
73
|
+
excludedFields?: string[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Dimension metadata on a field, mirroring the open format's `dimension` block
|
|
77
|
+
* (e.g. Apache Ossie's `OSIDimension`). An empty block still marks the field as
|
|
78
|
+
* a dimension, which enables temporal inference from `type` (see
|
|
79
|
+
* isTimeDimension).
|
|
80
|
+
*/
|
|
81
|
+
export interface Dimension {
|
|
82
|
+
isTime?: boolean;
|
|
83
|
+
}
|
|
84
|
+
export declare const ALLOWED_DIALECTS: readonly ["ANSI_SQL", "BIGQUERY", "SPANNER", "MYSQL", "POSTGRES", "ALLOYDB", "SQLSERVER", "SNOWFLAKE", "DATABRICKS"];
|
|
85
|
+
export type SqlDialect = (typeof ALLOWED_DIALECTS)[number];
|
|
86
|
+
export interface DialectExpression {
|
|
87
|
+
dialect: SqlDialect;
|
|
88
|
+
expression: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* A field: a dimension / attribute of an entity or relationship.
|
|
92
|
+
*
|
|
93
|
+
* Fields describe the data; aggregates are expressed as model-level `Metric`s,
|
|
94
|
+
* not fields.
|
|
95
|
+
*
|
|
96
|
+
* Expression fidelity: the format may supply an expression in several SQL
|
|
97
|
+
* dialects (or as a single string in the Google flavor). The loader keeps every
|
|
98
|
+
* entry in `dialects` in the order written and records `stringForm` (`true`
|
|
99
|
+
* when authored as `expression: "<sql>"`, `false` when authored as a `dialects`
|
|
100
|
+
* list). It also populates `expression` (the target-dialect text, or else the
|
|
101
|
+
* `ANSI_SQL` one) and `importedExpression` (the first other vendor entry, with
|
|
102
|
+
* its `importedDialect`) via `pickDialect`. A bound field sets at least one of
|
|
103
|
+
* `expression`, `importedExpression` or a non-empty `dialects` (the loader sets
|
|
104
|
+
* one of the first two whenever it writes the third). When only
|
|
105
|
+
* `importedExpression` is present, `expression` awaits a transpile pass (see
|
|
106
|
+
* ./transpile) that fills it from the imported form.
|
|
107
|
+
*/
|
|
108
|
+
export interface Field {
|
|
109
|
+
name: string;
|
|
110
|
+
expression?: string;
|
|
111
|
+
importedExpression?: string;
|
|
112
|
+
importedDialect?: string;
|
|
113
|
+
dialects?: DialectExpression[];
|
|
114
|
+
stringForm?: boolean;
|
|
115
|
+
dimension?: Dimension;
|
|
116
|
+
label?: string;
|
|
117
|
+
description?: string;
|
|
118
|
+
type?: DataType;
|
|
119
|
+
aiContext?: AiContext;
|
|
120
|
+
customExtensions?: CustomExtension[];
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The open format's `datatype` vocabulary, mirroring Apache Ossie's `DataType`:
|
|
124
|
+
* a CLOSED, case-sensitive set of logical types, independent of physical
|
|
125
|
+
* representation. It is optional; omit it when the type is unknown. `Opaque`
|
|
126
|
+
* marks an unknown type: the loader reads it as no type, and the catalog stores
|
|
127
|
+
* it where a type is required. No custom extension supplies a real type for
|
|
128
|
+
* it. The loader enforces this set at parse time, so a `type` on the IR is
|
|
129
|
+
* always one of these.
|
|
130
|
+
*/
|
|
131
|
+
export declare const DATA_TYPES: readonly ["String", "Integer", "Decimal", "Float", "Boolean", "Date", "Time", "DateTime", "DateTimeTz", "Opaque"];
|
|
132
|
+
export type DataType = typeof DATA_TYPES[number];
|
|
133
|
+
/**
|
|
134
|
+
* Normalizes a raw `datatype` string according to the document's flavor.
|
|
135
|
+
*
|
|
136
|
+
* In `0.2.0.dev0`, matching is strictly case-sensitive. In `0.2.0.dev0/google`,
|
|
137
|
+
* matching is case-insensitive and returns the canonical spelling. In both
|
|
138
|
+
* flavors, an omitted `datatype` and `Opaque` normalize to `type: undefined`.
|
|
139
|
+
*/
|
|
140
|
+
export declare function normalizeDataType(raw: string | undefined, version: '0.2.0.dev0' | '0.2.0.dev0/google'): {
|
|
141
|
+
ok: true;
|
|
142
|
+
type: Exclude<DataType, 'Opaque'> | undefined;
|
|
143
|
+
} | {
|
|
144
|
+
ok: false;
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* A field's effective temporal-dimension role, mirroring the open format's
|
|
148
|
+
* `is_time_dimension()` (e.g. Apache Ossie's `OSIField`): a field must carry
|
|
149
|
+
* `dimension` metadata to be a dimension at all; within it an explicit `isTime`
|
|
150
|
+
* takes precedence, otherwise the role defaults from a temporal `type`.
|
|
151
|
+
*/
|
|
152
|
+
export declare function isTimeDimension(field: Field): boolean;
|
|
153
|
+
export declare function fieldBinding(field: Pick<Field, 'expression' | 'importedExpression'>): string | undefined;
|
|
154
|
+
export declare const FIELD_BINDING_KEYS: readonly ["expression", "dialects", "stringForm", "importedExpression", "importedDialect"];
|
|
155
|
+
export declare const FIELD_DEFINITION_KEYS: readonly ["type", "label", "dimension", "description", "aiContext", "customExtensions"];
|
|
156
|
+
/**
|
|
157
|
+
* Whether a field is bound to a column under the current binding: it carries an
|
|
158
|
+
* expression, an imported vendor expression, or a non-empty dialect list.
|
|
159
|
+
* `stringForm` and `importedDialect` describe a binding and are not one on
|
|
160
|
+
* their own. Inheritance, profile pruning and push validation use this test.
|
|
161
|
+
* A graph generator asks a narrower question, whether the field has SQL for its
|
|
162
|
+
* engine (see expressionForDialect), so a bound field can still be left out of
|
|
163
|
+
* one engine's graph.
|
|
164
|
+
*/
|
|
165
|
+
export declare function isFieldBound(field: Pick<Field, 'expression' | 'importedExpression' | 'dialects'>): boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Whether a relationship's `to_columns` cover the primary key or a unique key.
|
|
168
|
+
* A key is covered when every one of its columns is among `to_columns`, so a
|
|
169
|
+
* superset of a key covers it, since each row still matches at most one target
|
|
170
|
+
* row. Column names compare as BigQuery compares them: ignoring case, and
|
|
171
|
+
* without the backticks that only quote a name.
|
|
172
|
+
*/
|
|
173
|
+
export declare function coversKey(toColumns: string[], primaryKey: string[], uniqueKeys: string[][]): boolean;
|
|
174
|
+
/**
|
|
175
|
+
* Selects the SQL expression for a target engine from a Field or Metric.
|
|
176
|
+
*
|
|
177
|
+
* With a non-empty `dialects` list, returns the entry matching `targetDialect`;
|
|
178
|
+
* failing that, and where the target is not already `ANSI_SQL`, falls back to
|
|
179
|
+
* the `ANSI_SQL` entry; failing both, returns `undefined`. With `dialects`
|
|
180
|
+
* empty or absent, returns `item.importedExpression` when `importedDialect` is
|
|
181
|
+
* the target, and `item.expression` otherwise.
|
|
182
|
+
*/
|
|
183
|
+
export declare function expressionForDialect(item: {
|
|
184
|
+
expression?: string;
|
|
185
|
+
dialects?: DialectExpression[];
|
|
186
|
+
importedExpression?: string;
|
|
187
|
+
importedDialect?: string;
|
|
188
|
+
}, targetDialect: (typeof ALLOWED_DIALECTS)[number]): string | undefined;
|
|
189
|
+
/**
|
|
190
|
+
* A relationship: a directed foreign-key edge in the semantic graph, from
|
|
191
|
+
* `source` to `destination`. The join pairs the endpoints' columns positionally
|
|
192
|
+
* (`source.columns[i] = destination.columns[i]`): the source's foreign-key
|
|
193
|
+
* columns referencing the destination's key columns.
|
|
194
|
+
*/
|
|
195
|
+
export interface Relationship {
|
|
196
|
+
name: string;
|
|
197
|
+
source: RelationshipEnd;
|
|
198
|
+
destination: RelationshipEnd;
|
|
199
|
+
association?: Association;
|
|
200
|
+
description?: string;
|
|
201
|
+
aiContext?: AiContext;
|
|
202
|
+
customExtensions?: CustomExtension[];
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* One endpoint of a relationship: the entity it attaches to and the columns on
|
|
206
|
+
* that entity's own table that participate in the join.
|
|
207
|
+
*/
|
|
208
|
+
export interface RelationshipEnd {
|
|
209
|
+
entity: string;
|
|
210
|
+
columns: string[];
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* An association (junction) table backing a many-to-many relationship.
|
|
214
|
+
*
|
|
215
|
+
* A many-to-many link cannot be a foreign key: an FK column holds a single
|
|
216
|
+
* value and so references at most one row (a to-one direction), which cannot
|
|
217
|
+
* encode a pairing where each side maps to many of the other. The pairs instead
|
|
218
|
+
* live in a separate junction table, one row per (source, destination) -- e.g.
|
|
219
|
+
* an `enrollment` row per (student, course).
|
|
220
|
+
*
|
|
221
|
+
* Unlike a direct foreign key -- which the open format expresses and the loader
|
|
222
|
+
* produces -- a junction edge is backed by its OWN table (`dataSource`) with
|
|
223
|
+
* its OWN key (`keys`) and may carry edge `fields` (properties of the
|
|
224
|
+
* association itself, e.g. an enrollment's grade). Each side names the columns
|
|
225
|
+
* ON THE JUNCTION TABLE that reference the key of the endpoint entity's node
|
|
226
|
+
* (see nodeKey). The open format has no association-table syntax yet, so this
|
|
227
|
+
* is produced by hand-built IR (or a future format extension), not the loader.
|
|
228
|
+
*/
|
|
229
|
+
export interface Association {
|
|
230
|
+
dataSource: string;
|
|
231
|
+
keys: string[];
|
|
232
|
+
sourceColumns: string[];
|
|
233
|
+
destinationColumns: string[];
|
|
234
|
+
fields?: Field[];
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* A metric: a model-level, named aggregate.
|
|
238
|
+
*
|
|
239
|
+
* Because it lives on the model rather than a single entity, a metric may span
|
|
240
|
+
* multiple entities — its `expression` can reference fields across the graph,
|
|
241
|
+
* joined via relationships. See `entity` for the single attach point and how
|
|
242
|
+
* it's derived.
|
|
243
|
+
*
|
|
244
|
+
* Expression fidelity mirrors `Field`: a target/canonical `expression` and/or
|
|
245
|
+
* the original vendor `importedExpression` (+ `importedDialect`).
|
|
246
|
+
*/
|
|
247
|
+
export interface Metric {
|
|
248
|
+
name: string;
|
|
249
|
+
expression?: string;
|
|
250
|
+
importedExpression?: string;
|
|
251
|
+
importedDialect?: string;
|
|
252
|
+
dialects?: DialectExpression[];
|
|
253
|
+
stringForm?: boolean;
|
|
254
|
+
entity?: string;
|
|
255
|
+
authoredEntity?: string;
|
|
256
|
+
description?: string;
|
|
257
|
+
type?: DataType;
|
|
258
|
+
aiContext?: AiContext;
|
|
259
|
+
customExtensions?: CustomExtension[];
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* An action: a model-level, named write operation over the ontology -- the
|
|
263
|
+
* write-side counterpart to a metric's read. Like a metric it lives on the
|
|
264
|
+
* model (not a single entity) and may span several entities via its typed
|
|
265
|
+
* `parameters`.
|
|
266
|
+
*
|
|
267
|
+
* The model contributes only what the ontology can say that a plain tool schema
|
|
268
|
+
* cannot: parameters typed from the ontology (a projected one takes its type
|
|
269
|
+
* and its wording from the field it names) and the
|
|
270
|
+
* constraints that gate the call. The mechanics of running it are delegated to
|
|
271
|
+
* an `executor` (e.g. an MCP tool in Agent Registry); `description` is
|
|
272
|
+
* informational and does not affect runtime.
|
|
273
|
+
*/
|
|
274
|
+
export interface Action {
|
|
275
|
+
name: string;
|
|
276
|
+
description?: string;
|
|
277
|
+
executor?: Executor;
|
|
278
|
+
parameters: ActionParameter[];
|
|
279
|
+
guards?: string[];
|
|
280
|
+
affects?: AffectedConcept[];
|
|
281
|
+
aiContext?: AiContext;
|
|
282
|
+
customExtensions?: CustomExtension[];
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* One concept an action changes, and how.
|
|
286
|
+
*
|
|
287
|
+
* `concept` is the authored name of an entity or a relationship, kept verbatim
|
|
288
|
+
* for a lossless round-trip. Which of the two it is, is deliberately NOT
|
|
289
|
+
* recorded: it is a fact about the model, it changes nothing about what the
|
|
290
|
+
* entry means, and the same three operations apply either way. Whoever needs
|
|
291
|
+
* the distinction -- validate does, to know which fields the concept has --
|
|
292
|
+
* resolves it against the model, so there is one place it can be wrong instead
|
|
293
|
+
* of two. The loader warns about a name that resolves to neither.
|
|
294
|
+
*
|
|
295
|
+
* `operation` and `fields` are optional, and their absence means "unspecified"
|
|
296
|
+
* rather than "nothing". The open format accepts a bare name as shorthand for
|
|
297
|
+
* an entry with neither -- `affects: [Order]` is the coarse blast radius the
|
|
298
|
+
* proposal describes -- so a model can start there and add precision only
|
|
299
|
+
* where a rule needs it.
|
|
300
|
+
*/
|
|
301
|
+
export interface AffectedConcept {
|
|
302
|
+
concept: string;
|
|
303
|
+
operation?: ConceptOperation;
|
|
304
|
+
fields?: string[];
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* What an action does to a concept it affects.
|
|
308
|
+
*
|
|
309
|
+
* One vocabulary covers entities and relationships alike, because both admit
|
|
310
|
+
* the same three acts. An edge is not only added and removed: a many-to-many
|
|
311
|
+
* relationship is backed by a junction table with fields of its own (see
|
|
312
|
+
* Association), so modifying an enrollment's grade is as ordinary as modifying
|
|
313
|
+
* an order's total. Splitting the vocabulary by kind would make that change
|
|
314
|
+
* inexpressible and would buy a policy predicate nothing.
|
|
315
|
+
*/
|
|
316
|
+
export declare const CONCEPT_OPERATIONS: readonly ["create", "modify", "delete"];
|
|
317
|
+
export type ConceptOperation = typeof CONCEPT_OPERATIONS[number];
|
|
318
|
+
/**
|
|
319
|
+
* One input to an action. Always a SCALAR value: a parameter carries a value,
|
|
320
|
+
* never an object the runtime has to go and find first.
|
|
321
|
+
*
|
|
322
|
+
* There are two ways to author one.
|
|
323
|
+
*
|
|
324
|
+
* DERIVED. `concept` plus `field` PROJECT the parameter from a field the model
|
|
325
|
+
* already declares -- of an entity or of a relationship, the same two things
|
|
326
|
+
* `affects` may name:
|
|
327
|
+
*
|
|
328
|
+
* - {concept: Account, field: accountId}
|
|
329
|
+
* - {name: sourceAccountId, concept: Account, field: accountId,
|
|
330
|
+
* description: The account money leaves.}
|
|
331
|
+
*
|
|
332
|
+
* `name` defaults to the field's name, so the one-key form above declares a
|
|
333
|
+
* parameter called `accountId`. `type` MUST NOT be authored: it is the field's,
|
|
334
|
+
* and a parameter restating it is a second place for it to be wrong. The
|
|
335
|
+
* loader copies `type`, `description`, `label` and `aiContext` down from the
|
|
336
|
+
* field; the parameter's own wording wins over the field's where it states any,
|
|
337
|
+
* and the type never does.
|
|
338
|
+
*
|
|
339
|
+
* STANDALONE. Nothing in the model corresponds -- a free-text `memo`, a reason
|
|
340
|
+
* code -- so the parameter declares its own scalar `type` and names no field:
|
|
341
|
+
*
|
|
342
|
+
* - {name: memo, type: String, description: Why the credit was issued.}
|
|
343
|
+
*
|
|
344
|
+
* `concept` and `field` are kept on the IR ALONGSIDE what they resolved to, so
|
|
345
|
+
* the reference round-trips as the author wrote it while a consumer that does
|
|
346
|
+
* not have the model -- a catalog reader, an agent holding only the published
|
|
347
|
+
* aspect -- can still read the resolved type.
|
|
348
|
+
*
|
|
349
|
+
* `required` and `default` are always the parameter's own and are never
|
|
350
|
+
* inherited: a field describes what a thing HAS, and says nothing about whether
|
|
351
|
+
* a CALL must supply a value for it.
|
|
352
|
+
*
|
|
353
|
+
* `type` is optional only as an AUTHORED key. After a load it is populated on
|
|
354
|
+
* every parameter -- stated by a standalone one, resolved from the field by a
|
|
355
|
+
* derived one. The single exception is a parameter the loader could resolve
|
|
356
|
+
* neither way, which is kept verbatim and warned about, and which validate.ts
|
|
357
|
+
* then rejects.
|
|
358
|
+
*/
|
|
359
|
+
export interface ActionParameter {
|
|
360
|
+
name: string;
|
|
361
|
+
type?: string;
|
|
362
|
+
concept?: string;
|
|
363
|
+
field?: string;
|
|
364
|
+
description?: string;
|
|
365
|
+
label?: string;
|
|
366
|
+
aiContext?: AiContext;
|
|
367
|
+
required?: boolean;
|
|
368
|
+
default?: unknown;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* The mechanics of how an action is executed: exactly one kind, tagged so
|
|
372
|
+
* consumers can switch on it. The open format expresses it as an object with a
|
|
373
|
+
* single kind key (`mcp` / `rest` / `grpc`); the loader normalizes that to this
|
|
374
|
+
* discriminated union. Other kinds (SQL DML, CLI, ...) can be added later.
|
|
375
|
+
*/
|
|
376
|
+
export type Executor = {
|
|
377
|
+
kind: 'mcp';
|
|
378
|
+
mcp: McpExecutor;
|
|
379
|
+
} | {
|
|
380
|
+
kind: 'rest';
|
|
381
|
+
rest: RestExecutor;
|
|
382
|
+
} | {
|
|
383
|
+
kind: 'grpc';
|
|
384
|
+
grpc: GrpcExecutor;
|
|
385
|
+
} | {
|
|
386
|
+
kind: 'sql';
|
|
387
|
+
sql: SqlExecutor;
|
|
388
|
+
};
|
|
389
|
+
/**
|
|
390
|
+
* A SQL executor: the write itself, declared in the model as an ordered list of
|
|
391
|
+
* DML statements.
|
|
392
|
+
*
|
|
393
|
+
* The other three executor kinds name a system that performs the write, so what
|
|
394
|
+
* the write does is opaque to the model. This one contains it, which buys two
|
|
395
|
+
* things the opaque kinds cannot offer.
|
|
396
|
+
*
|
|
397
|
+
* - The blast radius is checkable. `affects` can be read against the
|
|
398
|
+
* statements rather than taken on trust.
|
|
399
|
+
* - A guard becomes a real gate. An MCP, REST or gRPC call commits inside a
|
|
400
|
+
* system the caller does not control, so a write it performed could not be
|
|
401
|
+
* rolled back if the rest of the action failed; a statement run in a
|
|
402
|
+
* database transaction can be. Guards settle before that transaction opens,
|
|
403
|
+
* so a refusal leaves the store untouched and no check ever observes the
|
|
404
|
+
* write it gates.
|
|
405
|
+
*
|
|
406
|
+
* The narrowness is the safety argument, and validate.ts enforces it. A
|
|
407
|
+
* statement is a single INSERT, UPDATE or DELETE. Every `@name` it binds names
|
|
408
|
+
* a parameter the action declares, so an argument reaches the store as a bound
|
|
409
|
+
* value and never as SQL. There is no control flow, no statement composed at
|
|
410
|
+
* call time, and no way for a caller to supply a statement of its own: an
|
|
411
|
+
* action whose body arrives with the call declares nothing, and a gate cannot
|
|
412
|
+
* check what was never declared.
|
|
413
|
+
*
|
|
414
|
+
* A row the statement inserts needs a primary key, and the statement is what
|
|
415
|
+
* decides where it comes from: a UUID function the store offers, a value the
|
|
416
|
+
* caller passes as an ordinary parameter, or the key column left out where it
|
|
417
|
+
* has a default. The runtime generates nothing on its behalf. A key that comes
|
|
418
|
+
* in as a parameter is one the caller chooses, and the check in validate.ts
|
|
419
|
+
* reads only a statement's first word, so an upsert passes and overwrites the
|
|
420
|
+
* row that key names.
|
|
421
|
+
*/
|
|
422
|
+
export interface SqlExecutor {
|
|
423
|
+
statements: string[];
|
|
424
|
+
}
|
|
425
|
+
export declare const SQL_EXECUTOR_VERBS: readonly ["INSERT", "UPDATE", "DELETE"];
|
|
426
|
+
/**
|
|
427
|
+
* An MCP executor: references a tool already registered in Agent Registry, by
|
|
428
|
+
* the MCP server's resource name plus the tool's in-server selector. Agent
|
|
429
|
+
* Registry is the canonical source consumed at runtime (e.g. by an agent).
|
|
430
|
+
*/
|
|
431
|
+
export interface McpExecutor {
|
|
432
|
+
server: string;
|
|
433
|
+
tool: string;
|
|
434
|
+
}
|
|
435
|
+
/** A REST executor: an HTTP endpoint and method. */
|
|
436
|
+
export interface RestExecutor {
|
|
437
|
+
endpoint: string;
|
|
438
|
+
method: string;
|
|
439
|
+
}
|
|
440
|
+
/** A gRPC executor: a fully-qualified service and method. */
|
|
441
|
+
export interface GrpcExecutor {
|
|
442
|
+
service: string;
|
|
443
|
+
method: string;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* What a violated constraint does to the write that tripped it.
|
|
447
|
+
*
|
|
448
|
+
* - `reject` the write is refused. Nobody is allowed to approve it, which
|
|
449
|
+
* is what makes the rule an invariant rather than a policy.
|
|
450
|
+
* - `escalate` the write is held and a person decides. The rule is a business
|
|
451
|
+
* threshold, so somebody is allowed to say yes.
|
|
452
|
+
* - `warn` the write proceeds and the violation is reported.
|
|
453
|
+
*
|
|
454
|
+
* An engine reading the catalog needs this in order to route. Without it every
|
|
455
|
+
* rule publishes with the same shape, and a $30 credit that needs a supervisor
|
|
456
|
+
* is indistinguishable from one that is simply forbidden.
|
|
457
|
+
*
|
|
458
|
+
* This is a disposition, not a magnitude, and the two are deliberately separate
|
|
459
|
+
* keys. `escalate` is not "between" reject and warn on a scale of badness: it is
|
|
460
|
+
* a different control flow, and what it really states is that an approver
|
|
461
|
+
* exists. Two rules can be equally grave -- both guarding a million-dollar write
|
|
462
|
+
* -- and differ only in whether anyone in the organization is entitled to say
|
|
463
|
+
* yes. See CONSTRAINT_SEVERITIES for the magnitude.
|
|
464
|
+
*
|
|
465
|
+
* `escalate` names that an approver exists. It does not name who: an approver
|
|
466
|
+
* role is not modeled yet.
|
|
467
|
+
*
|
|
468
|
+
* The consequence is a field rather than something a `judgment` states in its
|
|
469
|
+
* own prose, because three things need it without running a judge. An
|
|
470
|
+
* unrunnable judge -- none configured, a failed call, a timeout -- still has to
|
|
471
|
+
* route the breach it could not evaluate. A search for the rules that can stop
|
|
472
|
+
* a write cannot read prose. And a policy DSL states its effect in the rule
|
|
473
|
+
* head, so a rule whose consequence is only implied by its wording cannot be
|
|
474
|
+
* lowered into OPA or Cedar.
|
|
475
|
+
*
|
|
476
|
+
* A judgment may declare any of the three, `reject` included. What settles a
|
|
477
|
+
* judgment can decide two identical proposals differently, and `reject` leaves
|
|
478
|
+
* no appeal, so that pairing is the riskiest thing this model can express. It
|
|
479
|
+
* is still a bet an organization is entitled to place, and refusing to
|
|
480
|
+
* represent it would move the policy out of the catalog rather than prevent it.
|
|
481
|
+
* It is made auditable instead: `evaluation` publishes `judged` beside the
|
|
482
|
+
* word, so "unappealable rules settled by a model" is one query. `onViolation`
|
|
483
|
+
* is required on a judgment rather than defaulted, because a forgotten word
|
|
484
|
+
* would produce exactly that pairing silently.
|
|
485
|
+
*
|
|
486
|
+
* A constraint's word is the consequence of the one condition it states. A
|
|
487
|
+
* policy whose conditions carry different consequences is written as several
|
|
488
|
+
* constraints, which `guards` on an action lists together; the strictest
|
|
489
|
+
* consequence among the violated ones is what the action does. See
|
|
490
|
+
* docs/semantic-model/actions.md for a worked policy.
|
|
491
|
+
*
|
|
492
|
+
* STATUS: the declared word is published, read back, and routed on for the
|
|
493
|
+
* rules something settles. A judgment is settled where an action names it in
|
|
494
|
+
* `guards`, and `warn` reports while `reject` and `escalate` stop the call;
|
|
495
|
+
* `escalate` says so in the refusal, because nothing here has an approver to
|
|
496
|
+
* route to. An expression is still text nothing computes, so its word decides
|
|
497
|
+
* nothing yet.
|
|
498
|
+
*/
|
|
499
|
+
export declare const VIOLATION_EFFECTS: readonly ["reject", "escalate", "warn"];
|
|
500
|
+
export type ViolationEffect = (typeof VIOLATION_EFFECTS)[number];
|
|
501
|
+
/**
|
|
502
|
+
* How grave a violation of a constraint is, independent of what the engine does
|
|
503
|
+
* about it.
|
|
504
|
+
*
|
|
505
|
+
* Ranking and reporting want this: which of forty violations in a batch to show
|
|
506
|
+
* a human first, which to page on. Enforcement does not -- that is
|
|
507
|
+
* `onViolation`, and the split is the point. A `low` rule may still be an
|
|
508
|
+
* absolute `reject`, and a `critical` one may be a `warn` because the
|
|
509
|
+
* organization is not ready to block on it yet.
|
|
510
|
+
*
|
|
511
|
+
* The scale is the ordinary four-point one, and it avoids `warning` on purpose:
|
|
512
|
+
* a severity called `warning` sitting beside an effect called `warn` would read
|
|
513
|
+
* as the same statement made twice.
|
|
514
|
+
*
|
|
515
|
+
* STATUS: authored, published and read back. Nothing ranks or routes on it yet.
|
|
516
|
+
*/
|
|
517
|
+
export declare const CONSTRAINT_SEVERITIES: readonly ["critical", "high", "medium", "low"];
|
|
518
|
+
export type ConstraintSeverity = (typeof CONSTRAINT_SEVERITIES)[number];
|
|
519
|
+
/**
|
|
520
|
+
* A constraint: a model-level, named invariant over the ontology, stated in
|
|
521
|
+
* words and settled by a language model reading the call that would break it.
|
|
522
|
+
*
|
|
523
|
+
* A `judgment` is the rule as a sentence: *the credit memo must name a specific
|
|
524
|
+
* service failure*, *the order must be within the customer's standing limit*.
|
|
525
|
+
* It is the one body a constraint has, so settling any rule is a model call;
|
|
526
|
+
* `expression` is a reserved key the loader refuses. See "what a judgment
|
|
527
|
+
* costs" in docs/semantic-model/actions.md.
|
|
528
|
+
*
|
|
529
|
+
* A judgment states ONE condition, because the consequence is carried by
|
|
530
|
+
* `onViolation` and one word cannot route two branches. A policy whose branches
|
|
531
|
+
* end differently -- a missing approval is held for a person, a disguised
|
|
532
|
+
* transaction is refused -- is written as one constraint per branch, and
|
|
533
|
+
* `guards` on the action lists them together.
|
|
534
|
+
*
|
|
535
|
+
* What the catalog offers a judged rule is identity and governance, never
|
|
536
|
+
* determinism: one name, one owner, one version, one declared consequence, and
|
|
537
|
+
* the same text for every caller instead of prose re-improvised per call. A
|
|
538
|
+
* language model can still decide two identical proposals differently, and no
|
|
539
|
+
* schema changes that. `onViolation` is required so that the consequence of
|
|
540
|
+
* that non-determinism is always stated rather than inherited.
|
|
541
|
+
*
|
|
542
|
+
* STATUS: authored, validated, published and enforced. kcmd carries a
|
|
543
|
+
* constraint to Knowledge Catalog, where an agent can read the rules a model
|
|
544
|
+
* requires. Where an action names a constraint in `guards`, the judgment is
|
|
545
|
+
* settled before the transaction opens, which is why it reads the attempted
|
|
546
|
+
* call and never the state the write produced: a rule about the RESULT of a
|
|
547
|
+
* write is not something this body states. A caller that supplies no judge gets
|
|
548
|
+
* nothing settled -- the action is refused rather than run past the rule.
|
|
549
|
+
*
|
|
550
|
+
* `description` is the error text a violation would surface, so write it to
|
|
551
|
+
* steer an agent's next move -- "reduce the order quantity or choose another
|
|
552
|
+
* customer" -- rather than to label the rule.
|
|
553
|
+
*/
|
|
554
|
+
export interface Constraint {
|
|
555
|
+
name: string;
|
|
556
|
+
judgment?: string;
|
|
557
|
+
description?: string;
|
|
558
|
+
onViolation?: ViolationEffect;
|
|
559
|
+
severity?: ConstraintSeverity;
|
|
560
|
+
aiContext?: AiContext;
|
|
561
|
+
}
|
|
562
|
+
export interface DeploymentSpec {
|
|
563
|
+
name: string;
|
|
564
|
+
target: string;
|
|
565
|
+
profile?: string;
|
|
566
|
+
}
|
|
567
|
+
export interface ProfileEntityBinding {
|
|
568
|
+
name: string;
|
|
569
|
+
source?: string;
|
|
570
|
+
primaryKey?: string[];
|
|
571
|
+
uniqueKeys?: string[][];
|
|
572
|
+
fields?: Array<Pick<Field, 'name' | 'expression' | 'dialects' | 'stringForm' | 'importedExpression' | 'importedDialect'>>;
|
|
573
|
+
fieldsExclude?: string[];
|
|
574
|
+
}
|
|
575
|
+
export interface ProfileRelationshipBinding {
|
|
576
|
+
name: string;
|
|
577
|
+
fromColumns: string[];
|
|
578
|
+
toColumns: string[];
|
|
579
|
+
}
|
|
580
|
+
export interface ProfileSpec {
|
|
581
|
+
name: string;
|
|
582
|
+
entities: ProfileEntityBinding[];
|
|
583
|
+
relationships: ProfileRelationshipBinding[];
|
|
584
|
+
metricsExclude?: '*' | string[];
|
|
585
|
+
actions?: Array<{
|
|
586
|
+
name: string;
|
|
587
|
+
executor?: Executor | null;
|
|
588
|
+
}>;
|
|
589
|
+
}
|