diff --git a/CHANGELOG.md b/CHANGELOG.md index d311f9e..a449005 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index af1ae55..8afe619 100644 --- a/README.md +++ b/README.md @@ -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) @@ -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: diff --git a/VERSION b/VERSION index ccbccc3..cc6612c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.0 +2.3.0 \ No newline at end of file diff --git a/examples/approve-expense-l4/algorithms/policy_lookup_assistant.card.yaml b/examples/approve-expense-l4/algorithms/policy_lookup_assistant.card.yaml new file mode 100644 index 0000000..62e5b34 --- /dev/null +++ b/examples/approve-expense-l4/algorithms/policy_lookup_assistant.card.yaml @@ -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" diff --git a/examples/approve-expense-l4/resources/mappings.yaml b/examples/approve-expense-l4/resources/mappings.yaml index b4947d0..ceac9fe 100644 --- a/examples/approve-expense-l4/resources/mappings.yaml +++ b/examples/approve-expense-l4/resources/mappings.yaml @@ -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 diff --git a/examples/approve-expense-l4/uapf.yaml b/examples/approve-expense-l4/uapf.yaml index 630275f..d65cc05 100644 --- a/examples/approve-expense-l4/uapf.yaml +++ b/examples/approve-expense-l4/uapf.yaml @@ -16,6 +16,8 @@ paths: cmmn: cmmn resources: resources metadata: metadata + algorithms: algorithms +algorithm_cards: true owners: - type: team id: finance-process-office diff --git a/examples/archives/approve-expense-l4.uapf b/examples/archives/approve-expense-l4.uapf index 06291b1..e99ddbc 100644 Binary files a/examples/archives/approve-expense-l4.uapf and b/examples/archives/approve-expense-l4.uapf differ diff --git a/schemas/algorithm-card.schema.json b/schemas/algorithm-card.schema.json new file mode 100644 index 0000000..37c8273 --- /dev/null +++ b/schemas/algorithm-card.schema.json @@ -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" } + } + } + } +} diff --git a/schemas/resource-mapping.schema.json b/schemas/resource-mapping.schema.json index 60c8635..3fcbf06 100644 --- a/schemas/resource-mapping.schema.json +++ b/schemas/resource-mapping.schema.json @@ -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..) or a relative path to the .card.yaml file (see chapter 13)." } } }, diff --git a/schemas/uapf-manifest.schema.json b/schemas/uapf-manifest.schema.json index 8599343..7d425f2 100644 --- a/schemas/uapf-manifest.schema.json +++ b/schemas/uapf-manifest.schema.json @@ -107,6 +107,10 @@ "metadata": { "type": "string", "default": "metadata" + }, + "algorithms": { + "type": "string", + "default": "algorithms" } } }, @@ -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": { diff --git a/specification/02-process-cornerstones.md b/specification/02-process-cornerstones.md index 38e4c9a..e33b47f 100644 --- a/specification/02-process-cornerstones.md +++ b/specification/02-process-cornerstones.md @@ -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. + diff --git a/specification/10-conformance-checklist.md b/specification/10-conformance-checklist.md index e86cecb..3b35cf0 100644 --- a/specification/10-conformance-checklist.md +++ b/specification/10-conformance-checklist.md @@ -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. diff --git a/specification/11-semantic-validation.md b/specification/11-semantic-validation.md index 242f9d1..2ccb5ab 100644 --- a/specification/11-semantic-validation.md +++ b/specification/11-semantic-validation.md @@ -91,6 +91,22 @@ FOR EACH file IN dmn/*.dmn: ASSERT file CONTAINS ``` + +### 11.3.4 Algorithm Card Reference Integrity + +When a resource target carries an `algorithm_card` property, the +referenced Card MUST resolve. + +**Validation Rule SEM-012:** +``` +FOR EACH target IN resources/mappings.yaml: + IF target.algorithm_card IS PRESENT: + IF target.algorithm_card MATCHES /^algo\./: + ASSERT target.algorithm_card EXISTS as id IN any algorithms/*.card.yaml + ELSE: + ASSERT target.algorithm_card EXISTS as path RELATIVE TO package root +``` + ## 11.4 Error Codes | Code | Severity | Description | @@ -106,9 +122,10 @@ FOR EACH file IN dmn/*.dmn: | SEM-009 | ERROR | Duplicate binding for same source | | SEM-010 | WARNING | Fallback target not defined | | SEM-011 | ERROR | Cornerstone file missing diagram interchange (DI) | +| SEM-012 | ERROR | Algorithm Card reference does not resolve | ## 11.5 Conformance -- Implementations MUST validate SEM-001 through SEM-003, SEM-007 through SEM-009, and SEM-011 +- Implementations MUST validate SEM-001 through SEM-003, SEM-007 through SEM-009, SEM-011, and SEM-012 - Implementations SHOULD validate SEM-004 through SEM-006 and SEM-010 - Implementations MUST report error codes with messages diff --git a/specification/13-algorithm-cards.md b/specification/13-algorithm-cards.md new file mode 100644 index 0000000..d0aed31 --- /dev/null +++ b/specification/13-algorithm-cards.md @@ -0,0 +1,221 @@ +# 13 — Algorithm Cards (Normative) + +## 13.0 Purpose + +This chapter defines the **Algorithm Card** artifact: a typed, versioned +governance wrapper for a single algorithm invoked behind a resource target. +A Card supplies the metadata required to identify, audit, validate, and +replace an algorithm without requiring the algorithm's implementation to +live inside the UAPF package. + +Algorithm Cards extend the Resources cornerstone (see chapter 02). They +do NOT constitute a new cornerstone. The four cornerstones — BPMN, DMN, +CMMN, Resources + Mapping — defined in chapter 02 remain authoritative +and unchanged. + +## 13.1 Scope + +The Resources cornerstone declares *where* work is dispatched +(`ai_agent`, `human_role`, `system_api`, `mcp_tool`, `external_service`). +It does NOT declare *what* the dispatched algorithm does, who is +accountable for it, when it was last validated, or how it behaves under +uncertainty. Algorithm Cards fill that gap. + +A Card is OPTIONAL. Packages whose resource targets are sufficiently +described by their existing target declaration MAY omit Cards entirely. +Packages whose targets invoke probabilistic models, learned classifiers, +third-party services, or any algorithm whose behaviour is not self-evident +from the target declaration alone SHOULD provide a Card per such target. + +UAPF does NOT standardize through this chapter: +- the source language or representation of algorithms, +- the runtime that executes them, +- the format of training data, model weights, or external services + referenced by a Card, +- any specific AI, ML, cryptographic, or privacy technique. + +A Card describes; it does not implement. + +## 13.2 The Algorithm Card artifact + +A Card MUST be a YAML file under the package's `algorithms/` folder. + +The folder location is configured by `paths.algorithms` in the manifest; +the default value is `algorithms`. + +A Card MUST validate against `schemas/algorithm-card.schema.json`. + +A Card file MUST use the suffix `.card.yaml`. + +## 13.3 Required fields + +Every Card MUST declare: + +| Field | Constraint | +|---|---| +| `kind` | The literal string `uapf.algorithm.card` | +| `id` | Globally unique identifier, pattern `^algo\.[a-z0-9][a-z0-9._-]+$` | +| `version` | Semantic version string (chapter 12 quoting rules apply) | +| `name` | Human-readable title | +| `intent` | Plain-language description of what the algorithm does | +| `algorithm_kind` | One of: `formula`, `classifier`, `extractor`, `ml_model`, `rule_table`, `crypto`, `redactor`, `router`, `validator`, `aggregator`, `transformer`, `emitter`, `other` | +| `io` | Typed input/output contract | +| `implementation` | Discriminated by `type`: `inline`, `external`, or `composite` | +| `owners` | At least one owner, structurally consistent with `metadata/ownership.yaml` | +| `lifecycle` | Status, structurally consistent with `metadata/lifecycle.yaml` | + +## 13.4 Implementation forms + +The `implementation` block declares where the algorithm body lives. It is +a discriminated union on the `type` field. + +### 13.4.1 `inline` + +The algorithm body is present in the Card. Used when the algorithm is +declaratively expressible in a supported language. The Card MUST declare: + +- `type`: the literal `inline` +- `language`: one of `feel`, `dmn`, `rego`, `regex`, `sql`, `wasm` +- `body`: the algorithm body as a string, OR +- `body_ref`: a path to a file in the package containing the body + +Exactly one of `body` or `body_ref` MUST be present. + +### 13.4.2 `external` + +The algorithm body lives outside the package. The Card MUST declare: + +- `type`: the literal `external` +- `medium`: one of `llm_prompt`, `ml_model`, `http_api`, `mcp_tool`, + `native_binary`, `crypto_module`, `vendor_saas` +- `uri`: addressable reference (URL, file path, registry reference) +- `hash`: SHA-256 of the referenced artifact, format `sha256:` +- `runtime`: OPTIONAL medium-specific runtime configuration + +### 13.4.3 `composite` + +The Card refers to two or more other Cards composed together. The Card +MUST declare: + +- `type`: the literal `composite` +- `composed_of`: ordered list of `{ ref, version }` referencing other + Cards by `id` + +Composite resolution is recursive. Implementations MUST detect cycles +(see SEM-008 in chapter 11). + +## 13.5 IO contract + +The `io` block MUST contain `inputs` and `outputs`, each a list of +field declarations. Each field MUST declare `id` and `type`. Each field +MAY declare `schema` (path to JSON Schema for complex types), `unit` +(SI unit, ISO 4217 currency, or domain-specific symbol), `cardinality` +(`single` | `optional` | `array` | `stream`; default `single`), and +`constraints` (a JSON Schema constraint subset). + +## 13.6 Optional fields + +A Card MAY declare: + +| Field | Purpose | +|---|---| +| `determinism` | `deterministic` (default), `stochastic`, `learned` | +| `confidence` | Uncertainty model: `type`, `threshold`, `below_threshold` action | +| `side_effects` | `pure` (default), `reads_state`, `writes_state`, `external_call` | +| `complexity` | Latency and complexity-class declarations | +| `failure_mode` | Behaviour when output cannot be produced | +| `limitations` | Free-text list of known limitations | +| `reference` | Legal / methodology / standard citation | +| `validation` | `last_validated`, `test_suite`, `validator`, `methodology`, `metrics` | +| `audit` | Logging configuration: `log_inputs`, `log_outputs`, `retention` | + +## 13.7 Type-specific extensions + +A Card MAY include OPTIONAL extension blocks. Extensions are scoped by +`algorithm_kind` and carry domain-specific metadata that does not fit the +universal core. The following extensions are defined in this version: + +- `ml` — applies when `algorithm_kind` is `ml_model` or `classifier` + with an ML implementation. Links to Model Card URL, training data + reference, fairness analysis. +- `crypto` — applies when `algorithm_kind` is `crypto`. FIPS certificate, + algorithm identifier, key length, quantum-resistance flag. +- `privacy` — applies when the algorithm processes personal data. + Technique, parameters, re-identification risk class. +- `risk` — algorithmic risk classification and human-oversight + requirements. +- `prompt` — applies when `implementation.medium` is `llm_prompt`. + Model identifier, prompt hash, temperature, max tokens. + +Implementations MUST ignore extensions they do not understand. +Extensions MUST NOT contradict the universal core. + +## 13.8 Relationship to Resource targets + +A resource target in `resources/mappings.yaml` MAY reference a Card via +the optional `algorithm_card` property. The reference is the Card's `id` +or a relative path to the Card file. + +```yaml +targets: + - id: classifier_x + type: ai_agent + name: "Generic classifier" + algorithm_card: algo.example.classifier_x +``` + +The Card and the target describe complementary facets of the same +resource: the target describes the *binding surface* (how to reach the +algorithm), the Card describes the *algorithmic surface* (what the +algorithm does, with what guarantees). + +A target MAY reference at most one Card. Multiple targets MAY reference +the same Card. Implementations MUST resolve Card references during +validation; unresolved references MUST raise SEM-012. + +## 13.9 Manifest declaration + +A package containing Algorithm Cards SHOULD declare: + +```yaml +algorithm_cards: true +paths: + algorithms: algorithms +``` + +`algorithm_cards` is a manifest-level boolean declaring intent. +`paths.algorithms` declares the folder name if not the default. Both +fields are OPTIONAL and live at manifest top level — not inside the +closed `cornerstones` block. + +## 13.10 Testing + +Per-Card tests SHOULD be stored under +`tests/algorithms/.test.yaml`. + +Tests carry a uniform shape regardless of Card `algorithm_kind` or +`implementation.type`: input cases, expected outputs, and a tolerance +declaration. Deterministic algorithms use exact-match tolerance; +stochastic algorithms use distributional tolerance with explicit +pass-rate thresholds. + +A passing test run is the operational definition of validation. CI +SHOULD update `validation.last_validated` on the Card when the test +suite passes against the current `implementation.hash` (for external) +or `body_ref` content hash (for inline). + +The detailed test format is non-normative and lives in implementation +guides. + +## 13.11 Cards in MCP export + +When a package is exported to MCP per chapter 06, Cards MUST be +exposable as resources under `uapf://algorithms/...` and queryable via +`uapf.list` and `uapf.get_artifact`. + +The `uapf.resolve_resources` tool MUST include the Card reference in +the resolved binding when a target's `algorithm_card` is present. + +## 13.12 Conformance + +See chapter 10 for the Algorithm Cards conformance section.