Skip to content
Merged
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
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
# Changelog

## [2.3.0] - 2026-05-20

### Added
- New OPTIONAL artifact category — Algorithm Cards — defined in
`specification/13-algorithm-cards.md` and validated by
`schemas/algorithm-card.schema.json`. A Card is a typed, versioned
governance wrapper for a single algorithm invoked behind a resource
target. Cards live in the package's `algorithms/` folder (path
configurable via `paths.algorithms`) and supply intent, IO contract,
ownership, lifecycle, validation history, and OPTIONAL extensions
for ML, crypto, privacy, risk, and prompt-based implementations.
- Manifest schema gains two OPTIONAL top-level properties:
`algorithm_cards` (boolean) and `paths.algorithms` (string). Neither
is required; both live outside the closed `cornerstones` block.
- Resource mapping schema gains one OPTIONAL `algorithm_card` property
per target, referencing a Card by `id` or relative path.
- New validation rule `SEM-012` (ERROR): Algorithm Card reference does
not resolve.
- New OPTIONAL conformance block in `10-conformance-checklist.md` for
implementations that support Algorithm Cards.
- New example `examples/approve-expense-l4` now demonstrates a Card
attached to one of its resource targets.

### Note
- Fully additive, backward-compatible. Every package valid under 2.2.x
remains valid under 2.3.0. Algorithm Cards extend the Resources
cornerstone — they do NOT become a fifth cornerstone. The four
cornerstones (BPMN, DMN, CMMN, Resources + Mapping) remain
authoritative and unchanged. Hence a minor bump.

## [2.2.0] - 2026-05-17

### Added
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ UAPF is a disciplined format for storing and versioning organizational processes
- Conformance checklist: [`specification/10-conformance-checklist.md`](specification/10-conformance-checklist.md)
- Semantic validation: [`specification/11-semantic-validation.md`](specification/11-semantic-validation.md)
- YAML guidelines: [`specification/12-yaml-guidelines.md`](specification/12-yaml-guidelines.md)
- Algorithm Cards: [`specification/13-algorithm-cards.md`](specification/13-algorithm-cards.md)

## Schemas (normative)
- UAPF manifest schema: [`schemas/uapf-manifest.schema.json`](schemas/uapf-manifest.schema.json)
Expand All @@ -66,6 +67,7 @@ UAPF is a disciplined format for storing and versioning organizational processes
- Lifecycle metadata schema: [`schemas/lifecycle.schema.json`](schemas/lifecycle.schema.json)
- Policies schema: [`schemas/policies.schema.json`](schemas/policies.schema.json)
- MCP tool schemas: [`schemas/mcp-tools.schema.json`](schemas/mcp-tools.schema.json)
- Algorithm Card schema: [`schemas/algorithm-card.schema.json`](schemas/algorithm-card.schema.json)

## Normative boundaries
Only the following are normative SSOT for UAPF v1:
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.2.0
2.3.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
kind: uapf.algorithm.card

id: algo.expense_approval.policy_lookup_assistant
version: "1.0.0"
name: "Policy lookup assistant"
intent: >
Assists evaluation of expense-approval policy by retrieving the
applicable internal policy text for a given expense category and
amount, and presenting it in a structured form for the approver
and for the DMN policy decision.

algorithm_kind: extractor

io:
inputs:
- id: expense_category
type: string
- id: expense_amount
type: decimal
unit: EUR
outputs:
- id: applicable_policy_text
type: string
- id: policy_section_ref
type: string

implementation:
type: external
medium: vendor_saas
uri: "https://example.com/policy-api/v1/lookup"
hash: "sha256:0000000000000000000000000000000000000000000000000000000000000000"

determinism: deterministic
side_effects: external_call

owners:
- type: team
id: finance-process-office
contact: finance-process-office@example.com

lifecycle:
status: approved
since: "2026-05-20"

validation:
last_validated: "2026-05-20"
test_suite: ../tests/algorithms/policy_lookup_assistant.test.yaml
validator: finance-process-office

audit:
log_inputs: redacted
log_outputs: full
retention: "1y"
1 change: 1 addition & 0 deletions examples/approve-expense-l4/resources/mappings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ targets:
capabilities:
- capability.policy.lookup
- capability.decision.assist
algorithm_card: algo.expense_approval.policy_lookup_assistant

- id: role.manager
type: human_role
Expand Down
2 changes: 2 additions & 0 deletions examples/approve-expense-l4/uapf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ paths:
cmmn: cmmn
resources: resources
metadata: metadata
algorithms: algorithms
algorithm_cards: true
owners:
- type: team
id: finance-process-office
Expand Down
Binary file modified examples/archives/approve-expense-l4.uapf
Binary file not shown.
178 changes: 178 additions & 0 deletions schemas/algorithm-card.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://uapf.dev/schemas/algorithm-card.schema.json",
"title": "UAPF Algorithm Card Schema",
"type": "object",
"additionalProperties": false,
"required": ["kind", "id", "version", "name", "intent", "algorithm_kind", "io", "implementation", "owners", "lifecycle"],
"properties": {
"kind": { "const": "uapf.algorithm.card" },
"id": {
"type": "string",
"pattern": "^algo\\.[a-z0-9][a-z0-9._-]+$"
},
"version": {
"type": "string",
"pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$"
},
"name": { "type": "string", "minLength": 1 },
"intent": { "type": "string", "minLength": 20 },
"algorithm_kind": {
"type": "string",
"enum": ["formula", "classifier", "extractor", "ml_model", "rule_table", "crypto", "redactor", "router", "validator", "aggregator", "transformer", "emitter", "other"]
},
"io": {
"type": "object",
"additionalProperties": false,
"required": ["inputs", "outputs"],
"properties": {
"inputs": { "type": "array", "items": { "$ref": "#/$defs/io_field" } },
"outputs": { "type": "array", "items": { "$ref": "#/$defs/io_field" } }
}
},
"implementation": {
"oneOf": [
{ "$ref": "#/$defs/impl_inline" },
{ "$ref": "#/$defs/impl_external" },
{ "$ref": "#/$defs/impl_composite" }
]
},
"owners": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/owner_ref" }
},
"lifecycle": {
"type": "object",
"additionalProperties": false,
"required": ["status"],
"properties": {
"status": { "enum": ["draft", "review", "approved", "deprecated", "retired"] },
"since": { "type": "string", "format": "date" }
}
},
"determinism": { "enum": ["deterministic", "stochastic", "learned"] },
"confidence": {
"type": "object",
"additionalProperties": false,
"properties": {
"type": { "enum": ["none", "probability", "score", "categorical"] },
"threshold": { "type": "number", "minimum": 0, "maximum": 1 },
"below_threshold": { "type": "string" }
}
},
"side_effects": { "enum": ["pure", "reads_state", "writes_state", "external_call"] },
"complexity": { "type": "object" },
"failure_mode": { "type": "string" },
"limitations": { "type": "array", "items": { "type": "string" } },
"reference": {
"type": "object",
"additionalProperties": false,
"properties": {
"legal": { "type": "string" },
"methodology": { "type": "string" },
"standard": { "type": "string" },
"url": { "type": "string", "format": "uri" }
}
},
"validation": {
"type": "object",
"additionalProperties": false,
"properties": {
"last_validated": { "type": "string", "format": "date" },
"test_suite": { "type": "string" },
"validator": { "type": "string" },
"methodology": { "type": "string" },
"metrics": { "type": "object", "additionalProperties": { "type": "number" } }
}
},
"audit": {
"type": "object",
"additionalProperties": false,
"properties": {
"log_inputs": { "enum": ["none", "redacted", "full"] },
"log_outputs": { "enum": ["none", "redacted", "full"] },
"retention": { "type": "string", "pattern": "^[0-9]+[ymdh]$" }
}
},
"ml": { "type": "object" },
"crypto": { "type": "object" },
"privacy": { "type": "object" },
"risk": { "type": "object" },
"prompt": { "type": "object" }
},
"$defs": {
"io_field": {
"type": "object",
"additionalProperties": false,
"required": ["id", "type"],
"properties": {
"id": { "type": "string", "pattern": "^[a-z_][a-z0-9_]*$" },
"type": { "enum": ["string", "integer", "decimal", "boolean", "date", "datetime", "object", "array", "binary", "stream", "probability"] },
"schema": { "type": "string" },
"unit": { "type": "string" },
"cardinality": { "enum": ["single", "optional", "array", "stream"] },
"constraints": { "type": "object" },
"documentation": { "type": "string" }
}
},
"impl_inline": {
"type": "object",
"additionalProperties": false,
"required": ["type", "language"],
"properties": {
"type": { "const": "inline" },
"language": { "enum": ["feel", "dmn", "rego", "regex", "sql", "wasm"] },
"body": { "type": "string" },
"body_ref": { "type": "string" }
},
"oneOf": [
{ "required": ["body"] },
{ "required": ["body_ref"] }
]
},
"impl_external": {
"type": "object",
"additionalProperties": false,
"required": ["type", "medium", "uri", "hash"],
"properties": {
"type": { "const": "external" },
"medium": { "enum": ["llm_prompt", "ml_model", "http_api", "mcp_tool", "native_binary", "crypto_module", "vendor_saas"] },
"uri": { "type": "string" },
"hash": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
"runtime": { "type": "object" }
}
},
"impl_composite": {
"type": "object",
"additionalProperties": false,
"required": ["type", "composed_of"],
"properties": {
"type": { "const": "composite" },
"composed_of": {
"type": "array",
"minItems": 2,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["ref", "version"],
"properties": {
"ref": { "type": "string", "pattern": "^algo\\." },
"version": { "type": "string" }
}
}
}
}
},
"owner_ref": {
"type": "object",
"additionalProperties": false,
"required": ["type", "id"],
"properties": {
"type": { "enum": ["team", "person", "role"] },
"id": { "type": "string", "minLength": 1 },
"contact": { "type": "string" }
}
}
}
}
4 changes: 4 additions & 0 deletions schemas/resource-mapping.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
"schedule": { "type": "string", "description": "Cron expression or 'always'" },
"timezone": { "type": "string", "default": "UTC" }
}
},
"algorithm_card": {
"type": "string",
"description": "Reference to an Algorithm Card describing this target. Either the Card's id (algo.<scope>.<name>) or a relative path to the .card.yaml file (see chapter 13)."
}
}
},
Expand Down
8 changes: 8 additions & 0 deletions schemas/uapf-manifest.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
"metadata": {
"type": "string",
"default": "metadata"
},
"algorithms": {
"type": "string",
"default": "algorithms"
}
}
},
Expand Down Expand Up @@ -252,6 +256,10 @@
"guardrails": {
"type": "string",
"description": "Path, relative to the package root, to the guardrails file enforced at every capability call (e.g. 'resources/guardrails.yaml')."
},
"algorithm_cards": {
"type": "boolean",
"description": "Whether this package contains Algorithm Cards (see chapter 13)."
}
},
"$defs": {
Expand Down
8 changes: 8 additions & 0 deletions specification/02-process-cornerstones.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,11 @@ Resources describe who/what executes work and how tasks bind to those resources.
- MCP tools/endpoints.

UAPF does not redefine BPMN/DMN/CMMN semantics; it packages them with governance and bindings.

### Algorithm Cards (extension)

Resource targets MAY carry deeper governance metadata via Algorithm
Cards (see chapter 13). Algorithm Cards extend, but do not constitute,
the Resources cornerstone. The four cornerstones remain BPMN, DMN,
CMMN, and Resources + Mapping.

12 changes: 12 additions & 0 deletions specification/10-conformance-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,16 @@ An implementation claiming UAPF conformance MUST satisfy the following.
- [ ] Validates version fields are strings, not numbers
- [ ] Rejects invalid type coercions in required fields


## Algorithm Cards (13) — OPTIONAL

If an implementation supports Algorithm Cards:

- [ ] Recognizes `algorithm_cards: true` and `paths.algorithms` in the manifest
- [ ] Validates each `*.card.yaml` against `schemas/algorithm-card.schema.json`
- [ ] Resolves `target.algorithm_card` references during workspace validation (SEM-012)
- [ ] Exposes Cards via MCP under `uapf://algorithms/...` when MCP export is enabled
- [ ] Includes Card reference in `uapf.resolve_resources` output when target carries one
- [ ] Ignores Card extension blocks (`ml`, `crypto`, `privacy`, `risk`, `prompt`) it does not understand without raising errors

An implementation MUST state which sections it supports.
Loading
Loading