From 922d759c0f3a26e39efa631aa9b3c518c5a5365c Mon Sep 17 00:00:00 2001 From: Michael Heller <21163552+mdheller@users.noreply.github.com> Date: Mon, 29 Jun 2026 00:30:49 -0400 Subject: [PATCH] Add agentic-marketing contract family RecommendationObject, SurfaceRegistry, AudienceTag, PersonaBundle (JSON Schema draft 2020-12) + canonical examples. RecommendationObject binds marketing/SEO actuation to the reasoning-evidence fabric (traceHash/ replayClass) and is fail-closed without an autonomy admissionReceiptRef. SurfaceRegistry is the signed surface source of truth; AudienceTag + PersonaBundle express personas as Boolean expressions over atomic tags. --- CHANGELOG.md | 1 + examples/audience_tag.json | 13 +++ examples/persona_bundle.json | 9 ++ examples/recommendation_object.json | 52 +++++++++++ examples/surface_registry.json | 19 ++++ schemas/AudienceTag.json | 25 ++++++ schemas/PersonaBundle.json | 21 +++++ schemas/RecommendationObject.json | 134 ++++++++++++++++++++++++++++ schemas/SurfaceRegistry.json | 43 +++++++++ 9 files changed, 317 insertions(+) create mode 100644 examples/audience_tag.json create mode 100644 examples/persona_bundle.json create mode 100644 examples/recommendation_object.json create mode 100644 examples/surface_registry.json create mode 100644 schemas/AudienceTag.json create mode 100644 schemas/PersonaBundle.json create mode 100644 schemas/RecommendationObject.json create mode 100644 schemas/SurfaceRegistry.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 49d399a..4037f4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). Thi ## [Unreleased] ### Added +- Agentic-marketing contract family: `RecommendationObject`, `SurfaceRegistry`, `AudienceTag`, `PersonaBundle` with canonical examples (`examples/recommendation_object.json`, `examples/surface_registry.json`, `examples/audience_tag.json`, `examples/persona_bundle.json`). `RecommendationObject` (evidence → action → risk → guardrails → rollback → validation) chains into the reasoning-evidence fabric via `traceHash`/`replayClass` and is fail-closed on actuation without an `admissionReceiptRef` from the autonomy ladder (L0–L5). `SurfaceRegistry` is the signed, queryable web-surface source of truth RO scopes resolve against; `AudienceTag` + `PersonaBundle` express personas as Boolean expressions over stable atomic tags (distinct from `TagAssignment`, which classifies data fields). - SourceOS interaction substrate top-level index and README discovery links for `SourceOSInteractionEvent`, generated TypeScript/Python artifacts, and the Noetica → Superconscious → AgentPlane → AgentTerm reference flow. - Runtime observability and capability governance contracts: `CapabilityLedger`, `BrowserAutomationReceipt`, `GitWorkspaceState`, `OrphanEventReceipt`, and `RuntimeInstallReceipt` with canonical examples, validation wiring (`tools/validate_runtime_observability_examples.py`), a contract catalog, and ADR-0012. - Reasoning run contracts: `ReasoningRun`, `ReasoningEvent`, `ReasoningReceipt`, `ReasoningReplayPlan`, and `ReasoningBenchmark` with canonical examples and a contract-additions note for the Superconscious reference loop. diff --git a/examples/audience_tag.json b/examples/audience_tag.json new file mode 100644 index 0000000..35aaad7 --- /dev/null +++ b/examples/audience_tag.json @@ -0,0 +1,13 @@ +{ + "id": "urn:srcos:audience-tag:intent_learning", + "type": "AudienceTag", + "specVersion": "2.0.0", + "family": "INTENT_STAGE", + "label": "Learning intent", + "definition": "User is actively seeking to learn or upskill.", + "privacyRisk": 2, + "inclusionSignals": ["course_views", "tutorial_searches", "repeat_visits_to_docs"], + "exclusionRules": ["no_targeting_of_minors"], + "activationChannels": ["search", "newsletters", "communities"], + "primaryMetrics": ["content_completion", "signup", "repeat_visits"] +} diff --git a/examples/persona_bundle.json b/examples/persona_bundle.json new file mode 100644 index 0000000..a1473b0 --- /dev/null +++ b/examples/persona_bundle.json @@ -0,0 +1,9 @@ +{ + "id": "urn:srcos:persona-bundle:p_dev_builder", + "type": "PersonaBundle", + "specVersion": "2.0.0", + "label": "Developer (builder)", + "definition": "Individual contributor building software.", + "tagExpression": "IDENTITY_ROLE in {developer, engineer} AND INTENT_STAGE in {implementing, evaluating}", + "jobsToBeDone": ["ship features", "choose tools", "fix bugs"] +} diff --git a/examples/recommendation_object.json b/examples/recommendation_object.json new file mode 100644 index 0000000..c16bca3 --- /dev/null +++ b/examples/recommendation_object.json @@ -0,0 +1,52 @@ +{ + "id": "urn:srcos:recommendation-object:ro_2026w27_restore_root_files_01", + "type": "RecommendationObject", + "specVersion": "2.0.0", + "createdAt": "2026-06-29T00:00:00Z", + "title": "Restore robots.txt, sitemap.xml, llms.txt on socioprophet.com", + "scope": { + "properties": ["socioprophet.com"], + "surfaces": ["urn:srcos:surface:socioprophet-marketing"], + "tags": [] + }, + "evidence": { + "source": "semrush-site-audit-2026-03-04", + "robots_txt": "404", + "sitemap_xml": "404", + "llms_txt": "missing", + "site_health_pct": 77, + "healthy_pages": 0 + }, + "action": { + "kind": "publish_static_files", + "files": ["marketing/public/robots.txt", "marketing/public/sitemap.xml", "marketing/public/llms.txt"], + "deploy_target": "firebase:marketing" + }, + "risk": { + "policyCompliance": 0, + "privacy": 0, + "brandSafety": 0, + "outcomeQuality": 0, + "volatility": 0, + "manipulation": 0 + }, + "guardrails": { + "keep_ai_bots_allowed": true, + "no_disallow_root": true + }, + "rollback": { + "method": "remove_files", + "revert_to": "pre-deploy" + }, + "validation": { + "design": "recrawl", + "primary": "site_health_score", + "expect": "robots/sitemap/llms return 200; healthy_pages > 0", + "duration": "1w" + }, + "status": "proposed", + "autonomyLevel": 2, + "admissionReceiptRef": null, + "replayClass": "exact", + "traceHash": "sha256:0000000000000000000000000000000000000000000000000000000000000000" +} diff --git a/examples/surface_registry.json b/examples/surface_registry.json new file mode 100644 index 0000000..2c9a2a2 --- /dev/null +++ b/examples/surface_registry.json @@ -0,0 +1,19 @@ +{ + "id": "urn:srcos:surface-registry:socioprophet-2026-06-29", + "type": "SurfaceRegistry", + "specVersion": "2.0.0", + "generatedAt": "2026-06-29T00:00:00Z", + "signature": null, + "surfaces": [ + { "surfaceId": "urn:srcos:surface:socioprophet-com", "domain": "socioprophet.com", "role": "Canonical marketing entrypoint", "privilege": "public", "defaultBehavior": "Primary / landing + /documentation", "intent": "brand", "ttlSeconds": 86400, "owner": "marketing", "notes": "Canonical public brand entrypoint" }, + { "surfaceId": "urn:srcos:surface:socioprophet-ai", "domain": "socioprophet.ai", "role": "AI platform", "privilege": "public-premium", "defaultBehavior": "Redirect to product section until shipped", "intent": "product", "ttlSeconds": 86400, "owner": "product", "notes": null }, + { "surfaceId": "urn:srcos:surface:socioprophet-dev", "domain": "socioprophet.dev", "role": "Developer platform", "privilege": "public", "defaultBehavior": "Redirect to /documentation", "intent": "product", "ttlSeconds": 86400, "owner": "product", "notes": null }, + { "surfaceId": "urn:srcos:surface:socioprophet-cloud", "domain": "socioprophet.cloud", "role": "Hosted suite", "privilege": "public-premium", "defaultBehavior": "Redirect to product section until shipped", "intent": "product", "ttlSeconds": 86400, "owner": "product", "notes": null }, + { "surfaceId": "urn:srcos:surface:socioprophet-sh", "domain": "socioprophet.sh", "role": "Installers + cloud shell", "privilege": "public-operator", "defaultBehavior": "/install public, /shell gated", "intent": "operator", "ttlSeconds": 86400, "owner": "platform", "notes": "Operator realm separated" }, + { "surfaceId": "urn:srcos:surface:socioprophet-live", "domain": "socioprophet.live", "role": "Live builds / boot images", "privilege": "immutable", "defaultBehavior": "Immutable content-addressed + verify", "intent": "artifact", "ttlSeconds": null, "owner": "platform", "notes": "Artifact hosting" }, + { "surfaceId": "urn:srcos:surface:socioprophet-academy", "domain": "socioprophet.academy", "role": "Education", "privilege": "public-accounts", "defaultBehavior": "public-first", "intent": "education", "ttlSeconds": 86400, "owner": "academy", "notes": null }, + { "surfaceId": "urn:srcos:surface:socioprophet-md", "domain": "socioprophet.md", "role": "Medical access", "privilege": "public-premium", "defaultBehavior": "free public + premium clinicians", "intent": "regulated", "ttlSeconds": 86400, "owner": "medical", "notes": "Regulated surface" }, + { "surfaceId": "urn:srcos:surface:socioprophet-law", "domain": "socioprophet.law", "role": "AI law product", "privilege": "public-premium", "defaultBehavior": "public knowledge + gated practitioners", "intent": "regulated", "ttlSeconds": 86400, "owner": "law", "notes": "Regulated surface" }, + { "surfaceId": "urn:srcos:surface:truthorbot", "domain": "truthorbot.org", "role": "Adversarial evaluation lab", "privilege": "public", "defaultBehavior": "static-only", "intent": "evaluation", "ttlSeconds": 86400, "owner": "research", "notes": null } + ] +} diff --git a/schemas/AudienceTag.json b/schemas/AudienceTag.json new file mode 100644 index 0000000..3b4c59a --- /dev/null +++ b/schemas/AudienceTag.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/AudienceTag.json", + "title": "AudienceTag", + "description": "An atomic, stable audience-segmentation tag (role, affiliation, intent, capability, network position, or context) that personas are composed from. Distinct from TagAssignment, which classifies data fields; AudienceTag classifies reachable audiences for governed prospecting.", + "type": "object", + "additionalProperties": false, + "required": ["id", "type", "specVersion", "family", "label", "definition", "privacyRisk"], + "properties": { + "id": { "type": "string", "pattern": "^urn:srcos:audience-tag:", "description": "Stable URN identifier for this audience tag." }, + "type": { "const": "AudienceTag", "description": "Type discriminator; always 'AudienceTag'." }, + "specVersion": { "type": "string", "description": "Semantic version of the contract this document conforms to." }, + "family": { + "enum": ["IDENTITY_ROLE", "ORG_AFFILIATION", "DOMAIN_INTEREST", "INTENT_STAGE", "CAPABILITY_STACK", "NETWORK_ROLE", "CONTEXT_CHANNEL", "VALUES_MISSION"], + "description": "Tag family the tag belongs to." + }, + "label": { "type": "string", "description": "Human-readable label, e.g. 'K-12 teacher'." }, + "definition": { "type": "string", "description": "One-sentence definition of inclusion." }, + "privacyRisk": { "type": "integer", "minimum": 0, "maximum": 4, "description": "Privacy-risk rating (0=aggregate-safe .. 4=sensitive inference)." }, + "inclusionSignals": { "type": "array", "items": { "type": "string" }, "description": "Signals that qualify a member for this tag." }, + "exclusionRules": { "type": "array", "items": { "type": "string" }, "description": "Rules that disqualify a member." }, + "activationChannels": { "type": "array", "items": { "type": "string" }, "description": "Channels through which this tag is reachable." }, + "primaryMetrics": { "type": "array", "items": { "type": "string" }, "description": "Success metrics most predictive for this tag." } + } +} diff --git a/schemas/PersonaBundle.json b/schemas/PersonaBundle.json new file mode 100644 index 0000000..b89fd1d --- /dev/null +++ b/schemas/PersonaBundle.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/PersonaBundle.json", + "title": "PersonaBundle", + "description": "A persona expressed as a Boolean expression over AudienceTag identifiers, preserving human legibility while keeping the targeting system bound to stable atomic tags rather than brittle caricatures.", + "type": "object", + "additionalProperties": false, + "required": ["id", "type", "specVersion", "label", "tagExpression"], + "properties": { + "id": { "type": "string", "pattern": "^urn:srcos:persona-bundle:", "description": "Stable URN identifier for this persona bundle." }, + "type": { "const": "PersonaBundle", "description": "Type discriminator; always 'PersonaBundle'." }, + "specVersion": { "type": "string", "description": "Semantic version of the contract this document conforms to." }, + "label": { "type": "string", "description": "Human-readable persona name, e.g. 'Developer (builder)'." }, + "definition": { "type": "string", "description": "One-sentence description of the persona." }, + "tagExpression": { + "type": "string", + "description": "Boolean expression over AudienceTag ids/families using AND/OR/NOT and set membership, e.g. \"IDENTITY_ROLE in {developer, engineer} AND INTENT_STAGE in {implementing, evaluating}\"." + }, + "jobsToBeDone": { "type": "array", "items": { "type": "string" }, "description": "Primary jobs-to-be-done for this persona." } + } +} diff --git a/schemas/RecommendationObject.json b/schemas/RecommendationObject.json new file mode 100644 index 0000000..2fbffb9 --- /dev/null +++ b/schemas/RecommendationObject.json @@ -0,0 +1,134 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/RecommendationObject.json", + "title": "RecommendationObject", + "description": "A governed, replayable proposed action over marketing/prospecting/SEO surfaces: binds evidence to an action with explicit risk, guardrails, rollback, and validation, and chains into the reasoning-evidence fabric so every actuation is auditable. Cannot actuate without an autonomy admission receipt.", + "type": "object", + "additionalProperties": false, + "required": [ + "id", + "type", + "specVersion", + "createdAt", + "scope", + "action", + "risk", + "status" + ], + "properties": { + "id": { + "type": "string", + "pattern": "^urn:srcos:recommendation-object:", + "description": "Stable URN identifier for this recommendation object." + }, + "type": { + "const": "RecommendationObject", + "description": "Type discriminator; always 'RecommendationObject'." + }, + "specVersion": { + "type": "string", + "description": "Semantic version of the contract this document conforms to." + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the recommendation object was created." + }, + "title": { + "type": "string", + "description": "Short human-readable summary of the proposed action." + }, + "scope": { + "type": "object", + "additionalProperties": true, + "description": "Which properties, surfaces, and audience tags this recommendation affects.", + "properties": { + "properties": { + "type": "array", + "items": { "type": "string" }, + "description": "Publisher/platform property identifiers in scope." + }, + "surfaces": { + "type": "array", + "items": { "type": "string" }, + "description": "Surface identifiers (e.g. ServiceManifest surface URNs) in scope." + }, + "tags": { + "type": "array", + "items": { "type": "string" }, + "description": "Audience tag identifiers in scope." + } + } + }, + "evidence": { + "type": "object", + "additionalProperties": true, + "description": "Windowed metrics, bias-corrected estimates, and audit findings that justify the action (e.g. site-audit buckets, backlink toxicity, curvature findings)." + }, + "action": { + "type": "object", + "additionalProperties": true, + "description": "The proposed change to a control surface (e.g. publish file, shift budget, disavow domain, adjust exploration entropy)." + }, + "risk": { + "type": "object", + "additionalProperties": true, + "description": "Risk-rubric scores (0=none .. 3=severe) bounding the action against the persuasion-machine and compliance risks.", + "properties": { + "policyCompliance": { "type": "integer", "minimum": 0, "maximum": 3, "description": "Platform/legal policy violation risk." }, + "privacy": { "type": "integer", "minimum": 0, "maximum": 3, "description": "Re-identification / sensitive-inference / data-minimization risk." }, + "brandSafety": { "type": "integer", "minimum": 0, "maximum": 3, "description": "Adjacency to harmful/misinformation content." }, + "outcomeQuality": { "type": "integer", "minimum": 0, "maximum": 3, "description": "Risk of high engagement but low downstream value." }, + "volatility": { "type": "integer", "minimum": 0, "maximum": 3, "description": "Spiky / controversy-driven instability risk." }, + "manipulation": { "type": "integer", "minimum": 0, "maximum": 3, "description": "Bot/fraud/inorganic-behavior susceptibility." } + } + }, + "guardrails": { + "type": "object", + "additionalProperties": true, + "description": "Hard constraints enforced during execution (e.g. spend caps, frequency caps, blocklists)." + }, + "rollback": { + "type": "object", + "additionalProperties": true, + "description": "How to safely undo the action (e.g. revert-to prior config hash)." + }, + "validation": { + "type": "object", + "additionalProperties": true, + "description": "Experiment design and success metrics used to validate the action's effect." + }, + "status": { + "enum": ["proposed", "admitted", "actuated", "validated", "rolled-back", "rejected"], + "description": "Lifecycle state of the recommendation object." + }, + "autonomyLevel": { + "type": "integer", + "minimum": 0, + "maximum": 5, + "description": "Autonomy ladder level (L0-L5) required to actuate this recommendation." + }, + "admissionReceiptRef": { + "type": ["string", "null"], + "description": "URN of the autonomy admission receipt that authorized actuation; null until admitted. Actuation is fail-closed without it." + }, + "runRef": { + "type": "string", + "pattern": "^urn:srcos:reasoning-run:", + "description": "Optional reference to the reasoning run that produced this recommendation." + }, + "receiptRef": { + "type": "string", + "pattern": "^urn:srcos:receipt:reasoning:", + "description": "Optional reference to the reasoning receipt emitted on actuation." + }, + "replayClass": { + "enum": ["exact", "best-effort", "evidence-only", "non-replayable-side-effect"], + "description": "Replay fidelity class for the action, matching the reasoning-evidence fabric." + }, + "traceHash": { + "type": "string", + "description": "Hash of the serialized recommendation object plus prior digest, for forensic hash-chaining onto the evidence spine." + } + } +} diff --git a/schemas/SurfaceRegistry.json b/schemas/SurfaceRegistry.json new file mode 100644 index 0000000..f8bbfdb --- /dev/null +++ b/schemas/SurfaceRegistry.json @@ -0,0 +1,43 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.srcos.ai/v2/SurfaceRegistry.json", + "title": "SurfaceRegistry", + "description": "A signed, queryable registry of marketing/product web surfaces (domains and paths) with role, privilege boundary, default routing behavior, intent, and TTL. The single source of truth that RecommendationObject scopes resolve against.", + "type": "object", + "additionalProperties": false, + "required": ["id", "type", "specVersion", "surfaces"], + "properties": { + "id": { + "type": "string", + "pattern": "^urn:srcos:surface-registry:", + "description": "Stable URN identifier for this registry snapshot." + }, + "type": { "const": "SurfaceRegistry", "description": "Type discriminator; always 'SurfaceRegistry'." }, + "specVersion": { "type": "string", "description": "Semantic version of the contract this document conforms to." }, + "generatedAt": { "type": "string", "format": "date-time", "description": "Timestamp the registry snapshot was generated." }, + "signature": { "type": ["string", "null"], "description": "Detached signature over the canonicalized surfaces array, or null if unsigned." }, + "surfaces": { + "type": "array", + "description": "The registered surfaces.", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["surfaceId", "domain", "role", "privilege"], + "properties": { + "surfaceId": { "type": "string", "pattern": "^urn:srcos:surface:", "description": "Stable URN identifier for the surface." }, + "domain": { "type": "string", "description": "Host the surface is served on, e.g. socioprophet.com." }, + "role": { "type": "string", "description": "What the surface is for, e.g. 'Canonical marketing entrypoint'." }, + "privilege": { + "enum": ["public", "public-premium", "public-operator", "public-accounts", "operator", "immutable", "reserved"], + "description": "Privilege boundary governing access and actuation." + }, + "defaultBehavior": { "type": ["string", "null"], "description": "Default routing/landing behavior." }, + "intent": { "type": ["string", "null"], "description": "Primary intent served (e.g. brand, product, docs, education, regulated)." }, + "ttlSeconds": { "type": ["integer", "null"], "minimum": 0, "description": "Freshness TTL for this surface entry in seconds." }, + "owner": { "type": ["string", "null"], "description": "Accountable owner of the surface." }, + "notes": { "type": ["string", "null"], "description": "Free-text notes." } + } + } + } + } +}