{
  "contract_id": "viva-insights-query-join",
  "version": "0.7.0",
  "date": "2026-10-28",
  "status": "reference",
  "scope": "Joining weekly Viva Insights Person Query exports with Consumption, GitHub and Agent query exports into one person-week panel",
  "spine": "person_query.person",
  "input_requirements": {
    "required_query_ids": [
      "person_query"
    ],
    "additional_query_ids": [
      "consumption_query",
      "github_query",
      "agent_query"
    ],
    "minimum_additional_queries": 1,
    "recommendation": "Use all four queries for a broader view of ways of working and AI usage across the products and activities they measure.",
    "applicability": "Apply file requirements, joins and source-specific checks only to the selected queries. Record omitted queries as unavailable, without inferring non-use."
  },
  "naming_conventions": {
    "ids": "File and dataset IDs are references within this guide's contract. They are not exported columns, file paths or required names for objects in your script.",
    "derived_datasets": "Dataset labels describe intermediate summaries and the final panel that your script creates. Choose your own object names.",
    "week_start": "WeekStart is this guide's chosen name for an aligned week-start date. It is not an extra column supplied by the exports. You may keep MetricDate or choose another name, provided every source uses the same week definition."
  },
  "target_grain": {
    "keys": [
      "PersonId",
      "WeekStart"
    ],
    "person_query_cadence_required": "weekly",
    "week_start": "detect_from_person_query",
    "rule": "Export all selected queries grouped by week, with the same week start, wherever possible. This contract requires a weekly Person Query. `WeekStart` is its `MetricDate`. Consumption and GitHub default to daily, so change their grouping at setup. Use daily exports only when daily detail or week-start alignment is needed (G03, G03b)."
  },
  "coverage_assumption": {
    "complete_by_default": true,
    "scope": "The configured population, date window and product filters of each supplied Viva Insights query.",
    "missing_activity_rows": "Inactive person-days are excluded by default. Within the query's scope, treat omitted activity rows as zero activity, including a person-week with no activity rows. This does not require separate completeness evidence.",
    "exceptions": "Keep unavailable queries, out-of-scope people or periods, null cells in existing rows and known export problems distinct from inactivity. Partial boundary weeks do not establish full-week totals.",
    "eligibility": "Activity zeros do not establish product eligibility or licence status. Use product-specific evidence for adoption denominators."
  },
  "header_matching": "Headers are listed in their raw export form, with spaces. The vivainsights R and Python packages replace spaces with underscores when they import a query, so `Collaboration hours` becomes Collaboration_hours. Treat the two forms as the same column. This applies to headers only, never to identifier values.",
  "query_setup_recommendation": "For all four queries, we recommend the Create analysis route because it offers more customisation parameters than dashboard exports.",
  "queries": [
    {
      "id": "person_query",
      "name": "Person query",
      "role": "spine",
      "icon": "/assets/images/queries/person-query.svg",
      "product_description": "Analyse collaboration trends across the company",
      "recommended_path": [
        "Create analysis",
        "Customized query",
        "Person query"
      ],
      "access_context": "The Person query is available only through this route. It gives you access to the full Person query metric list, including behavioural metrics such as Email hours, Meeting hours and Internal network size. Select the metrics you need when setting up the query.",
      "cadence": "Weekly. Daily or monthly groupings are outside this contract.",
      "period_options": [
        "week"
      ],
      "default_period": "week",
      "verification": "observed_in_real_exports",
      "files": [
        {
          "id": "person_query.person",
          "file": "Person_<username>_<date>_<time>Hours.csv",
          "grain": "One row per person per week",
          "native_key": [
            "PersonId",
            "MetricDate"
          ],
          "required_for_layout_match": true,
          "required_for_core_panel": true,
          "columns": [
            {
              "name": "PersonId",
              "type": "string",
              "role": "key",
              "note": "Pseudonymised person identifier. Keep as text."
            },
            {
              "name": "MetricDate",
              "type": "date",
              "role": "key",
              "note": "Week start. Detect the weekday from the data."
            }
          ],
          "column_groups": [
            {
              "name": "HR attributes",
              "headers": "inspect_export",
              "note": "Configured at query setup. Observed examples: Organization, FunctionType, SupervisorIndicator, Layer. Values can change between weeks."
            },
            {
              "name": "Metric columns",
              "headers": "inspect_export",
              "note": "Selected at query setup. See the metric families table."
            }
          ],
          "file_pattern": "A single CSV, for example `Person_jdoe_Oct27_2026_1027Hours.csv`. Localised exports translate the words in the name, and the public sample fixture is `PersonQuery.csv`, so identify the file by its `PersonId` and `MetricDate` columns."
        }
      ]
    },
    {
      "id": "consumption_query",
      "name": "Consumption query",
      "role": "fact",
      "icon": "/assets/images/queries/consumption-query.svg",
      "product_description": "Analyse credit usage across services, users, groups, and spending policies.",
      "recommended_path": [
        "Create analysis",
        "Customized query",
        "Consumption query"
      ],
      "alternative_path": [
        "Consumption dashboard",
        "Export data"
      ],
      "cadence": "Daily by default, or weekly when grouped by week at setup. Facts plus metadata files.",
      "period_options": [
        "day",
        "week"
      ],
      "default_period": "day",
      "verification": "observed_in_real_exports",
      "files": [
        {
          "id": "consumption.m365_credits",
          "file": "PersonM365CreditsMetrics.csv",
          "grain": "One row per person, service, spending policy and period (day or week)",
          "native_key": [
            "PersonId",
            "ServiceId",
            "SpendingPolicyId",
            "MetricDate"
          ],
          "required_for_layout_match": true,
          "required_for_core_panel": true,
          "columns": [
            {
              "name": "PersonId",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "ServiceId",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "ServiceName",
              "type": "string",
              "role": "attribute",
              "note": ""
            },
            {
              "name": "SpendingPolicyId",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "MetricDate",
              "type": "date",
              "role": "key",
              "note": "Day or week start, as set at query setup."
            },
            {
              "name": "Session count",
              "type": "number",
              "role": "measure",
              "note": ""
            },
            {
              "name": "Spending policy limit",
              "type": "number",
              "role": "limit",
              "note": ""
            },
            {
              "name": "Total Copilot Credits used",
              "type": "number",
              "role": "measure",
              "note": ""
            },
            {
              "name": "User limit",
              "type": "number",
              "role": "limit",
              "note": ""
            },
            {
              "name": "PeopleHistoricalId",
              "type": "string",
              "role": "foreign_key",
              "note": "Links to `PeopleMetaData.csv`."
            }
          ],
          "column_groups": []
        },
        {
          "id": "consumption.github_credits",
          "file": "PersonGitHubCreditsMetrics.csv",
          "grain": "One row per person and period with billable GitHub usage (sparse)",
          "native_key": [
            "PersonId",
            "MetricDate"
          ],
          "required_for_layout_match": true,
          "required_for_core_panel": true,
          "columns": [
            {
              "name": "PersonId",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "MetricDate",
              "type": "date",
              "role": "key",
              "note": "Day or week start, as set at query setup."
            },
            {
              "name": "Total GitHub AI Credits used",
              "type": "number",
              "role": "measure",
              "note": ""
            },
            {
              "name": "PeopleHistoricalId",
              "type": "string",
              "role": "foreign_key",
              "note": "Links to `PeopleMetaData.csv`."
            }
          ],
          "column_groups": []
        },
        {
          "id": "consumption.people_metadata",
          "file": "PeopleMetaData.csv",
          "grain": "One row per historical person record",
          "native_key": [
            "PeopleHistoricalId"
          ],
          "required_for_layout_match": true,
          "required_for_core_panel": true,
          "columns": [
            {
              "name": "PeopleHistoricalId",
              "type": "string",
              "role": "key",
              "note": "No `PersonId` in this file."
            },
            {
              "name": "IsCopilotLicensed",
              "type": "boolean-like text",
              "role": "attribute",
              "note": "Historical Microsoft 365 Copilot licence evidence only. Not evidence of GitHub Copilot provisioning."
            }
          ],
          "column_groups": [],
          "note": "Carries no HR attributes. Take organisational attributes from the Person Query."
        },
        {
          "id": "consumption.policy_metadata",
          "file": "M365SpendingPolicyMetaData.csv",
          "grain": "One row per spending policy",
          "native_key": [
            "SpendingPolicyId"
          ],
          "required_for_layout_match": true,
          "required_for_core_panel": false,
          "columns": [
            {
              "name": "SpendingPolicyId",
              "type": "string",
              "role": "key",
              "note": ""
            }
          ],
          "column_groups": [
            {
              "name": "Policy attributes",
              "headers": "inspect_export",
              "note": "Descriptive policy fields. Inspect the headers in each export."
            }
          ]
        }
      ]
    },
    {
      "id": "github_query",
      "name": "GitHub query",
      "role": "fact",
      "icon": "/assets/images/queries/github-query.svg",
      "product_description": "Analyse GitHub Copilot usage to understand developer activity and coding trends.",
      "recommended_path": [
        "Create analysis",
        "Customized query",
        "GitHub query"
      ],
      "cadence": "Daily by default, or weekly when grouped by week at setup. Activity facts plus dimensional breakdowns.",
      "period_options": [
        "day",
        "week"
      ],
      "default_period": "day",
      "verification": "reference_schema_not_yet_verified_on_real_exports",
      "files": [
        {
          "id": "github.activity",
          "file": "PersonGitHubActivityMetrics.csv",
          "grain": "One row per person and period",
          "native_key": [
            "PersonId",
            "MetricDate"
          ],
          "required_for_layout_match": true,
          "required_for_core_panel": true,
          "columns": [
            {
              "name": "PersonId",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "MetricDate",
              "type": "date",
              "role": "key",
              "note": "Day or week start, as set at query setup."
            },
            {
              "name": "Agent adoption",
              "type": "number",
              "role": "indicator",
              "note": "Adoption indicator or percentage. Excludes code review."
            },
            {
              "name": "Code completions accepted",
              "type": "number",
              "role": "measure",
              "note": ""
            },
            {
              "name": "Code completions suggested",
              "type": "number",
              "role": "measure",
              "note": ""
            },
            {
              "name": "User-initiated chat requests",
              "type": "number",
              "role": "measure",
              "note": ""
            }
          ],
          "column_groups": []
        },
        {
          "id": "github.by_feature",
          "file": "GitHubActivityBreakdownByFeatureMetrics.csv",
          "grain": "One row per person, period and feature",
          "native_key": [
            "PersonId",
            "MetricDate",
            "Feature"
          ],
          "required_for_layout_match": true,
          "required_for_core_panel": false,
          "columns": [
            {
              "name": "PersonId",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "MetricDate",
              "type": "date",
              "role": "key",
              "note": ""
            },
            {
              "name": "Feature",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "Feature Usage Count",
              "type": "number",
              "role": "measure",
              "note": ""
            }
          ],
          "column_groups": []
        },
        {
          "id": "github.by_language_feature",
          "file": "GitHubActivityBreakdownByLanguageFeatureMetrics.csv",
          "grain": "One row per person, period, language and feature",
          "native_key": [
            "PersonId",
            "MetricDate",
            "Language",
            "Feature"
          ],
          "required_for_layout_match": true,
          "required_for_core_panel": false,
          "columns": [
            {
              "name": "PersonId",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "MetricDate",
              "type": "date",
              "role": "key",
              "note": ""
            },
            {
              "name": "Language",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "Feature",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "Usage count by language and feature",
              "type": "number",
              "role": "measure",
              "note": ""
            }
          ],
          "column_groups": []
        },
        {
          "id": "github.by_language_model",
          "file": "GitHubActivityBreakdownByLanguageModelMetrics.csv",
          "grain": "One row per person, period, language and model",
          "native_key": [
            "PersonId",
            "MetricDate",
            "Language",
            "Model"
          ],
          "required_for_layout_match": true,
          "required_for_core_panel": false,
          "columns": [
            {
              "name": "PersonId",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "MetricDate",
              "type": "date",
              "role": "key",
              "note": ""
            },
            {
              "name": "Language",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "Model",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "Usage count by language and model",
              "type": "number",
              "role": "measure",
              "note": ""
            }
          ],
          "column_groups": []
        },
        {
          "id": "github.by_model_feature",
          "file": "GitHubActivityBreakdownByModelFeatureMetrics.csv",
          "grain": "One row per person, period, model and feature",
          "native_key": [
            "PersonId",
            "MetricDate",
            "Model",
            "Feature"
          ],
          "required_for_layout_match": true,
          "required_for_core_panel": false,
          "columns": [
            {
              "name": "PersonId",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "MetricDate",
              "type": "date",
              "role": "key",
              "note": ""
            },
            {
              "name": "Model",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "Feature",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "Usage count by model and feature",
              "type": "number",
              "role": "measure",
              "note": ""
            }
          ],
          "column_groups": []
        }
      ]
    },
    {
      "id": "agent_query",
      "name": "Agent query",
      "role": "fact",
      "icon": "/assets/images/queries/agent-query.svg",
      "product_description": "Analyse agent adoption trends across the company",
      "recommended_path": [
        "Create analysis",
        "Customized query",
        "Agent query"
      ],
      "alternative_path": [
        "Agent Dashboard",
        "Export data"
      ],
      "cadence": "Weekly facts with an optional metadata file.",
      "period_options": [
        "week"
      ],
      "default_period": "week",
      "verification": "observed_in_real_exports",
      "files": [
        {
          "id": "agent.activity",
          "file": "PersonAgentActivityMetrics.csv",
          "grain": "One row per person, agent and week",
          "native_key": [
            "PersonId",
            "AgentId",
            "MetricDate"
          ],
          "required_for_layout_match": true,
          "required_for_core_panel": true,
          "columns": [
            {
              "name": "PersonId",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "AgentId",
              "type": "string",
              "role": "key",
              "note": ""
            },
            {
              "name": "MetricDate",
              "type": "date",
              "role": "key",
              "note": "Weekly. Sunday-start in observed exports."
            },
            {
              "name": "Conversational agent sessions",
              "type": "number",
              "role": "measure",
              "note": ""
            },
            {
              "name": "Returning Agent 365 user (most recent and prior 7 days)",
              "type": "number",
              "role": "indicator",
              "note": "0 or 1 over a 7-day window."
            },
            {
              "name": "Returning Agent 365 user (most recent and prior 28 days)",
              "type": "number",
              "role": "indicator",
              "note": "0 or 1 over a 28-day window."
            }
          ],
          "column_groups": []
        },
        {
          "id": "agent.metadata",
          "file": "AgentMetadata.csv",
          "grain": "One row per agent",
          "native_key": [
            "AgentId"
          ],
          "required_for_layout_match": false,
          "required_for_core_panel": false,
          "columns": [
            {
              "name": "AgentId",
              "type": "string",
              "role": "key",
              "note": ""
            }
          ],
          "column_groups": [
            {
              "name": "Agent attributes",
              "headers": "inspect_export",
              "note": "Descriptive agent fields. Inspect the headers in each export. Never use them to identify people."
            }
          ],
          "note": "Present in some exports and absent in others."
        }
      ]
    }
  ],
  "derived_datasets": [
    {
      "id": "summary.m365_credits_person_week",
      "label": "Microsoft 365 credits summary",
      "from_file_ids": [
        "consumption.m365_credits"
      ],
      "grain": [
        "PersonId",
        "WeekStart"
      ],
      "build_steps": [
        5,
        6
      ],
      "built_by": "Sum credits across services and spending policies after G05, and across days if the export is daily. Include sessions summed across policies only when G05b passes."
    },
    {
      "id": "summary.github_credits_person_week",
      "label": "GitHub credits summary",
      "from_file_ids": [
        "consumption.github_credits"
      ],
      "grain": [
        "PersonId",
        "WeekStart"
      ],
      "build_steps": [
        6
      ],
      "built_by": "Sum credits across days if the export is daily. A weekly export is already one row per person-week."
    },
    {
      "id": "summary.github_activity_person_week",
      "label": "GitHub activity summary",
      "from_file_ids": [
        "github.activity"
      ],
      "grain": [
        "PersonId",
        "WeekStart"
      ],
      "build_steps": [
        6
      ],
      "built_by": "Apply the measure rules, aggregating across days only if the export is daily."
    },
    {
      "id": "summary.agent_person_week",
      "label": "Agent activity summary",
      "from_file_ids": [
        "agent.activity"
      ],
      "grain": [
        "PersonId",
        "WeekStart"
      ],
      "build_steps": [
        6
      ],
      "built_by": "Sum sessions across agents. Derive any person-level returning flag explicitly."
    },
    {
      "id": "panel.person_week",
      "label": "Combined person-week panel",
      "from_file_ids": [
        "person_query.person"
      ],
      "grain": [
        "PersonId",
        "WeekStart"
      ],
      "build_steps": [
        7
      ],
      "built_by": "Start with the Person Query and left join each summary. Keep every Person Query row."
    }
  ],
  "person_query_metric_families": [
    {
      "family": "Collaboration",
      "kind": "weekly_total",
      "headers": [
        "Collaboration hours",
        "External collaboration hours",
        "Meeting hours",
        "Email hours",
        "Chat hours",
        "After hours collaboration hours"
      ]
    },
    {
      "family": "Focus",
      "kind": "weekly_total",
      "headers": [
        "Available to focus hours",
        "Uninterrupted hours"
      ]
    },
    {
      "family": "Network",
      "kind": "stock",
      "headers": [
        "Internal network size",
        "External network size",
        "Strong ties",
        "Diverse ties",
        "Network outside organization"
      ]
    },
    {
      "family": "Copilot eligibility",
      "kind": "day_count",
      "headers": [
        "Total Copilot enabled days"
      ]
    },
    {
      "family": "Copilot activity, totals",
      "kind": "weekly_total_or_day_count",
      "headers": [
        "Total Copilot actions taken",
        "Total Copilot active days"
      ]
    },
    {
      "family": "Copilot activity, by surface",
      "kind": "weekly_total_or_day_count",
      "headers": [
        "Copilot actions taken in Copilot Chat",
        "Copilot actions taken in Microsoft 365 Copilot app",
        "Days of active Copilot Chat usage",
        "Days of active Copilot Chat (legacy web) usage",
        "Days of active Copilot usage in Excel",
        "Days of active Copilot usage in Loop",
        "Days of active Copilot usage in OneNote",
        "Days of active Copilot usage in Outlook",
        "Days of active Copilot usage in Powerpoint",
        "Days of active Copilot usage in Teams",
        "Days of active Copilot usage in Word"
      ]
    },
    {
      "family": "Cowork",
      "kind": "weekly_total_or_day_count",
      "headers": [
        "Cowork tasks submitted",
        "User-initiated Cowork tasks submitted",
        "Days of active Cowork usage"
      ]
    },
    {
      "family": "Unlicensed Copilot Chat",
      "kind": "weekly_total_or_day_count",
      "note": "A separate metric family for Copilot Chat use without a Microsoft 365 Copilot licence. Inspect the export for its headers and keep it separate from licensed Copilot metrics.",
      "headers": []
    }
  ],
  "relationships": [
    {
      "id": "J1",
      "from_id": "consumption.m365_credits",
      "to_id": "consumption.people_metadata",
      "on": [
        "PeopleHistoricalId"
      ],
      "cardinality": "many_to_one",
      "purpose": "Microsoft 365 Copilot licence evidence, before aggregation"
    },
    {
      "id": "J2",
      "from_id": "consumption.github_credits",
      "to_id": "consumption.people_metadata",
      "on": [
        "PeopleHistoricalId"
      ],
      "cardinality": "many_to_one",
      "purpose": "Check that each historical person record exists. `IsCopilotLicensed` describes Microsoft 365 only and cannot confirm GitHub eligibility."
    },
    {
      "id": "J3",
      "from_id": "consumption.m365_credits",
      "to_id": "consumption.policy_metadata",
      "on": [
        "SpendingPolicyId"
      ],
      "cardinality": "many_to_one",
      "purpose": "Check that each spending policy exists in the metadata."
    },
    {
      "id": "J4",
      "from_id": "agent.activity",
      "to_id": "agent.metadata",
      "on": [
        "AgentId"
      ],
      "cardinality": "many_to_one",
      "purpose": "Optional enrichment, only when the metadata file is supplied"
    },
    {
      "id": "J5",
      "from_id": "summary.m365_credits_person_week",
      "to_id": "panel.person_week",
      "on": [
        "PersonId",
        "WeekStart"
      ],
      "cardinality": "one_to_one",
      "purpose": "Left join onto the spine"
    },
    {
      "id": "J6",
      "from_id": "summary.github_credits_person_week",
      "to_id": "panel.person_week",
      "on": [
        "PersonId",
        "WeekStart"
      ],
      "cardinality": "one_to_one",
      "purpose": "Left join onto the spine"
    },
    {
      "id": "J7",
      "from_id": "summary.github_activity_person_week",
      "to_id": "panel.person_week",
      "on": [
        "PersonId",
        "WeekStart"
      ],
      "cardinality": "one_to_one",
      "purpose": "Left join onto the spine"
    },
    {
      "id": "J8",
      "from_id": "summary.agent_person_week",
      "to_id": "panel.person_week",
      "on": [
        "PersonId",
        "WeekStart"
      ],
      "cardinality": "one_to_one",
      "purpose": "Left join onto the spine"
    },
    {
      "id": "J9",
      "from_ids": [
        "github.by_feature",
        "github.by_language_feature",
        "github.by_language_model",
        "github.by_model_feature"
      ],
      "to_id": "panel.person_week",
      "on": [
        "PersonId",
        "WeekStart"
      ],
      "cardinality": "linked_detail",
      "purpose": "Never joined wide. Keep as separate detail tables keyed to the panel"
    }
  ],
  "measures": [
    {
      "id": "M01",
      "file_id": "consumption.m365_credits",
      "columns": [
        "Total Copilot Credits used"
      ],
      "kind": "additive",
      "person_week_rule": "Sum across services and spending policies after G05 passes, and across days when the export is daily."
    },
    {
      "id": "M02",
      "file_id": "consumption.m365_credits",
      "columns": [
        "Session count"
      ],
      "kind": "conditionally_additive",
      "person_week_rule": "Sum across services, and across days when the export is daily. Sum across `SpendingPolicyId` rows only when G05b passes. Sessions are not people."
    },
    {
      "id": "M03",
      "file_id": "consumption.m365_credits",
      "columns": [
        "Spending policy limit",
        "User limit"
      ],
      "kind": "limit",
      "person_week_rule": "Never sum. Keep per policy as linked detail."
    },
    {
      "id": "M04",
      "file_id": "consumption.github_credits",
      "columns": [
        "Total GitHub AI Credits used"
      ],
      "kind": "additive",
      "person_week_rule": "Sum across days when the export is daily. Keep separate from Microsoft 365 credits."
    },
    {
      "id": "M05",
      "file_id": "github.activity",
      "columns": [
        "Code completions accepted",
        "Code completions suggested",
        "User-initiated chat requests"
      ],
      "kind": "additive",
      "person_week_rule": "Sum across days when the export is daily. Acceptance rate is summed accepted divided by summed suggested, with a stated zero-denominator rule."
    },
    {
      "id": "M06",
      "file_id": "github.activity",
      "columns": [
        "Agent adoption"
      ],
      "kind": "indicator",
      "person_week_rule": "Do not sum. For a daily export, state a derived weekly rule, for example any positive day in the week. For a weekly export, use the exported value."
    },
    {
      "id": "M07",
      "file_id": "github.by_feature",
      "columns": [
        "Feature Usage Count"
      ],
      "kind": "additive_within_file",
      "person_week_rule": "Sum days within this file when daily, retaining Feature for each person-week. Keep as linked detail. Never add to another breakdown."
    },
    {
      "id": "M08",
      "file_id": "github.by_language_feature",
      "columns": [
        "Usage count by language and feature"
      ],
      "kind": "additive_within_file",
      "person_week_rule": "Sum days within this file when daily, retaining Language and Feature for each person-week. Keep as linked detail. Never add to another breakdown."
    },
    {
      "id": "M09",
      "file_id": "github.by_language_model",
      "columns": [
        "Usage count by language and model"
      ],
      "kind": "additive_within_file",
      "person_week_rule": "Sum days within this file when daily, retaining Language and Model for each person-week. Keep as linked detail. Never add to another breakdown."
    },
    {
      "id": "M10",
      "file_id": "github.by_model_feature",
      "columns": [
        "Usage count by model and feature"
      ],
      "kind": "additive_within_file",
      "person_week_rule": "Sum days within this file when daily, retaining Model and Feature for each person-week. Keep as linked detail. Never add to another breakdown."
    },
    {
      "id": "M11",
      "file_id": "agent.activity",
      "columns": [
        "Conversational agent sessions"
      ],
      "kind": "additive",
      "person_week_rule": "Sum across agents to person-week."
    },
    {
      "id": "M12",
      "file_id": "agent.activity",
      "columns": [
        "Returning Agent 365 user (most recent and prior 7 days)"
      ],
      "kind": "window_indicator",
      "person_week_rule": "Do not sum across agents or weeks. A person-level flag, such as returning for any agent, is a stated derived definition."
    },
    {
      "id": "M13",
      "file_id": "agent.activity",
      "columns": [
        "Returning Agent 365 user (most recent and prior 28 days)"
      ],
      "kind": "window_indicator",
      "person_week_rule": "Do not sum across agents or weeks. A person-level flag, such as returning for any agent, is a stated derived definition."
    },
    {
      "id": "M14",
      "file_id": "person_query.person",
      "columns": [
        "Internal network size",
        "External network size"
      ],
      "kind": "stock",
      "person_week_rule": "Detect and record the measurement window. Values can repeat within a month. Average or deduplicate snapshots according to that window, never sum."
    },
    {
      "id": "M15",
      "file_id": "person_query.person",
      "columns": [
        "Days of active Copilot Chat usage",
        "Days of active Copilot Chat (legacy web) usage",
        "Days of active Copilot usage in Excel",
        "Days of active Copilot usage in Loop",
        "Days of active Copilot usage in OneNote",
        "Days of active Copilot usage in Outlook",
        "Days of active Copilot usage in Powerpoint",
        "Days of active Copilot usage in Teams",
        "Days of active Copilot usage in Word"
      ],
      "kind": "day_count",
      "person_week_rule": "Never add across surfaces to make total active days, because one day can include several surfaces. Use `Total Copilot active days`."
    }
  ],
  "missingness_states": [
    {
      "id": "observed_positive",
      "meaning": "A row exists with a positive value"
    },
    {
      "id": "observed_zero",
      "meaning": "A row exists with a recorded zero"
    },
    {
      "id": "absent_inactive_zero",
      "meaning": "No activity row within a supplied query's configured population and date window. Assume complete Viva Insights data and record zero activity"
    },
    {
      "id": "absent_unknown",
      "meaning": "The query is unavailable, the person or period is outside its scope, a known export problem applies, or an absent non-activity measure has no defined zero interpretation. Keep as unknown"
    },
    {
      "id": "observed_null",
      "meaning": "A row exists but the measure is null. Do not apply the omitted-inactive-row default to this cell"
    },
    {
      "id": "ineligible",
      "meaning": "Not eligible for that product in the week"
    },
    {
      "id": "outside_cohort",
      "meaning": "Not selected by the analysis cohort rule"
    }
  ],
  "gates": [
    {
      "id": "G01",
      "level": "MUST",
      "rule": "Require the Person Query plus at least one of Consumption, GitHub or Agent. Record which queries are supplied and identify each export's layout. Within each selected query, files with `required_for_layout_match` set to true must all be present. If files or key columns differ from this contract, stop and record the difference."
    },
    {
      "id": "G02",
      "level": "MUST",
      "rule": "Read identifiers as text. Do not change their case, trim them silently or fuzzy-match people."
    },
    {
      "id": "G03",
      "level": "MUST",
      "rule": "Confirm weekly grouping from the Person Query configuration or equivalent export metadata, then validate one row per `PersonId` and `MetricDate` and detect the weekday of `MetricDate`. Stop if grouping is unknown, daily or monthly. Do not assume Monday or Sunday."
    },
    {
      "id": "G03b",
      "level": "MUST",
      "rule": "Record each fact export's configured date grouping from query setup or equivalent export metadata, then validate `MetricDate` against it. Sparse dates alone cannot establish cadence. Recommend weekly grouping for all queries. Daily and weekly exports are supported. A weekly export must start on the same weekday as the Person Query. Stop for unknown grouping, any other period such as monthly, or a different weekly start."
    },
    {
      "id": "G04",
      "level": "MUST",
      "rule": "Assert uniqueness of each file's native key. Report duplicate counts and stop. Never keep an arbitrary first row."
    },
    {
      "id": "G05",
      "level": "MUST",
      "rule": "Before summing Microsoft 365 credits across `SpendingPolicyId`, count person-service-period keys with more than one positive-credit row. If any exist, obtain a documented confirmation that the rows record disjoint consumption."
    },
    {
      "id": "G05b",
      "level": "MUST",
      "rule": "Sum `Session count` across `SpendingPolicyId` rows only when the documented confirmation explicitly covers sessions. Otherwise keep sessions per policy."
    },
    {
      "id": "G06",
      "level": "MUST",
      "rule": "Join metadata many-to-one on unique keys. Report unmatched key counts without identifiers. Check that each `PeopleHistoricalId` maps to one `PersonId`."
    },
    {
      "id": "G07",
      "level": "MUST",
      "rule": "Bring only panel-bound summaries to one row per `PersonId` and `WeekStart` before joining. Apply the measure rules: sum days only for configured daily exports, credits across policies only after G05, and sessions across policies only after G05b. Otherwise retain sessions per policy outside the panel. Keep GitHub breakdown dimensions as linked detail under G11. Never expand weekly rows into invented daily rows."
    },
    {
      "id": "G08",
      "level": "MUST",
      "rule": "Left join each person-week summary onto the Person Query. Assert one-to-one, preserve the Person Query row count, and reconcile additive totals before and after."
    },
    {
      "id": "G09",
      "level": "MUST",
      "rule": "Assume supplied Viva Insights queries are complete within their configured population, date window and product filters. Omitted activity rows represent inactivity by default, so record zero activity within that scope without requiring separate completeness evidence. Do not zero-fill unavailable queries, out-of-scope periods or people, null cells in existing rows, rolling indicators, limits, or known export problems. Record partial boundary weeks separately. Eligibility is a separate attribute: Microsoft 365 licence evidence never confirms GitHub eligibility."
    },
    {
      "id": "G10",
      "level": "MUST",
      "rule": "Keep Microsoft 365 and GitHub credits in separate columns. Never derive tokens or currency from credits."
    },
    {
      "id": "G11",
      "level": "MUST",
      "rule": "Do not join GitHub breakdown files wide. Keep them as linked detail tables."
    },
    {
      "id": "G12",
      "level": "SHOULD",
      "rule": "Treat integration and cohort selection as separate, declared steps. An unavailable query does not establish non-use."
    },
    {
      "id": "G13",
      "level": "SHOULD",
      "rule": "Record each variable's measurement window. Network sizes can repeat within a month and are averaged rather than summed."
    },
    {
      "id": "G14",
      "level": "MUST",
      "rule": "Coverage, licence and additivity confirmations apply only to the export they were given for."
    },
    {
      "id": "G15",
      "level": "MUST",
      "rule": "Check `PersonId` overlap between sources before joining. Investigate low overlap against activity filters, omitted inactive people and configured populations before concluding that pseudonymisation differs. Do not repair identifiers by matching on attributes."
    },
    {
      "id": "G16",
      "level": "MUST",
      "rule": "Publish a group only when it contains at least 10 distinct people, counted with count_distinct(`PersonId`), in every filter and time slice. Withhold an entire related breakdown if remaining cells or totals would reveal a suppressed cell by subtraction. Never output identifiers."
    },
    {
      "id": "G17",
      "level": "MUST",
      "rule": "Describe joined results as associations. Credits, sessions and actions do not measure value, quality or productivity."
    }
  ]
}
