{
  "$schema": "https://t2k.ai/schemas/t2k-ontology-pack.v1.schema.json",
  "manifestType": "t2k.ontology-pack",
  "manifestVersion": "1.0",
  "ontologyVersion": "1.0.0",
  "ontologyId": "example.gtm",
  "label": "Go-to-market pipeline",
  "description": "A reusable teaching ontology for account pipeline and campaign-linked opportunities.",
  "packKind": "workflow",
  "status": "draft",
  "scope": {
    "domain": "go_to_market",
    "description": "Read-only qualified-pipeline questions over a fictional CRM and marketing snapshot.",
    "exclusions": [
      "Revenue recognition",
      "Forecast probability calibration",
      "Causal attribution or incremental marketing lift",
      "Automated campaign spending or CRM writes"
    ]
  },
  "objectTypes": [
    {
      "id": "account",
      "label": "Account",
      "family": "Commercial organization",
      "nodeKind": "organization",
      "purpose": "An organization a sales team works with.",
      "identity": [
        "account_id"
      ],
      "properties": [
        {
          "id": "account_id",
          "valueType": "string",
          "required": true,
          "description": "Stable source-system identifier; display labels are not identity.",
          "authorityDomain": "operations",
          "temporal": false
        },
        {
          "id": "display_name",
          "valueType": "string",
          "required": true,
          "description": "Account display name.",
          "authorityDomain": "sales",
          "temporal": false
        }
      ]
    },
    {
      "id": "contact",
      "label": "Contact",
      "family": "Commercial relationship",
      "nodeKind": "person",
      "purpose": "A CRM contact identified by its CRM ID, not by name or email.",
      "identity": [
        "contact_id"
      ],
      "properties": [
        {
          "id": "contact_id",
          "valueType": "string",
          "required": true,
          "description": "Stable source-system identifier; display labels are not identity.",
          "authorityDomain": "operations",
          "temporal": false
        },
        {
          "id": "display_name",
          "valueType": "string",
          "required": true,
          "description": "Contact display name.",
          "authorityDomain": "sales",
          "temporal": false
        }
      ]
    },
    {
      "id": "opportunity",
      "label": "Opportunity",
      "family": "Commercial pipeline",
      "nodeKind": "case",
      "purpose": "A potential or completed commercial agreement; amount is a recorded opportunity value.",
      "identity": [
        "opportunity_id"
      ],
      "properties": [
        {
          "id": "opportunity_id",
          "valueType": "string",
          "required": true,
          "description": "Stable source-system identifier; display labels are not identity.",
          "authorityDomain": "operations",
          "temporal": false
        },
        {
          "id": "stage",
          "valueType": "string",
          "required": true,
          "description": "Example stages: prospecting, qualified, won, lost. Qualified is an explicit CRM stage.",
          "authorityDomain": "sales",
          "temporal": true
        },
        {
          "id": "amount_minor",
          "valueType": "integer",
          "required": true,
          "description": "Unweighted opportunity value in minor units of the declared currency; not recognized revenue.",
          "authorityDomain": "sales",
          "temporal": true
        },
        {
          "id": "currency",
          "valueType": "string",
          "required": true,
          "description": "Uppercase ISO currency code; this example queries USD only.",
          "authorityDomain": "sales",
          "temporal": false
        }
      ]
    },
    {
      "id": "campaign",
      "label": "Campaign",
      "family": "Marketing activity",
      "nodeKind": "workflow",
      "purpose": "A named marketing initiative with observed interactions.",
      "identity": [
        "campaign_id"
      ],
      "properties": [
        {
          "id": "campaign_id",
          "valueType": "string",
          "required": true,
          "description": "Stable source-system identifier; display labels are not identity.",
          "authorityDomain": "operations",
          "temporal": false
        },
        {
          "id": "channel",
          "valueType": "string",
          "required": true,
          "description": "Recorded marketing channel.",
          "authorityDomain": "marketing",
          "temporal": false
        }
      ]
    },
    {
      "id": "touchpoint",
      "label": "Touchpoint",
      "family": "Marketing evidence",
      "nodeKind": "artifact",
      "purpose": "An observed interaction explicitly linked to a campaign, contact and opportunity for this example.",
      "identity": [
        "touchpoint_id"
      ],
      "properties": [
        {
          "id": "touchpoint_id",
          "valueType": "string",
          "required": true,
          "description": "Stable source-system identifier; display labels are not identity.",
          "authorityDomain": "operations",
          "temporal": false
        },
        {
          "id": "interaction",
          "valueType": "string",
          "required": true,
          "description": "Recorded interaction kind; it does not establish causal influence.",
          "authorityDomain": "marketing",
          "temporal": false
        },
        {
          "id": "occurred_at",
          "valueType": "string",
          "required": true,
          "description": "UTC ISO 8601 event time, distinct from when a claim was observed.",
          "authorityDomain": "marketing",
          "temporal": false
        }
      ]
    }
  ],
  "structuralRelationships": [
    {
      "from": "contact",
      "property": "at_account",
      "to": "account",
      "cardinality": "many_to_one",
      "description": "The CRM-recorded account associated with a contact."
    },
    {
      "from": "opportunity",
      "property": "for_account",
      "to": "account",
      "cardinality": "many_to_one",
      "description": "The account associated with the opportunity."
    },
    {
      "from": "touchpoint",
      "property": "by_contact",
      "to": "contact",
      "cardinality": "many_to_one",
      "description": "The explicitly resolved participant in this interaction."
    },
    {
      "from": "touchpoint",
      "property": "from_campaign",
      "to": "campaign",
      "cardinality": "many_to_one",
      "description": "The marketing campaign identified in the interaction record."
    },
    {
      "from": "touchpoint",
      "property": "linked_opportunity",
      "to": "opportunity",
      "cardinality": "many_to_one",
      "description": "An explicit CRM/marketing association; no causal claim or inferred identity matching."
    }
  ],
  "reasoningFunctions": [
    {
      "id": "qualified_pipeline",
      "input": "Account ID and one currency code.",
      "output": "Qualified opportunities with their recorded amount in minor currency units.",
      "humanCheckpoint": "Sales operations reviews source quality before using this result in a forecast."
    },
    {
      "id": "campaign_linked_pipeline",
      "input": "Campaign ID and one currency code.",
      "output": "Sum of qualified opportunity amounts after deduplicating opportunities across touchpoints.",
      "humanCheckpoint": "Marketing operations reviews associations; this descriptive result is not causal attribution."
    }
  ],
  "normalizationRules": [
    "These are documented authoring requirements, not executable normalization code. The supplied fixtures are already normalized.",
    "Use source-scoped stable IDs for identity; never merge accounts or contacts from display-name similarity alone.",
    "Map source stages to prospecting, qualified, won or lost only with a reviewed stage map. Do not equate qualified with won.",
    "Represent USD amounts as integer cents. Preserve currency and exclude other currencies instead of applying an implicit exchange rate.",
    "Preserve every touchpoint, but deduplicate opportunity IDs before summing campaign-linked pipeline."
  ],
  "validationRules": [
    {
      "id": "stage_is_not_revenue",
      "level": "semantic",
      "severity": "review",
      "target": "example.gtm:opportunity",
      "assertion": "Opportunity stage and amount must retain their source definitions.",
      "message": "This is an authoring requirement. The queries explicitly select qualified; they do not recognize revenue."
    },
    {
      "id": "associations_are_not_causal",
      "level": "semantic",
      "severity": "review",
      "target": "example.gtm:relation:touchpoint:linked_opportunity:opportunity",
      "assertion": "An opportunity link records an association rather than causal marketing lift.",
      "message": "The query provides descriptive linked pipeline, not attribution credit, incrementality or MMM contribution."
    },
    {
      "id": "same_currency_only",
      "level": "semantic",
      "severity": "review",
      "target": "example.gtm:opportunity.currency",
      "assertion": "Every amount included in one aggregate must have the requested currency.",
      "message": "The example graph functions enforce a currency-equality filter; conversion requires a separate model."
    }
  ]
}
