@agenticprimitives/ontology 1.0.0-alpha.4 → 1.0.0-alpha.41

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.
Files changed (183) hide show
  1. package/README.md +59 -21
  2. package/cbox/agent-facet-shapes.shacl.ttl +130 -0
  3. package/cbox/capability-catalog-shapes.shacl.ttl +284 -0
  4. package/cbox/card-projection-shapes.shacl.ttl +216 -0
  5. package/cbox/consultation-shapes.shacl.ttl +85 -0
  6. package/cbox/content-vocabulary.ttl +52 -0
  7. package/cbox/controlled-vocabularies.ttl +224 -4
  8. package/cbox/discovery-graph-shapes.shacl.ttl +284 -0
  9. package/cbox/familyoffice-shapes.shacl.ttl +92 -0
  10. package/cbox/familyoffice-vocabulary.ttl +48 -0
  11. package/cbox/geo-vocabulary.ttl +36 -0
  12. package/cbox/guidance-vocabulary.ttl +22 -0
  13. package/cbox/interaction-shapes.shacl.ttl +218 -0
  14. package/cbox/interaction-vocabulary.ttl +159 -0
  15. package/cbox/judgment-shapes.shacl.ttl +83 -0
  16. package/cbox/naming-registry-shapes.shacl.ttl +272 -0
  17. package/cbox/org-team-shapes.shacl.ttl +184 -0
  18. package/cbox/privacy-credential-shapes.shacl.ttl +187 -0
  19. package/cbox/profile-facet-vocabulary.ttl +50 -0
  20. package/cbox/registry-vocabulary.ttl +86 -0
  21. package/cbox/run-measures-shapes.shacl.ttl +59 -0
  22. package/cbox/run-provenance-shapes.shacl.ttl +264 -0
  23. package/cbox/scope-vocabulary.ttl +112 -0
  24. package/cbox/skill-grounding-vocabulary.ttl +18 -0
  25. package/cbox/skill-vocabulary.ttl +50 -0
  26. package/context.jsonld +37 -1
  27. package/dist/arg-types.d.ts +60 -0
  28. package/dist/arg-types.d.ts.map +1 -0
  29. package/dist/arg-types.js +143 -0
  30. package/dist/arg-types.js.map +1 -0
  31. package/dist/artifacts.d.ts +9 -2
  32. package/dist/artifacts.d.ts.map +1 -1
  33. package/dist/artifacts.js +153 -2
  34. package/dist/artifacts.js.map +1 -1
  35. package/dist/contact-fields.d.ts +28 -0
  36. package/dist/contact-fields.d.ts.map +1 -0
  37. package/dist/contact-fields.js +38 -0
  38. package/dist/contact-fields.js.map +1 -0
  39. package/dist/decisions.d.ts +69 -0
  40. package/dist/decisions.d.ts.map +1 -0
  41. package/dist/decisions.js +98 -0
  42. package/dist/decisions.js.map +1 -0
  43. package/dist/evaluation-context.d.ts +134 -0
  44. package/dist/evaluation-context.d.ts.map +1 -0
  45. package/dist/evaluation-context.js +136 -0
  46. package/dist/evaluation-context.js.map +1 -0
  47. package/dist/governance.d.ts +84 -0
  48. package/dist/governance.d.ts.map +1 -0
  49. package/dist/governance.js +88 -0
  50. package/dist/governance.js.map +1 -0
  51. package/dist/grounded-vocabulary.d.ts +29 -0
  52. package/dist/grounded-vocabulary.d.ts.map +1 -0
  53. package/dist/grounded-vocabulary.js +110 -0
  54. package/dist/grounded-vocabulary.js.map +1 -0
  55. package/dist/household.d.ts +19 -0
  56. package/dist/household.d.ts.map +1 -0
  57. package/dist/household.js +41 -0
  58. package/dist/household.js.map +1 -0
  59. package/dist/index.d.ts +1091 -3
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +1323 -5
  62. package/dist/index.js.map +1 -1
  63. package/dist/outcomes.d.ts +47 -0
  64. package/dist/outcomes.d.ts.map +1 -0
  65. package/dist/outcomes.js +40 -0
  66. package/dist/outcomes.js.map +1 -0
  67. package/dist/participant-vocabulary.d.ts +57 -0
  68. package/dist/participant-vocabulary.d.ts.map +1 -0
  69. package/dist/participant-vocabulary.js +66 -0
  70. package/dist/participant-vocabulary.js.map +1 -0
  71. package/dist/party-roles.d.ts +115 -0
  72. package/dist/party-roles.d.ts.map +1 -0
  73. package/dist/party-roles.js +343 -0
  74. package/dist/party-roles.js.map +1 -0
  75. package/dist/payload-classes.d.ts +22 -0
  76. package/dist/payload-classes.d.ts.map +1 -0
  77. package/dist/payload-classes.js +30 -0
  78. package/dist/payload-classes.js.map +1 -0
  79. package/dist/plan-shapes.d.ts +18 -0
  80. package/dist/plan-shapes.d.ts.map +1 -0
  81. package/dist/plan-shapes.js +38 -0
  82. package/dist/plan-shapes.js.map +1 -0
  83. package/dist/principles.generated.d.ts +11 -0
  84. package/dist/principles.generated.d.ts.map +1 -0
  85. package/dist/principles.generated.js +293 -0
  86. package/dist/principles.generated.js.map +1 -0
  87. package/dist/published-works.d.ts +13 -0
  88. package/dist/published-works.d.ts.map +1 -0
  89. package/dist/published-works.js +18 -0
  90. package/dist/published-works.js.map +1 -0
  91. package/dist/relations.d.ts +44 -0
  92. package/dist/relations.d.ts.map +1 -0
  93. package/dist/relations.js +104 -0
  94. package/dist/relations.js.map +1 -0
  95. package/dist/run-measures-context.d.ts +74 -0
  96. package/dist/run-measures-context.d.ts.map +1 -0
  97. package/dist/run-measures-context.js +77 -0
  98. package/dist/run-measures-context.js.map +1 -0
  99. package/dist/run-provenance-context.d.ts +315 -0
  100. package/dist/run-provenance-context.d.ts.map +1 -0
  101. package/dist/run-provenance-context.js +323 -0
  102. package/dist/run-provenance-context.js.map +1 -0
  103. package/dist/transitions.d.ts +42 -0
  104. package/dist/transitions.d.ts.map +1 -0
  105. package/dist/transitions.js +100 -0
  106. package/dist/transitions.js.map +1 -0
  107. package/dist/vault-records.d.ts +74 -0
  108. package/dist/vault-records.d.ts.map +1 -0
  109. package/dist/vault-records.js +777 -0
  110. package/dist/vault-records.js.map +1 -0
  111. package/dist/versions.generated.d.ts +262 -0
  112. package/dist/versions.generated.d.ts.map +1 -0
  113. package/dist/versions.generated.js +318 -0
  114. package/dist/versions.generated.js.map +1 -0
  115. package/evaluation.jsonld +133 -0
  116. package/mappings/actor-context-standards.ttl +89 -0
  117. package/mappings/agent-discovery-standards.ttl +127 -0
  118. package/mappings/collaboration-crosswalk-actors.ttl +30 -0
  119. package/mappings/collaboration-crosswalk-authority.ttl +31 -0
  120. package/mappings/collaboration-crosswalk-guidance.ttl +29 -0
  121. package/mappings/collaboration-crosswalk-intent.ttl +29 -0
  122. package/mappings/collaboration-crosswalk-messaging.ttl +37 -0
  123. package/mappings/collaboration-crosswalk-organization.ttl +66 -0
  124. package/mappings/collaboration-crosswalk-protocols.ttl +49 -0
  125. package/mappings/collaboration-crosswalk-skills.ttl +50 -0
  126. package/mappings/collaboration-profile.ttl +82 -0
  127. package/mappings/commerce-engagement-crosswalk.ttl +83 -0
  128. package/mappings/spine-standards.ttl +83 -0
  129. package/package.json +31 -9
  130. package/run-measures.jsonld +34 -0
  131. package/run-provenance.jsonld +314 -0
  132. package/tbox/actor-context.ttl +145 -0
  133. package/tbox/agent-resolution.ttl +308 -0
  134. package/tbox/agreement.ttl +77 -0
  135. package/tbox/attestation.ttl +156 -0
  136. package/tbox/card-projection.ttl +350 -0
  137. package/tbox/constraints.ttl +150 -0
  138. package/tbox/contact.ttl +61 -0
  139. package/tbox/content.ttl +76 -0
  140. package/tbox/context.ttl +508 -0
  141. package/tbox/coordination.ttl +263 -0
  142. package/tbox/core.ttl +325 -7
  143. package/tbox/dcat-imports.ttl +19 -0
  144. package/tbox/discovery.ttl +273 -0
  145. package/tbox/dqv-imports.ttl +29 -0
  146. package/tbox/earl-imports.ttl +32 -0
  147. package/tbox/engagement.ttl +349 -0
  148. package/tbox/entitlement.ttl +41 -0
  149. package/tbox/estate.ttl +78 -0
  150. package/tbox/evaluation.ttl +330 -0
  151. package/tbox/execution.ttl +720 -0
  152. package/tbox/familyoffice.ttl +87 -0
  153. package/tbox/fulfillment.ttl +140 -0
  154. package/tbox/geo.ttl +28 -0
  155. package/tbox/governance.ttl +67 -0
  156. package/tbox/guidance.ttl +40 -0
  157. package/tbox/household.ttl +142 -0
  158. package/tbox/identity.ttl +133 -6
  159. package/tbox/inference.ttl +177 -0
  160. package/tbox/intents.ttl +241 -0
  161. package/tbox/interaction.ttl +297 -0
  162. package/tbox/messaging.ttl +244 -0
  163. package/tbox/naming.ttl +114 -0
  164. package/tbox/org.ttl +410 -0
  165. package/tbox/payload.ttl +94 -0
  166. package/tbox/payment.ttl +124 -0
  167. package/tbox/plan.ttl +169 -0
  168. package/tbox/principles.ttl +212 -0
  169. package/tbox/privacy-credential.ttl +436 -0
  170. package/tbox/profile.ttl +107 -0
  171. package/tbox/prov-imports.ttl +73 -0
  172. package/tbox/registry.ttl +382 -0
  173. package/tbox/resolution.ttl +108 -0
  174. package/tbox/scope.ttl +59 -0
  175. package/tbox/security-exposure.ttl +102 -0
  176. package/tbox/situation.ttl +56 -0
  177. package/tbox/skills.ttl +316 -0
  178. package/tbox/skos-imports.ttl +54 -0
  179. package/tbox/transition.ttl +63 -0
  180. package/tbox/trust.ttl +210 -0
  181. package/tbox/values.ttl +81 -0
  182. package/tbox/verification-receipt.ttl +134 -0
  183. package/versions.adoption.json +173 -0
package/README.md CHANGED
@@ -1,13 +1,12 @@
1
1
  # @agenticprimitives/ontology
2
2
 
3
- The **monorepo-wide formal vocabulary** for agentic primitives — the off-chain
4
- source of truth that the on-chain ontology ([ADR-0009](../../docs/architecture/decisions/0009-on-chain-ontology-shacl-naming.md))
5
- instantiates and that [`identity-directory`](../identity-directory) (spec 223)
6
- conforms to.
3
+ **A trust substrate is only as coherent as its vocabulary.** When thirty packages, forty-two contracts, and a knowledge graph all talk about agents, credentials, custody, and delegation, "what exactly is a `CredentialFacet`" cannot have thirty answers. This package is the monorepo-wide formal vocabulary — the off-chain source of truth that the on-chain ontology ([ADR-0009](../../docs/architecture/decisions/0009-on-chain-ontology-shacl-naming.md)) instantiates and that [`identity-directory`](../identity-directory) (spec 223) conforms to.
7
4
 
8
- See [spec 225](../../specs/225-ontology.md) for the full contract and
9
- [ADR-0018](../../docs/architecture/decisions/0018-agenticprimitives-wide-formal-ontology.md)
10
- for the decision.
5
+ It is deliberately declarative: it names and constrains, it never authorizes. The vocabulary root depends on nothing — not even `@agenticprimitives/types` — so every other package can reference the same IRIs without inverting the dependency graph.
6
+
7
+ > Part of [agenticprimitives](../../README.md) — the trust substrate for the agent economy: one canonical Smart Agent identity with custody, delegation, naming, credentials, and audit evidence designed as one system.
8
+
9
+ See [spec 225](../../specs/225-ontology.md) for the full contract and [ADR-0018](../../docs/architecture/decisions/0018-agenticprimitives-wide-formal-ontology.md) for the decision.
11
10
 
12
11
  ## Layout (T-box / C-box / A-box)
13
12
 
@@ -16,12 +15,15 @@ context.jsonld @context — namespace prefix → IRI bindings
16
15
  tbox/ RDFS/OWL schema (classes + properties), per domain
17
16
  cbox/ SHACL shapes + SKOS controlled vocabularies (codelists)
18
17
  abox/ example / fixture instances (tests + golden vectors only)
18
+ mappings/ external-standard crosswalks (HCS / ERC-8004, spec 226)
19
19
  src/index.ts typed IRI constants + artifact paths
20
20
  ```
21
21
 
22
- This mirrors the reference ontology work
23
- (`agentictrustlabs/smart-agent/docs/ontology`): T-box = terminology, C-box =
24
- constraints + controlled vocabularies, A-box = instances.
22
+ T-box = terminology, C-box = constraints + controlled vocabularies, A-box = instances.
23
+
24
+ UML class-diagram documentation of the T-box — inheritance + relationships per domain area —
25
+ lives in [`docs/tbox/`](docs/tbox/README.md). For the plain-language version — the principles
26
+ the vocabulary protects and why — start with [`docs/story.md`](docs/story.md).
25
27
 
26
28
  ## Usage
27
29
 
@@ -32,20 +34,56 @@ CLASS.CanonicalAgentId; // "https://agenticprimitives.dev/ns/core#CanonicalAgent
32
34
  artifactPath(ARTIFACTS.tbox[0]); // absolute path to tbox/core.ttl — load into a SPARQL store
33
35
  ```
34
36
 
35
- The package is **declarative**: it ships the vocabulary artifacts and exposes
36
- their IRIs/paths. It contains no runtime auth/policy logic. SHACL-engine
37
- validation over instances, and the live A-box knowledge graph (a SPARQL store —
38
- Ontotext GraphDB reference), are wired by consumers in Phase 2 (spec 225 §11).
37
+ Two entry points, split on purpose:
38
+
39
+ - **Main entry (browser-safe)** — pure IRI constants: `NS`, `CLASS`, `PREDICATE`, `SHAPE`, `ONTOLOGY_VERSION`. No Node builtins; this is what `identity-directory` (and through it, browser apps) imports.
40
+ - **`/artifacts` subpath (Node-only)** — `ARTIFACTS` + `artifactPath(rel)` to resolve the shipped TTL/JSON-LD files for a SPARQL loader or SHACL engine. Server-side only.
41
+
42
+ ## How it's different
43
+
44
+ Generic SKOS/SHACL toolchains manage vocabularies as documents — governed in an editor, detached from the systems that depend on them, drifting the moment runtime code changes. Here the vocabulary is load-bearing and lockstep-checked in three directions:
45
+
46
+ 1. **On chain** — a shape or predicate here must match its on-chain counterpart in `OntologyTermRegistry` / `ShapeRegistry` (spec 225 §8); drift is logged as a finding, not tolerated as skew.
47
+ 2. **In TypeScript** — the IRIs mirror the branded types in [`types`](../types) (`CanonicalAgentId`, `Assurance`, …). One brand; this package names the IRI, never redefines the type.
48
+ 3. **Across standards** — `mappings/*.ttl` carries explicit crosswalks to external agent-identity standards (HCS, ERC-8004, OASF) instead of informal "roughly corresponds to" prose.
49
+
50
+ And it ships light: no heavy RDF/SHACL libraries in the published surface — consumers wire their own engines against the artifacts.
51
+
52
+ ## Scope
39
53
 
40
- ## Scope (Phase 1)
54
+ Bounded to generic AP primitives: identity, credential, custody, delegation, audit, naming, org, registry/discovery, trust, public exposure findings, and the substrate-spine T-box class definitions (spec 225 §11.5). Runtime SHACL shapes for product flows live in their owning packages; GraphDB A-box ingestion shapes for discovery live in `cbox/discovery-graph-shapes.shacl.ttl`; vertical vocabulary remains app-owned ([ADR-0021](../../docs/architecture/decisions/0021-generic-packages-vs-white-label-apps.md)).
41
55
 
42
- Bounded to the agent-trust core: identity, credential, custody, delegation,
43
- audit, naming, org. Marketplace / intents / geo are out of scope (spec 225 §11).
56
+ The discovery ontology deliberately builds from the domain-derived vocabulary shape in Agent Explorer's `apps/ontology/ontology` modules — `core.ttl`, `discovery.ttl`, `descriptors.ttl`, `erc8004.ttl`, `hol.ttl`, `oasf.ttl`, and `trust.ttl` — while refining it into AP-native namespaces rooted in PROV-O and DOLCE+DnS/DUL.
57
+
58
+ ### Module map (additions by spec)
59
+
60
+ | Concern | T-box | C-box |
61
+ |---------|-------|-------|
62
+ | Identity, kinds, derived types | `tbox/core.ttl`, `tbox/identity.ttl` | `cbox/controlled-vocabularies.ttl`, `cbox/canonical-agent-id-shape.shacl.ttl` |
63
+ | Typed naming, registry core (spec 346) | `tbox/naming.ttl`, `tbox/registry.ttl` | `cbox/naming-registry-shapes.shacl.ttl`, `cbox/registry-vocabulary.ttl` |
64
+ | Capabilities, claims, taxonomy mappings (specs 251/325/347 §5) | `tbox/skills.ttl` (`aps:SkillTaxonomyMapping` — `relation` = a SKOS mapping property) | `cbox/skill-vocabulary.ttl`, `cbox/capability-catalog-shapes.shacl.ttl` |
65
+ | **Canonical profile → A2A Agent Card → projection → publication → external identity binding (spec 347 §11; ADR-0062)** | `tbox/card-projection.ttl` — a second module of the `ap:` core namespace; PROV-O-grounded (generation/publication ⊑ `prov:Activity`; artifact/releases ⊑ `prov:Entity`; publisher/adapter ⊑ `prov:SoftwareAgent`); "canonical agent" ≡ `ap:Agent`, no second class | `cbox/card-projection-shapes.shacl.ttl` — public card metadata; projection provenance (all **eight** digests as named sub-properties of `ap:hasDigest`); external binding; **public disclosure boundary** (SPARQL-targeted at `ap:disclosureScope "public"`: no loopback / private / link-local endpoint, no vault locator; absence of scope is private). Codelists `ap:lossCategoryScheme`, card-release / projection-instance / binding lifecycles, `ap:bindingVerificationStateScheme`, `ap:digestRoleScheme` in `cbox/controlled-vocabularies.ttl` |
66
+ | Agentic interaction (spec 340) | `tbox/interaction.ttl` | `cbox/interaction-shapes.shacl.ttl`, `cbox/interaction-vocabulary.ttl` |
67
+ | Coordination / engagement / execution (specs 332/336/330) | `tbox/coordination.ttl`, `tbox/engagement.ttl`, `tbox/execution.ttl`, `tbox/plan.ttl` | — |
44
68
 
45
69
  ## What this is NOT
46
70
 
47
- - Not the TS types — `@agenticprimitives/types` owns `CanonicalAgentId`,
48
- `Assurance`, etc.; this package names the IRIs. One brand.
71
+ - Not the TS types — `@agenticprimitives/types` owns `CanonicalAgentId`, `Assurance`, etc.; this package names the IRIs. One brand.
49
72
  - Not the runtime CAIP-10 builder — that is `@agenticprimitives/agent-profile`.
50
- - Not an authority — it names + validates; it never grants custody or mints
51
- identity.
73
+ - Not an authority — it names and validates; it never grants custody or mints identity.
74
+
75
+ ## Status
76
+
77
+ **Phase 1 implemented** — the T/C/A-box artifacts, mappings, and the declarative TS surface ship today. SHACL-engine validation over instances and the live A-box knowledge graph (a SPARQL store — Ontotext GraphDB reference, projected by `identity-directory`) are Phase 2, wired by consumers per spec 225 §11 — and even then the ontology stays a validator, never an authority.
78
+
79
+ > Testnet/pilot-ready. Production launch is gated on the public checklist in the root README — including third-party contract audit and governance key rotation. Track every security finding live in [`docs/audits/findings.yaml`](../../docs/audits/findings.yaml).
80
+
81
+ **Authoritative spec:** [`specs/225-ontology.md`](../../specs/225-ontology.md). Bounded surface: `CLAUDE.md` + `capability.manifest.json`.
82
+
83
+ ## Build
84
+
85
+ ```bash
86
+ pnpm --filter @agenticprimitives/ontology typecheck
87
+ pnpm --filter @agenticprimitives/ontology test
88
+ pnpm --filter @agenticprimitives/ontology build
89
+ ```
@@ -0,0 +1,130 @@
1
+ # C-box — SHACL over the public agent PROFILE facet and the projected TRUST FABRIC (spec 331).
2
+ #
3
+ # Validates the A-box the discovery indexer writes: approf:* profile properties (including the
4
+ # three facets registered by governor tx 0x53acec54…) and the aptrust:TrustGraphEdge /
5
+ # apatt:Attestation nodes whose vocabulary tbox/trust.ttl now declares.
6
+ #
7
+ # Enforcement posture (spec 225 §11 / PD-19): these shapes are DECLARED here and enforced by the
8
+ # indexer's TS validators at projection time and by a SHACL engine over graph snapshots. They are
9
+ # never on a hot path and never an authorization input.
10
+ #
11
+ # WHAT A VIOLATION MEANS: a conformance failure here means the WRITER published a malformed facet
12
+ # — it does not mean the agent is untrustworthy, and it must never silently drop the agent from a
13
+ # result set. Fail LOUD to the indexer's audit, fail OPEN to fewer signals for the matcher
14
+ # (ADR-0013 / spec 329 §4: degrade to fewer signals, never to fewer candidates).
15
+
16
+ @prefix sh: <http://www.w3.org/ns/shacl#> .
17
+ @prefix approf: <https://agenticprimitives.dev/ns/profile#> .
18
+ @prefix aptrust: <https://agenticprimitives.dev/ns/trust#> .
19
+ @prefix apatt: <https://agenticprimitives.dev/ns/attestation#> .
20
+ @prefix ap: <https://agenticprimitives.dev/ns/core#> .
21
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
22
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
23
+
24
+ # ═══ The public profile facet ═══════════════════════════════════════════════
25
+
26
+ approf:AgentProfileShape a sh:NodeShape ;
27
+ sh:targetClass approf:AgentProfile ;
28
+ rdfs:label "AgentProfileShape" ;
29
+ rdfs:comment "Every property is OPTIONAL. A public profile is opt-in in whole and in part (facet-registries invariant 3/4): an agent that publishes nothing is conformant, and absence is never a defect." ;
30
+
31
+ sh:property [
32
+ sh:path approf:displayName ; sh:datatype xsd:string ; sh:maxCount 1 ; sh:maxLength 128 ;
33
+ ] ;
34
+ sh:property [
35
+ sh:path approf:description ; sh:datatype xsd:string ; sh:maxCount 1 ; sh:maxLength 2048 ;
36
+ sh:description "SA-keyed. The node-keyed name-record description is apnam:description and MUST NOT be emitted under this IRI (facet-registries G8)." ;
37
+ ] ;
38
+ sh:property [
39
+ sh:path approf:skills ; sh:datatype xsd:string ; sh:maxCount 1 ; sh:maxLength 2048 ;
40
+ sh:description "Comma-joined declared capability projections. Spec 331 migrates the value space to canonical catalog ids; both are legal during the dual-publish window." ;
41
+ ] ;
42
+
43
+ # ── approf:declaresCapabilityId — one triple per parsed id (spec 331) ────
44
+ sh:property [
45
+ sh:path approf:declaresCapabilityId ;
46
+ sh:datatype xsd:string ;
47
+ sh:pattern "^[a-z][a-z0-9]*:[a-z0-9]+(-[a-z0-9]+)*$" ;
48
+ sh:message "A capability id is a lowercase CURIE: '<prefix>:<kebab-slug>', e.g. 'adv:succession-plan-design'. keccak256 of this exact string is the on-chain skillId, so spelling is identity — it is never normalized, corrected, or case-folded at read time." ;
49
+ ] ;
50
+
51
+ # ── G2: languages, BCP-47 ───────────────────────────────────────────────
52
+ sh:property [
53
+ sh:path approf:languages ; sh:datatype xsd:string ; sh:maxCount 1 ; sh:maxLength 256 ;
54
+ sh:pattern "^[a-z]{2,3}(-[a-z0-9]{2,8})*(,[a-z]{2,3}(-[a-z0-9]{2,8})*)*$" ;
55
+ sh:message "atl:languages must be comma-separated, lowercase, well-formed BCP-47 tags with no spaces: 'es,en,pt-br'. See cbox/profile-facet-vocabulary.ttl for the subtag-prefix matching rule — substring matching is forbidden." ;
56
+ ] ;
57
+
58
+ # ── G3: regions, GeoFeatureRegistry-drawn ───────────────────────────────
59
+ sh:property [
60
+ sh:path approf:regions ; sh:datatype xsd:string ; sh:maxCount 1 ; sh:maxLength 256 ;
61
+ sh:pattern "^[A-Z0-9]{2,8}(-[A-Z0-9]{1,3})?(,[A-Z0-9]{2,8}(-[A-Z0-9]{1,3})?)*$" ;
62
+ sh:message "atl:regions must be comma-separated UPPERCASE codes with no spaces: 'EU,ES,ES-CT'. Each code must resolve to an ISO 3166 entry or a registered GeoFeatureRegistry feature; a code that resolves to neither is a conformance failure, NOT a free-text fallback (spec 251 forward-compatibility)." ;
63
+ ] ;
64
+
65
+ # ── G4: focus areas, open but shaped ────────────────────────────────────
66
+ sh:property [
67
+ sh:path approf:focusAreas ; sh:datatype xsd:string ; sh:maxCount 1 ; sh:maxLength 512 ;
68
+ sh:pattern "^[a-z0-9]+(-[a-z0-9]+)*(,[a-z0-9]+(-[a-z0-9]+)*)*$" ;
69
+ sh:message "atl:focusAreas must be comma-separated lowercase-hyphenated subject labels. A focus area is a subject domain (apctx:KnowledgeDomain), never a declared capability, and never a hard filter." ;
70
+ ] .
71
+
72
+ # ── The encoding this migration removes, stated as a shape ──────────────────
73
+
74
+ approf:NoEncodedFacetInSkillsShape a sh:NodeShape ;
75
+ sh:targetClass approf:AgentProfile ;
76
+ rdfs:label "NoEncodedFacetInSkillsShape" ;
77
+ rdfs:comment "Spec 331 §hack-1. Before the three facet predicates existed, languages, regions, jurisdictions and focus areas were stuffed into atl:skills as prefixed tokens (lang-es, region-eu, jurisdiction-spain, focus-*). The prefixes were deliberate and honest — they kept the encoding VISIBLE rather than silently conflating a language with a capability. Now that real predicates exist, the encoding is debt: a token matching these prefixes is a facet that belongs in atl:languages / atl:regions / atl:focusAreas. SEVERITY IS sh:Warning, not sh:Violation, and stays that way until the migration's dual-publish window closes — a live agent mid-migration is correct, not broken." ;
78
+ sh:property [
79
+ sh:path approf:skills ;
80
+ sh:severity sh:Warning ;
81
+ sh:not [ sh:pattern "(^|,\\s*)(lang|region|jurisdiction|focus)-" ] ;
82
+ sh:message "atl:skills carries an ENCODED facet token (lang-*/region-*/jurisdiction-*/focus-*). Publish it as atl:languages, atl:regions or atl:focusAreas instead — a subject domain, a place and a language are not declared capabilities (ADR-0051)." ;
83
+ ] .
84
+
85
+ # ═══ The projected trust fabric ═════════════════════════════════════════════
86
+
87
+ aptrust:TrustGraphEdgeShape a sh:NodeShape ;
88
+ sh:targetClass aptrust:TrustGraphEdge ;
89
+ rdfs:label "TrustGraphEdgeShape" ;
90
+ rdfs:comment "A projected AgentRelationship edge. Subject and object are ABSOLUTE and required: one on-chain record is shared by both endpoints under one derived IRI, so the node must state the edge without reference to who is reading it. The endpoint-relative views (ap:relatedAgent, ap:edgeDirection) hang on the agent and are validated by AgentTrustFabricShape below." ;
91
+ sh:property [ sh:path ap:edgeId ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
92
+ sh:pattern "^0x[0-9a-f]{64}$" ;
93
+ sh:message "edgeId is the deterministic on-chain computeEdgeId(subject, object, type) as lowercase 0x-hex." ] ;
94
+ sh:property [ sh:path ap:edgeSubject ; sh:minCount 1 ; sh:maxCount 1 ;
95
+ sh:message "Every edge has exactly one proposing subject — proposeEdge requires msg.sender == subject." ] ;
96
+ sh:property [ sh:path ap:edgeObject ; sh:minCount 1 ; sh:maxCount 1 ] ;
97
+ sh:property [ sh:path ap:relationshipTypeId ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
98
+ sh:message "The raw bytes32 type id is ALWAYS emitted, including for governor-registered types whose label does not resolve (ADR-0013: no silent gaps)." ] ;
99
+ sh:property [ sh:path ap:relationshipType ; sh:datatype xsd:string ; sh:maxCount 1 ;
100
+ sh:description "The resolved well-known label. Optional by design — an unresolved type is queryable via relationshipTypeId." ] ;
101
+ sh:property [ sh:path ap:edgeStatus ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
102
+ sh:in ( "PROPOSED" "CONFIRMED" "ACTIVE" "REVOKED" ) ;
103
+ sh:message "Only ACTIVE edges may inform trust scoring: a PROPOSED edge is one party talking to itself, and REVOKED is terminal." ] ;
104
+ sh:property [ sh:path ap:edgeSubject ;
105
+ sh:disjoint ap:edgeObject ;
106
+ sh:message "An agent cannot relate to itself — the contract rejects subject == object, and a self-edge in the graph is a projection defect." ] .
107
+
108
+ apatt:AttestationShape a sh:NodeShape ;
109
+ sh:targetClass apatt:Attestation ;
110
+ rdfs:label "AttestationShape" ;
111
+ rdfs:comment "A projected AttestationRegistry row. The chain holds a COMMITMENT (credentialHash); the body is off-chain and never reaches the knowledge graph (ADR-0040). Discovery may therefore learn THAT an attestation of type X from issuer Y exists — never what it says." ;
112
+ sh:property [ sh:path apatt:uid ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
113
+ sh:pattern "^0x[0-9a-f]{64}$" ] ;
114
+ sh:property [ sh:path apatt:credentialType ; sh:datatype xsd:string ; sh:maxCount 1 ] ;
115
+ sh:property [ sh:path ap:attestationIssuer ; sh:minCount 1 ; sh:maxCount 1 ;
116
+ sh:description "The SIGNER, recomputed from the EIP-712 digest on chain — never msg.sender, which the registry leaves unconstrained. This is what lets an endorsement be relayed by a third party while the authority stays with the issuer." ] ;
117
+ sh:property [ sh:path ap:attestationValid ; sh:datatype xsd:boolean ; sh:minCount 1 ; sh:maxCount 1 ;
118
+ sh:description "isValid(uid) at index time. NOTE AR-06: there is no issuer-revoke entrypoint, so issuer-side revocation (offchainCredentialStatusList) is NOT reflected here. A consumer treating this as a full revocation check is wrong." ] ;
119
+ sh:property [ sh:path apatt:credentialHash ; sh:maxCount 1 ;
120
+ sh:description "A commitment. Never dereferenced by discovery, never a searchable field." ] .
121
+
122
+ ap:AgentTrustFabricShape a sh:NodeShape ;
123
+ sh:targetClass ap:Agent ;
124
+ rdfs:label "AgentTrustFabricShape" ;
125
+ rdfs:comment "The endpoint-RELATIVE denormalizations and the counts trustScore reads." ;
126
+ sh:property [ sh:path ap:edgeDirection ; sh:datatype xsd:string ; sh:in ( "subject" "object" ) ] ;
127
+ sh:property [ sh:path ap:edgeCount ; sh:datatype xsd:integer ; sh:maxCount 1 ; sh:minInclusive 0 ] ;
128
+ sh:property [ sh:path ap:activeEdgeCount ; sh:datatype xsd:integer ; sh:maxCount 1 ; sh:minInclusive 0 ] ;
129
+ sh:property [ sh:path ap:attestationCount ; sh:datatype xsd:integer ; sh:maxCount 1 ; sh:minInclusive 0 ] ;
130
+ sh:property [ sh:path ap:validAttestationCount ; sh:datatype xsd:integer ; sh:maxCount 1 ; sh:minInclusive 0 ] .
@@ -0,0 +1,284 @@
1
+ # C-box — SHACL for capability CATALOGS and REALIZATION CONTRACTS
2
+ # (spec 330 W0 §7, unparked by spec 331; capability-architecture.md §2 + §5).
3
+ #
4
+ # Three groups:
5
+ # 1. What a well-formed capability + definition + catalog looks like.
6
+ # 2. The ANTI-PATTERN AXIOMS from architecture §2, expressed as shapes rather than prose.
7
+ # 3. The realization-contract META-SHAPE, plus the ONE contract this substrate can actually
8
+ # enforce today (spec 329's routed member consultation).
9
+ #
10
+ # On (3), the governing discipline: an unenforceable contract is worse than an absent one.
11
+ # A capability whose realizations this substrate cannot observe declares
12
+ # `aps:contractStatus "deferred"` with a rationale naming the missing evidence. The
13
+ # DeferredContractShape below makes that declaration MANDATORY — you may omit a contract, but
14
+ # you may not omit saying why.
15
+
16
+ @prefix sh: <http://www.w3.org/ns/shacl#> .
17
+ @prefix aps: <https://agenticprimitives.dev/ns/skill#> .
18
+ @prefix apctx: <https://agenticprimitives.dev/ns/context#> .
19
+ @prefix apguide: <https://agenticprimitives.dev/ns/guidance#> .
20
+ @prefix apexec: <https://agenticprimitives.dev/ns/execution#> .
21
+ @prefix aprole: <https://agenticprimitives.dev/ns/role#> .
22
+ @prefix apmsg: <https://agenticprimitives.dev/ns/messaging#> .
23
+ @prefix apint: <https://agenticprimitives.dev/ns/intent#> .
24
+ @prefix ap: <https://agenticprimitives.dev/ns/core#> .
25
+ @prefix prov: <http://www.w3.org/ns/prov#> .
26
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
27
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
28
+
29
+ # ═══ 1. Well-formedness ═════════════════════════════════════════════════════
30
+
31
+ aps:CapabilityShape a sh:NodeShape ;
32
+ sh:targetClass aps:Capability ;
33
+ rdfs:label "CapabilityShape" ;
34
+ sh:property [ sh:path aps:capabilityId ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
35
+ sh:pattern "^[a-z][a-z0-9]*:[a-z0-9]+(-[a-z0-9]+)*$" ;
36
+ sh:message "A capability id is a lowercase CURIE '<prefix>:<kebab-slug>'. keccak256 of this exact string is the on-chain skillId, so the spelling IS the identity: a rename is a new capability plus a skos:exactMatch, never an edit." ] ;
37
+ sh:property [ sh:path apctx:ownedByContext ; sh:minCount 1 ; sh:maxCount 1 ;
38
+ sh:message "Exactly ONE accountable owning bounded context (architecture invariant 2). A capability may PARTICIPATE in many contexts via apctx:classifiedBy — but 'everyone owns it' means nobody versions it." ] ;
39
+ sh:property [ sh:path apctx:levelInMap ; sh:maxCount 0 ;
40
+ sh:message "levelInMap belongs on an apctx:CapabilityMapEntry, never on a capability. A map is a VIEW projected from the graph; baking a presentation level into the capability is how a reporting hierarchy becomes an ontology (architecture §3)." ] ;
41
+ sh:property [ sh:path aps:specializesCapability ;
42
+ sh:disjoint aps:hasComponentCapability ;
43
+ sh:message "A capability cannot both BE a narrower form of X and HAVE X as a part. If both feel true, the relation is probably requiresCapability." ] .
44
+
45
+ aps:CapabilityDefinitionShape a sh:NodeShape ;
46
+ sh:targetClass aps:CapabilityDefinition ;
47
+ rdfs:label "CapabilityDefinitionShape" ;
48
+ sh:property [ sh:path aps:definesCapability ; sh:minCount 1 ; sh:maxCount 1 ;
49
+ sh:message "A definition defines exactly one capability. Many definition VERSIONS may define the same identity — that is the point of separating them." ] ;
50
+ sh:property [ sh:path aps:outcomeStatement ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
51
+ sh:minLength 20 ; sh:maxLength 400 ;
52
+ sh:message "Required, and required to be a sentence. An outcome statement that can only be phrased as an activity ('advises on X') is the tell that the term is a service or a subject domain, not a capability." ] ;
53
+ sh:property [ sh:path aps:contractStatus ; sh:datatype xsd:string ; sh:minCount 1 ; sh:maxCount 1 ;
54
+ sh:in ( "enforced" "deferred" ) ;
55
+ sh:message "Every definition states whether its realization contract is enforced or deferred. Silence is not an option: it would let a catalog imply verification it does not perform." ] .
56
+
57
+ aps:DeferredContractShape a sh:NodeShape ;
58
+ sh:targetClass aps:CapabilityDefinition ;
59
+ rdfs:label "DeferredContractShape" ;
60
+ rdfs:comment "Deferral is first-class and honest — but it must be ARGUED. This shape is the whole reason the catalog can ship with two enforced contracts and forty-three deferred ones without that being a cop-out." ;
61
+ sh:sparql [
62
+ sh:message "aps:contractStatus 'deferred' requires aps:deferredContractRationale naming the evidence that would make a contract enforceable; 'enforced' requires an aps:hasRealizationContract." ;
63
+ sh:prefixes aps: ;
64
+ sh:select """
65
+ SELECT $this WHERE {
66
+ { $this <https://agenticprimitives.dev/ns/skill#contractStatus> "deferred" .
67
+ FILTER NOT EXISTS { $this <https://agenticprimitives.dev/ns/skill#deferredContractRationale> ?r } }
68
+ UNION
69
+ { $this <https://agenticprimitives.dev/ns/skill#contractStatus> "enforced" .
70
+ FILTER NOT EXISTS { $this <https://agenticprimitives.dev/ns/skill#hasRealizationContract> ?c } }
71
+ }
72
+ """ ;
73
+ ] .
74
+
75
+ aps:CapabilityCatalogShape a sh:NodeShape ;
76
+ sh:targetClass aps:CapabilityCatalog ;
77
+ sh:property [ sh:path aps:catalogSteward ; sh:minCount 1 ; sh:maxCount 1 ;
78
+ sh:message "One steward per catalog — the account SkillDefinitionRegistry will require as msg.sender to publish or version any definition in it." ] .
79
+
80
+ # ═══ 2. The anti-pattern axioms as shapes (architecture §2) ═════════════════
81
+
82
+ aps:CapabilityProtocolProjectionShape a sh:NodeShape ;
83
+ sh:targetClass aps:CapabilityProtocolProjection ;
84
+ rdfs:label "CapabilityProtocolProjectionShape" ;
85
+ rdfs:comment "AXIOM 1 + INVARIANT 6. A card AgentSkill / atl:skills token / offering declares exactly ONE primary capability and NEVER identifies an internal plan. The forbidden shape is `implementedBy exactly-1` between a projection and a SKILL.md: a descriptor is fulfilled through a realization whose execution plan may use zero, one, or several playbooks, plus tools, delegated agents and human steps." ;
86
+ sh:property [ sh:path aps:declaresCapability ; sh:minCount 1 ; sh:maxCount 1 ;
87
+ sh:message "Exactly one primary declared capability per projection. An advertisement that declares three outcomes is three advertisements." ] ;
88
+ sh:property [ sh:path apguide:supportsCapability ; sh:maxCount 0 ;
89
+ sh:message "A projection must not reference a playbook. supportsCapability runs from the PACKAGE to the capability, never from the advertisement — a card skill is not 'the SKILL.md's public face' (axiom 1)." ] .
90
+
91
+ aps:NoDeclarationOnProtocolFeaturesShape a sh:NodeShape ;
92
+ rdfs:label "NoDeclarationOnProtocolFeaturesShape" ;
93
+ rdfs:comment "AXIOM 2. A2A AgentCapabilities (streaming, pushNotifications, extensions) are PROTOCOL FEATURES. `streaming: true` declares transport behaviour, not an outcome." ;
94
+ sh:targetObjectsOf aps:declaresCapability ;
95
+ sh:not [ sh:class <https://a2aproject.github.io/A2A/ns#AgentCapabilities> ] ;
96
+ sh:message "An A2A AgentCapabilities node may never be the subject of declaresCapability — protocol features are not business capabilities." .
97
+
98
+ aps:NoAuthorityFromClassificationShape a sh:NodeShape ;
99
+ rdfs:label "NoAuthorityFromClassificationShape" ;
100
+ rdfs:comment "AXIOM 4 + 5, stated for readers rather than validators: bearing a taxon, a declared label, a claim credential, or a demonstrated edge grants NOTHING. Authorization is delegation ∩ entitlement ∩ policy, evaluated at the gate at the moment of use. No shape can enforce this — it is enforced by the gate never reading any of these predicates — so it is recorded here as doctrine at the point where a reader would otherwise be tempted." ;
101
+ sh:targetNode aps:assertsCapability ;
102
+ sh:deactivated true .
103
+
104
+ # ═══ 3. Realization contracts ═══════════════════════════════════════════════
105
+
106
+ aps:CapabilityRealizationContractShape a sh:NodeShape ;
107
+ sh:targetClass aps:CapabilityRealizationContract ;
108
+ rdfs:label "CapabilityRealizationContractShape (the META-SHAPE)" ;
109
+ rdfs:comment "What every realization contract must itself contain. A contract is a SHACL shape over PROV; this shape validates the contracts, not the executions. THE PATTERN, in five required parts: (a) sh:targetClass — the activity type; (b) prov:used — required input entity types; (c) prov:generated — required output entity types; (d) prov:qualifiedAssociation — an association carrying BOTH a prov:agent with a prov:hadRole AND a prov:hadPlan; (e) completion conditions — an end time and a terminal state. Part (e) is what makes a contract about REALIZATION rather than about attempt." ;
110
+ sh:property [ sh:path sh:targetClass ; sh:minCount 1 ;
111
+ sh:message "A contract targets an activity class. A contract with no target validates nothing and is the exact failure mode this meta-shape exists to catch." ] ;
112
+ sh:property [ sh:path aps:definesCapability ; sh:minCount 1 ; sh:maxCount 1 ;
113
+ sh:message "A contract states which capability a conforming activity realizes." ] ;
114
+ sh:sparql [
115
+ sh:message "A realization contract must constrain all five parts: prov:used, prov:generated, prov:qualifiedAssociation, prov:endedAtTime, and a terminal completion state." ;
116
+ sh:select """
117
+ SELECT $this WHERE {
118
+ FILTER NOT EXISTS {
119
+ $this <http://www.w3.org/ns/shacl#property> ?u . ?u <http://www.w3.org/ns/shacl#path> <http://www.w3.org/ns/prov#used> .
120
+ $this <http://www.w3.org/ns/shacl#property> ?g . ?g <http://www.w3.org/ns/shacl#path> <http://www.w3.org/ns/prov#generated> .
121
+ $this <http://www.w3.org/ns/shacl#property> ?a . ?a <http://www.w3.org/ns/shacl#path> <http://www.w3.org/ns/prov#qualifiedAssociation> .
122
+ $this <http://www.w3.org/ns/shacl#property> ?e . ?e <http://www.w3.org/ns/shacl#path> <http://www.w3.org/ns/prov#endedAtTime> .
123
+ $this <http://www.w3.org/ns/shacl#property> ?c . ?c <http://www.w3.org/ns/shacl#path> <https://agenticprimitives.dev/ns/execution#completionState> .
124
+ }
125
+ }
126
+ """ ;
127
+ ] .
128
+
129
+ # ── The one contract this substrate can enforce TODAY ───────────────────────
130
+ #
131
+ # The spec-329 routed member consultation is the substrate's only capability whose realizations
132
+ # are already fully observable: the harness pre-reads a vault playbook (activation pins its
133
+ # content hash), the turn consumes a signed ConsultRequestV1 and emits an answered-XOR-declined
134
+ # ConsultAnswerV1 with the actor pinned to the member, and the org-side synthesis derives from
135
+ # each contributing answer. Every clause below cites something the live code already produces.
136
+
137
+ aps:MemberConsultationRealizationContract
138
+ a sh:NodeShape , aps:CapabilityRealizationContract ;
139
+ rdfs:label "MemberConsultationRealizationContract" ;
140
+ aps:definesCapability aps:MemberConsultationCapability ;
141
+ sh:targetClass apexec:MemberConsultationActivity ;
142
+ rdfs:comment "Realization contract for aps:MemberConsultationCapability — one member agent answering one routed consultation under its own playbook. A DECLINE IS A CONFORMING REALIZATION: the contract governs shape, not outcome, and buildConsultAnswer makes answered-xor-declined structural. Treating a decline as non-realization would create an incentive to answer outside one's documented positions, which is the opposite of what the consult path is for." ;
143
+
144
+ sh:property [ sh:path prov:used ;
145
+ sh:qualifiedValueShape [ sh:class apmsg:ConsultRequest ] ; sh:qualifiedMinCount 1 ;
146
+ sh:message "The turn must have consumed the ConsultRequestV1 it is answering." ] ;
147
+ sh:property [ sh:path prov:used ;
148
+ sh:qualifiedValueShape [ sh:class apguide:AgentSkillPackage ] ; sh:qualifiedMinCount 1 ;
149
+ sh:message "The turn must have consumed the member's playbook — guidance, never authority (ADR-0050)." ] ;
150
+ sh:property [ sh:path prov:generated ;
151
+ sh:qualifiedValueShape [ sh:class apmsg:ConsultAnswer ] ; sh:qualifiedMinCount 1 ; sh:qualifiedMaxCount 1 ] ;
152
+ sh:property [ sh:path prov:qualifiedAssociation ;
153
+ sh:qualifiedValueShape [
154
+ sh:class prov:Association ;
155
+ sh:property [ sh:path prov:agent ; sh:class apexec:AgentRuntime ; sh:minCount 1 ] ;
156
+ sh:property [ sh:path prov:hadRole ; sh:hasValue aprole:ConsultResponder ; sh:minCount 1 ] ;
157
+ sh:property [ sh:path prov:hadPlan ; sh:class apguide:AgentSkillPackage ; sh:minCount 1 ] ;
158
+ ] ;
159
+ sh:qualifiedMinCount 1 ;
160
+ sh:message "One qualified association carrying the runtime that bore responsibility, the capacity it acted in, and the plan that guided it." ] ;
161
+ sh:property [ sh:path apexec:usedPlanContentHash ; sh:minCount 1 ; sh:datatype xsd:string ;
162
+ sh:message "The playbook's content hash AT ACTIVATION. Without it the record cannot answer 'which executions must repeat after this playbook changed?' — and a demonstrated-capability signal computed over unpinned plans is unfalsifiable." ] ;
163
+ sh:property [ sh:path prov:endedAtTime ; sh:minCount 1 ; sh:datatype xsd:dateTime ] ;
164
+ sh:property [ sh:path apexec:completionState ; sh:minCount 1 ;
165
+ sh:in ( apexec:Answered apexec:Declined ) ] .
166
+
167
+ aps:OrgConsultationSynthesisRealizationContract
168
+ a sh:NodeShape , aps:CapabilityRealizationContract ;
169
+ rdfs:label "OrgConsultationSynthesisRealizationContract" ;
170
+ aps:definesCapability aps:ConsultationRoutingCapability ;
171
+ sh:targetClass apexec:ConsultationSynthesisActivity ;
172
+ rdfs:comment "Realization contract for aps:ConsultationRoutingCapability — the ORG side: selecting the right members and synthesizing their attributed answers. Enforced today because spec 329 already produces every part: an eligibility set derived structurally, a ranked candidate set with evidence paths, and a synthesis post whose attribution names each contributing member. This is the capability whose demonstrated-signal the advisor catalog's routing quality actually rides on." ;
173
+ sh:property [ sh:path prov:used ;
174
+ sh:qualifiedValueShape [ sh:class apint:ConsultationIntent ] ; sh:qualifiedMinCount 1 ] ;
175
+ sh:property [ sh:path prov:used ;
176
+ sh:qualifiedValueShape [ sh:class apmsg:ConsultAnswer ] ; sh:qualifiedMinCount 1 ;
177
+ sh:message "A synthesis with no contributing answer is not a realization of routing — it is the org agent talking to itself." ] ;
178
+ sh:property [ sh:path prov:generated ;
179
+ sh:qualifiedValueShape [ sh:class apmsg:MessageEvent ] ; sh:qualifiedMinCount 1 ] ;
180
+ sh:property [ sh:path prov:qualifiedAssociation ;
181
+ sh:qualifiedValueShape [
182
+ sh:class prov:Association ;
183
+ sh:property [ sh:path prov:agent ; sh:class apexec:AgentRuntime ; sh:minCount 1 ] ;
184
+ sh:property [ sh:path prov:hadRole ; sh:hasValue aprole:ConsultRouter ; sh:minCount 1 ] ;
185
+ sh:property [ sh:path prov:hadPlan ; sh:class apguide:AgentSkillPackage ; sh:minCount 1 ] ;
186
+ ] ; sh:qualifiedMinCount 1 ] ;
187
+ sh:property [ sh:path prov:endedAtTime ; sh:minCount 1 ; sh:datatype xsd:dateTime ] ;
188
+ sh:property [ sh:path apexec:completionState ; sh:minCount 1 ;
189
+ sh:in ( apexec:Answered apexec:Declined apexec:NoEligibleMember ) ] .
190
+
191
+ # ═══ 4. The parameterised ADVISORY realization contract ═════════════════════════════════════════
192
+ #
193
+ # THE INSIGHT THIS SECTION TESTS (the owner's item-3 question, stated precisely):
194
+ # A spec-329 consult answer, where the answering member DECLARED the advisory capability the
195
+ # question was routed on, IS a realization of that advisory capability. The substrate already
196
+ # emits every part of the proof — the request, the pinned playbook, the attributed answer, the
197
+ # terminal state — for `aps:MemberConsultationCapability`. An advisory realization is the SAME
198
+ # activity graph plus ONE more edge: which advisory id the routing selected the responder on.
199
+ #
200
+ # WHY ONE PARAMETERISED CONTRACT, NOT 43 SHAPES. Every consult-realizable advisory capability has
201
+ # the identical execution shape — they differ ONLY in the capability id on the routed-on edge.
202
+ # Authoring 43 near-identical NodeShapes would be repetition mistaken for rigour (the owner's
203
+ # words), and worse: 43 shapes drift, this one cannot. The capability id is DATA on the activity
204
+ # (`apexec:routedOnCapability`), matched against DATA on the definition, by SPARQL — so the contract
205
+ # is written once and every advisory definition that opts in is validated by it. This is the direct
206
+ # application of architecture §5's "the contract is a shape over PROV": the shape is over the shape
207
+ # of the graph, and the capability identity rides in the graph, not in the shape's name.
208
+ #
209
+ # ── WHY IT IS NOT ENFORCED TODAY, AND EXACTLY WHAT WOULD FLIP IT ────────────────────────────────
210
+ # One edge is missing from live PROV: `apexec:routedOnCapability`. The org's `rankConsultCandidates`
211
+ # ALREADY computes the routed-on id (the exact-match intersection of resolved need and declared ids,
212
+ # `capabilityHits`), and then discards it into a free-text evidence line. Spec 330 W1 has to emit it
213
+ # as a triple on the responder's turn. Until it does, this contract's target set is empty and it
214
+ # would pass by vacuity — so every advisory definition keeps `contractStatus "deferred"`, and this
215
+ # shape ships DEACTIVATED, as an executable specification of the one datum that is missing rather
216
+ # than as a live check pretending to observe something it cannot. `sh:deactivated true` is the
217
+ # honest state: the shape is correct, its input does not exist yet, and the test in §3's validation
218
+ # path drives it against a FIXTURE that supplies the missing edge — so the day W1 emits the edge,
219
+ # flipping `sh:deactivated` to false is the whole change, and the fixture proves it will validate.
220
+ #
221
+ # The evidence needed, in one line (this is the mandatory deferredContractRationale for all 43):
222
+ # a spec-330-W1 `apexec:routedOnCapability` edge on the member's consult turn, naming the
223
+ # advisory capability id the org's ranking selected the responder on.
224
+
225
+ aps:AdvisoryConsultRealizationContract
226
+ a sh:NodeShape , aps:CapabilityRealizationContract ;
227
+ rdfs:label "AdvisoryConsultRealizationContract (parameterised — ONE shape, every consult-realizable adv:*)" ;
228
+ aps:definesCapability aps:AdvisoryConsultRealizationParameter ;
229
+ sh:targetClass apexec:MemberConsultationActivity ;
230
+ sh:deactivated true ; # ← the one edit that flips it live, once W1 emits apexec:routedOnCapability
231
+ rdfs:comment "Parameterised realization contract for any advisory capability whose realization the consult path can carry. It is aps:MemberConsultationRealizationContract PLUS one clause: the turn must carry an apexec:routedOnCapability edge, and that capability must be one the responder actually declared (aps:declaresCapability). The capability identity is a PARAMETER read from the graph, not baked into 43 shape names. DEACTIVATED until spec 330 W1 emits the routed-on edge — see the header block for why an active-but-unobservable contract is the exact failure mode the catalog forbids." ;
232
+
233
+ # Everything aps:MemberConsultationRealizationContract requires, unchanged — an advisory
234
+ # realization is a member consultation, so it inherits the member consultation's whole shape.
235
+ sh:property [ sh:path prov:used ;
236
+ sh:qualifiedValueShape [ sh:class apmsg:ConsultRequest ] ; sh:qualifiedMinCount 1 ] ;
237
+ sh:property [ sh:path prov:used ;
238
+ sh:qualifiedValueShape [ sh:class apguide:AgentSkillPackage ] ; sh:qualifiedMinCount 1 ] ;
239
+ sh:property [ sh:path prov:generated ;
240
+ sh:qualifiedValueShape [ sh:class apmsg:ConsultAnswer ] ; sh:qualifiedMinCount 1 ; sh:qualifiedMaxCount 1 ] ;
241
+ sh:property [ sh:path prov:qualifiedAssociation ;
242
+ sh:qualifiedValueShape [
243
+ sh:class prov:Association ;
244
+ sh:property [ sh:path prov:agent ; sh:class apexec:AgentRuntime ; sh:minCount 1 ] ;
245
+ sh:property [ sh:path prov:hadRole ; sh:hasValue aprole:ConsultResponder ; sh:minCount 1 ] ;
246
+ sh:property [ sh:path prov:hadPlan ; sh:class apguide:AgentSkillPackage ; sh:minCount 1 ] ;
247
+ ] ; sh:qualifiedMinCount 1 ] ;
248
+ sh:property [ sh:path apexec:usedPlanContentHash ; sh:minCount 1 ; sh:datatype xsd:string ] ;
249
+ sh:property [ sh:path prov:endedAtTime ; sh:minCount 1 ; sh:datatype xsd:dateTime ] ;
250
+ sh:property [ sh:path apexec:completionState ; sh:minCount 1 ;
251
+ sh:in ( apexec:Answered apexec:Declined ) ] ;
252
+
253
+ # THE ONE ADDED CLAUSE (parts a): the turn names the advisory capability it was routed on.
254
+ sh:property [ sh:path apexec:routedOnCapability ; sh:minCount 1 ; sh:class aps:Capability ;
255
+ sh:message "An advisory realization must name the capability the org's routing selected the responder on — the parameter that says WHICH adv:* id this turn realizes. Without it the turn is a member consultation but not an advisory realization." ] ;
256
+
257
+ # THE ONE ADDED CLAUSE (part b): routed-on ⊆ declared. The realization only counts for a
258
+ # capability the responder actually put its name behind. This is the whole anti-inflation guard,
259
+ # in one FILTER: a member cannot earn a demonstrated edge for a capability it never declared, so
260
+ # routing an unrelated question at someone does not manufacture evidence they can do the thing.
261
+ sh:sparql [
262
+ sh:message "The routed-on advisory capability must be one the responding member DECLARED (aps:declaresCapability). Crediting a realization for an undeclared capability would let routing manufacture demonstrated-capability evidence the member never asserted — inverting the one signal that is supposed to be unfakeable." ;
263
+ sh:select """
264
+ SELECT $this ?cap WHERE {
265
+ $this <https://agenticprimitives.dev/ns/execution#routedOnCapability> ?cap .
266
+ $this <http://www.w3.org/ns/prov#qualifiedAssociation> ?assoc .
267
+ ?assoc <http://www.w3.org/ns/prov#agent> ?runtime .
268
+ ?runtime <http://www.w3.org/ns/prov#actedOnBehalfOf> ?member .
269
+ FILTER NOT EXISTS { ?member <https://agenticprimitives.dev/ns/skill#declaresCapability> ?cap }
270
+ }
271
+ """ ;
272
+ ] .
273
+
274
+ # The PARAMETER capability the contract "defines". Not an advisory capability itself — it is the
275
+ # substrate-owned identity that says "a conforming activity realizes WHICHEVER adv:* its routed-on
276
+ # edge names". This keeps the meta-shape's `aps:definesCapability minCount 1` satisfied (a contract
277
+ # states which capability a conforming activity realizes) while being honest that the specific
278
+ # advisory id is late-bound from the graph. The 43 advisory definitions point their
279
+ # aps:hasRealizationContract here ONCE W1 lands; today they stay deferred.
280
+ aps:AdvisoryConsultRealizationParameter a aps:Capability ;
281
+ aps:capabilityId "aps:advisory-consult-realization-parameter" ;
282
+ apctx:ownedByContext apctx:SubstrateContext ;
283
+ rdfs:label "Advisory-consult realization parameter" ;
284
+ rdfs:comment "A substrate-owned meta-capability standing for 'the advisory capability this consult turn was routed on'. It exists so one parameterised contract can serve 43 advisory definitions without either baking 43 names into 43 shapes or leaving the meta-shape's definesCapability unsatisfied." .