Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions core-spec/behavior-layer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# OSI Extension: Behavior Layer (Actions, Rules, Effects)

**Applies to:** OSI Core v0.1.2
**Goal:** Provide a vendor-agnostic behavior layer for deterministic action planning and attribution (what changed/why), without breaking OSI Core compatibility.

## 1) Placement & Compatibility

This extension supports two equivalent placements:

1. **Preferred (first-class):** `semantic_model[].behavior`
2. **Legacy (embedded):** behavior JSON embedded in `dataset.custom_extensions[].data` (as a JSON string)

Backwards compatibility guidance:
- New models SHOULD use `semantic_model.behavior`.
- Tools MAY continue to support legacy embedded behavior for older models.
- If both are present, tools SHOULD define precedence (recommended: first-class `semantic_model.behavior` wins).

## 2) Top-level object: Behavior

Minimal structure:

| Field | Type | Required | Notes |
|---|---|---:|---|
| `namespace` | string | Yes | Grouping namespace (e.g. `SAP_P2P`) |
| `behavior_layer_version` | string | Yes | Schema evolution version |
| `actions` | array | No* | Preferred list of actions (`actions` or `action_types` must exist) |
| `action_types` | array | No* | Legacy alias of `actions` |
| `rules` | array | Yes | Constraints/guards for planning and governance |
| `metadata` | object | No | Optional governance metadata |

## 3) Actions

Actions describe what a tool/agent can do (API calls, workflows, scripts). OSI does not assume SQL.

Recommended action fields:
- `id` (stable identifier, e.g. `suppliers/block`)
- `title`, `description`
- `kind`: `command` or `query`
- `operation`: free-form operation name (e.g. `block`, `unblock`, `analyze`)
- `entity_name`: dataset name or conceptual entity
- `io_schema`: optional input/output JSON schema
- `effects`: optional machine-readable impact annotations

## 4) Effects (impact annotations)

Effects encode how an action reads/writes/derives datasets/fields.

Minimal effect fields:
- `entity`: dataset / field / metric / relationship
- `mode`: read / write / derive
- `selectors`: `{ dataset, field_names[] }` (or other selectors)
- optional: `impact_type`, `transition`, `set_value`, `confidence`, `notes`

Typical uses:
- Deterministic planning: validate state transitions and required prerequisites
- Attribution: explain “what changed/why” for a field or dataset

## 5) Legacy embedded example (dataset.custom_extensions)

```yaml
datasets:
- name: suppliers
source: sap.p2p.suppliers
custom_extensions:
- vendor_name: COMMON
data: |
{
"namespace": "SAP_P2P",
"behavior_layer_version": "0.1",
"action_types": [],
"rules": []
}
```

97 changes: 97 additions & 0 deletions core-spec/behavior-layer.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/open-semantic-interchange/OSI/core-spec/behavior-layer.schema.json",
"title": "OSI Behavior Layer (First-class)",
"description": "Schema for semantic_model.behavior (actions/rules/effects). Supports legacy alias action_types.",
"type": "object",
"additionalProperties": true,
"required": ["namespace", "behavior_layer_version", "rules"],
"anyOf": [
{ "required": ["actions"] },
{ "required": ["action_types"] }
],
"properties": {
"namespace": { "type": "string", "minLength": 1 },
"behavior_layer_version": { "type": "string", "minLength": 1 },
"metadata": { "type": "object", "additionalProperties": true },
"actions": {
"type": "array",
"description": "Preferred: list of actions supported by this semantic model. (Alias of legacy action_types)",
"items": { "$ref": "#/$defs/actionType" }
},
"action_types": {
"type": "array",
"description": "Legacy alias of actions. New models SHOULD use actions.",
"items": { "$ref": "#/$defs/actionType" }
},
"rules": {
"type": "array",
"items": { "$ref": "#/$defs/rule" }
}
},
"$defs": {
"actionType": {
"type": "object",
"additionalProperties": true,
"required": ["id", "title"],
"properties": {
"id": { "type": "string", "minLength": 1 },
"title": { "type": "string", "minLength": 1 },
"description": { "type": "string" },
"kind": { "type": "string", "enum": ["command", "query"] },
"operation": { "type": "string", "description": "Free-form operation name." },
"aggregate": { "type": "string" },
"entity_name": { "type": "string" },
"idempotency": { "type": "string", "enum": ["idempotent", "non_idempotent", "unknown"] },
"applies_to": { "type": "object", "additionalProperties": true },
"io_schema": { "type": "object", "additionalProperties": true },
"effects": {
"type": "array",
"description": "Optional: machine-readable impact annotations (what this action reads/writes/derives).",
"items": { "$ref": "#/$defs/effect" }
},
"examples": { "type": "array", "items": { "type": "string" } },
"tool_hint": { "type": "object", "additionalProperties": true },
"tags": { "type": "array", "items": { "type": "string" } },
"synonyms": { "type": "array", "items": { "type": "string" } },
"deprecated": { "type": "boolean" },
"version": { "type": "string" }
}
},
"effect": {
"type": "object",
"additionalProperties": true,
"required": ["entity", "mode"],
"properties": {
"entity": { "type": "string", "enum": ["dataset", "field", "metric", "relationship"] },
"mode": { "type": "string", "enum": ["read", "write", "derive"] },
"impact_type": { "type": "string" },
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

impact_type is a string here, but an implicit enum in spec.yaml.

"selectors": { "type": "object", "additionalProperties": true },
"transition": { "type": "object", "additionalProperties": true },
"set_value": { "type": "string" },
"confidence": { "type": "string", "enum": ["guaranteed", "likely", "unknown"] },
"notes": { "type": "string" },
"tags": { "type": "array", "items": { "type": "string" } }
}
},
"rule": {
"type": "object",
"additionalProperties": true,
"required": ["id", "title", "severity", "when", "constraint", "message"],
"properties": {
"id": { "type": "string", "minLength": 1 },
"title": { "type": "string", "minLength": 1 },
"description": { "type": "string" },
"severity": { "type": "string", "enum": ["error", "warn", "info"] },
"when": { "type": "object", "additionalProperties": true },
"if": { "type": "object", "additionalProperties": true },
"constraint": { "type": "object", "additionalProperties": true },
"message": { "type": "string", "minLength": 1 },
"remediation": { "type": "string" },
"references": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
"tags": { "type": "array", "items": { "type": "string" } }
}
}
}
}

88 changes: 87 additions & 1 deletion core-spec/osi-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"properties": {
"version": {
"type": "string",
"const": "0.1.1",
"const": "0.1.2",
"description": "OSI specification version"
},
"dialects": {
Expand Down Expand Up @@ -92,6 +92,89 @@
"required": ["vendor_name", "data"],
"additionalProperties": false
},
"Behavior": {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused here: it seems we have two behavior type definition:

  • in behavior-layer.schema.json with standalone schema
  • in osi-schema.json inline as $defs/Behavior, $defs/BehaviorAction, $defs/BehaviorEffect, $defs/BehaviorRule

I see already some differences before the two definitions.

Why not having osi-schema.json reference behavior-layer.schema.json via $ref.

I guess that having two schemas that must kept in sync manually will drift.

"type": "object",
"description": "Optional behavior layer for deterministic action planning and attribution (actions/rules/effects).",
"additionalProperties": true,
"required": ["namespace", "behavior_layer_version", "rules"],
"anyOf": [
{ "required": ["actions"] },
{ "required": ["action_types"] }
],
"properties": {
"namespace": { "type": "string", "minLength": 1 },
"behavior_layer_version": { "type": "string", "minLength": 1 },
"metadata": { "type": "object", "additionalProperties": true },
"actions": {
"type": "array",
"items": { "$ref": "#/$defs/BehaviorAction" }
},
"action_types": {
"type": "array",
"description": "Legacy alias of actions.",
"items": { "$ref": "#/$defs/BehaviorAction" }
},
"rules": {
"type": "array",
"items": { "$ref": "#/$defs/BehaviorRule" }
}
}
},
"BehaviorAction": {
"type": "object",
"additionalProperties": true,
"required": ["id", "title"],
"properties": {
"id": { "type": "string", "minLength": 1 },
"title": { "type": "string", "minLength": 1 },
"description": { "type": "string" },
"kind": { "type": "string", "enum": ["command", "query"] },
"operation": { "type": "string" },
"entity_name": { "type": "string" },
"idempotency": { "type": "string", "enum": ["idempotent", "non_idempotent", "unknown"] },
"applies_to": { "type": "object", "additionalProperties": true },
"io_schema": { "type": "object", "additionalProperties": true },
"effects": {
"type": "array",
"items": { "$ref": "#/$defs/BehaviorEffect" }
},
"tags": { "type": "array", "items": { "type": "string" } },
"synonyms": { "type": "array", "items": { "type": "string" } }
}
},
"BehaviorEffect": {
"type": "object",
"additionalProperties": true,
"required": ["entity", "mode"],
"properties": {
"entity": { "type": "string", "enum": ["dataset", "field", "metric", "relationship"] },
"mode": { "type": "string", "enum": ["read", "write", "derive"] },
"impact_type": { "type": "string" },
"selectors": { "type": "object", "additionalProperties": true },
"transition": { "type": "object", "additionalProperties": true },
"set_value": { "type": "string" },
"confidence": { "type": "string", "enum": ["guaranteed", "likely", "unknown"] },
"notes": { "type": "string" }
}
},
"BehaviorRule": {
"type": "object",
"description": "Declarative rule/constraint for planning and governance.",
"additionalProperties": true,
"required": ["id", "title", "severity", "when", "constraint", "message"],
"properties": {
"id": { "type": "string", "minLength": 1 },
"title": { "type": "string", "minLength": 1 },
"description": { "type": "string" },
"severity": { "type": "string", "enum": ["error", "warn", "info"] },
"when": { "type": "object", "additionalProperties": true },
"if": { "type": "object", "additionalProperties": true },
"constraint": { "type": "object", "additionalProperties": true },
"message": { "type": "string", "minLength": 1 },
"remediation": { "type": "string" },
"tags": { "type": "array", "items": { "type": "string" } }
}
},
"DialectExpression": {
"type": "object",
"description": "Expression in a specific dialect",
Expand Down Expand Up @@ -330,6 +413,9 @@
},
"description": "Quantifiable measures spanning datasets"
},
"behavior": {
"$ref": "#/$defs/Behavior"
},
"custom_extensions": {
"type": "array",
"items": {
Expand Down
80 changes: 78 additions & 2 deletions core-spec/spec.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# OSI - Core Metadata Specification

**Version:** 0.1.1
**Version:** 0.1.2

## Goals

Expand All @@ -16,7 +16,8 @@
4. [Relationships](#relationships)
5. [Fields](#fields)
6. [Metrics](#metrics)
7. [Examples](#examples)
7. [Behavior (Actions / Rules / Effects)](#behavior-actions--rules--effects)
8. [Examples](#examples)

---

Expand Down Expand Up @@ -62,6 +63,7 @@ The top-level container that represents a complete semantic model, including dat
| `datasets` | array | Yes | Collection of logical datasets (fact and dimension tables) |
| `relationships` | array | No | Defines how logical datasets are connected |
| `metrics` | array | No | Quantifiable measures defined as aggregate expessions on fields from logical datsets |
| `behavior` | object | No | Optional behavior layer for deterministic action planning and attribution |
| `custom_extensions` | array | No | Vendor-specific attributes for extensibility |

### Example
Expand All @@ -75,13 +77,87 @@ semantic_model:
datasets: []
relationships: []
metrics: []
behavior:
namespace: "SALES"
behavior_layer_version: "0.1"
actions: []
rules: []
custom_extensions:
- vendor_name: DBT
data: '{"project_name": "tpcds_analytics", "models_path": "models/semantic"}'
```

---

## Behavior (Actions / Rules / Effects)

Behavior is an optional, vendor-agnostic layer for **deterministic action planning** and **attribution** (what changed/why).

This repository supports two equivalent placements:
1) **Preferred (first-class):** `semantic_model[].behavior`
2) **Backwards-compatible (legacy):** embed behavior-layer JSON under `custom_extensions` (e.g. `vendor_name: COMMON`)

### Schema (semantic_model.behavior)

| Field | Type | Required | Description |
|------|------|----------|-------------|
| `namespace` | string | Yes | Namespace/group for actions and rules (e.g. `SAP_P2P`) |
| `behavior_layer_version` | string | Yes | Version for behavior schema evolution |
| `actions` | array | No* | Preferred list of actions (`actions` or `action_types` required) |
| `action_types` | array | No* | Legacy alias of `actions` (for backwards compatibility) |
| `rules` | array | Yes | Declarative constraints/guards for planning and governance |
| `metadata` | object | No | Governance metadata (owner/tags/last_updated, etc.) |

### Action Schema (high-level)

Actions represent executable intents (API calls, workflows, tools). This spec intentionally does **not** assume SQL.

| Field | Type | Required | Description |
|------|------|----------|-------------|
| `id` | string | Yes | Action id, e.g. `suppliers/block` |
| `title` | string | Yes | Human-friendly title |
| `kind` | string | No | `command` or `query` |
| `operation` | string | No | Free-form operation name (e.g. `block`, `unblock`, `analyze`) |
| `effects` | array | No | Optional machine-readable impact annotations |

### Effects (impact annotations)

Effects encode how an action changes datasets/fields for:
- plan validation (state transitions / prohibited follow-ups)
- attribution (what changed/why for a field or dataset)

Minimal effect fields:
`entity` (dataset/field/metric/relationship), `mode` (read/write/derive), `selectors` (dataset + field_names),
optional `impact_type`, `transition`, `set_value`.

### Example

```yaml
semantic_model:
- name: sap_p2p
datasets: []
behavior:
namespace: "SAP_P2P"
behavior_layer_version: "0.1"
actions:
- id: suppliers/block
title: Block supplier
kind: command
operation: block
entity_name: suppliers
effects:
- entity: field
mode: write
impact_type: state_transition
selectors:
dataset: suppliers
field_names: [status]
set_value: Blocked
rules: []
```

---

## Datasets

Logical datasets represent business entities or concepts (fact and dimension tables). They contain fields and define the structure of the data.
Expand Down
Loading