{
 "schema_version": 1,
 "book": "data-governance-as-code",
 "edition": "2026.10.1",
 "line": "main",
 "prev_edition": null,
 "chapters": [
  {
   "chapter_id": "governance-end-to-end",
   "title": "Governance end to end",
   "order": 1,
   "file": "chapters/01-governance-end-to-end.md",
   "sha256": "5a158c4ed3c4fb33c5df006f6e510f8d702b2cd32d293c60a98f8e6fd47ec18d",
   "changed": true
  },
  {
   "chapter_id": "a-catalog-you-can-test",
   "title": "A catalog you can test",
   "order": 2,
   "file": "chapters/02-a-catalog-you-can-test.md",
   "sha256": "f16e71b4d6f05889003d6234cbb6919099b5df5993272186e48bc8c406b219d4",
   "changed": true
  },
  {
   "chapter_id": "finding-personal-data",
   "title": "Finding personal data",
   "order": 3,
   "file": "chapters/03-finding-personal-data.md",
   "sha256": "e62ea9929db1f17008301dbd000351a55dfa28dbf55960c2de0f27bd1682d7ab",
   "changed": true
  },
  {
   "chapter_id": "lineage-from-pipelines",
   "title": "Lineage from pipelines",
   "order": 4,
   "file": "chapters/04-lineage-from-pipelines.md",
   "sha256": "bd515a145dfac17d16b5c872b154c0db740fe20fd6e7518a4fef9ccebf8200ef",
   "changed": true
  },
  {
   "chapter_id": "access-policies-as-code",
   "title": "Access policies as code",
   "order": 5,
   "file": "chapters/05-access-policies-as-code.md",
   "sha256": "c03f7c21db7ff8505cbd44ab53014c16e9a5eff1117edfb9ababf1b17df38498",
   "changed": true
  },
  {
   "chapter_id": "enforcing-policies-on-queries",
   "title": "Enforcing policies on queries",
   "order": 6,
   "file": "chapters/06-enforcing-policies-on-queries.md",
   "sha256": "c4e8e23aa7dd7402382b5fab48d67df3a628f4db70f6d3a15a2f62afd33c7a5e",
   "changed": true
  },
  {
   "chapter_id": "retention-consent-erasure",
   "title": "Retention, consent and erasure",
   "order": 7,
   "file": "chapters/07-retention-consent-erasure.md",
   "sha256": "4b56ea9e4c74181bdb13be06d10faf1392622b90d3190c4133e0d78b2c9e209a",
   "changed": true
  },
  {
   "chapter_id": "audit-and-evidence",
   "title": "Audit and evidence",
   "order": 8,
   "file": "chapters/08-audit-and-evidence.md",
   "sha256": "3017be8dfdca3bc997a8d2a3c318d99de5ecedee9355dd41bd4fe69ae8c35bb6",
   "changed": true
  },
  {
   "chapter_id": "governing-data-for-ai",
   "title": "Governing data for AI",
   "order": 9,
   "file": "chapters/09-governing-data-for-ai.md",
   "sha256": "0be6c62c71470e9d8fb272ae936b7255c148a5138900bad6581b8e6485cefd1c",
   "changed": true
  },
  {
   "chapter_id": "governance-in-ci",
   "title": "Governance in CI",
   "order": 10,
   "file": "chapters/10-governance-in-ci.md",
   "sha256": "cee3abac4f82d9d09ffd5e8697262f1c45f6eb52eef45b86a8f902e60b0db8fe",
   "changed": true
  }
 ],
 "sections": [
  {
   "section_id": "catalog-a-table",
   "chapter_id": "governance-end-to-end",
   "title": "Catalog a table with its owner and classifications",
   "order": 1,
   "level": 2,
   "parent_id": null,
   "sha256": "d734499234efbfb6d6bba1e87648e2cf841ea471f8fbad42061228235bff094f",
   "changed": true,
   "example_ids": [
    "catalog-the-learners"
   ]
  },
  {
   "section_id": "capture-one-pipelines-lineage",
   "chapter_id": "governance-end-to-end",
   "title": "Capture one pipeline's column lineage",
   "order": 2,
   "level": 2,
   "parent_id": null,
   "sha256": "e386c5fb66c15c8a9bdac0e71bbf6951c5cc672a40a22e4780a196d72171a9c5",
   "changed": true,
   "example_ids": [
    "audience-pipeline-lineage"
   ]
  },
  {
   "section_id": "enforce-one-access-decision",
   "chapter_id": "governance-end-to-end",
   "title": "Enforce one access decision on a query",
   "order": 3,
   "level": 2,
   "parent_id": null,
   "sha256": "92bb49b3b3196e2d38648dee8e638c208f8f2232c932af844a0a9b6d970c2bda",
   "changed": true,
   "example_ids": [
    "support-region-enforced"
   ]
  },
  {
   "section_id": "fail-the-pull-request",
   "chapter_id": "governance-end-to-end",
   "title": "Fail the pull request that adds an unclassified column",
   "order": 4,
   "level": 2,
   "parent_id": null,
   "sha256": "ad0c67c5fdf536e00f47f52694f99a9c271ee966155d4d2b10eeab0535fed160",
   "changed": true,
   "example_ids": [
    "unclassified-column-fails"
   ]
  },
  {
   "section_id": "end-to-end-in-production",
   "chapter_id": "governance-end-to-end",
   "title": "What goes wrong in production",
   "order": 5,
   "level": 2,
   "parent_id": null,
   "sha256": "44281639d05c51246f34bbd5f46abd469c8b6da7a8b777535b0f4a7806519469",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "a-spreadsheet-nobody-updates",
   "chapter_id": "governance-end-to-end",
   "title": "A governance spreadsheet nobody updates",
   "order": 6,
   "level": 3,
   "parent_id": "end-to-end-in-production",
   "sha256": "5f9c40a332aedd076b2ade65930619c7dc48c3755cf2736422e4ddd9b874e41c",
   "changed": true,
   "example_ids": [
    "spreadsheet-misses-new-column"
   ]
  },
  {
   "section_id": "a-policy-another-tool-bypasses",
   "chapter_id": "governance-end-to-end",
   "title": "A policy one tool enforces and another bypasses",
   "order": 7,
   "level": 3,
   "parent_id": "end-to-end-in-production",
   "sha256": "4df60ccdd1cd17748350ea7ed3324b4af5605da5f9e08a6634dac58149e7e720",
   "changed": true,
   "example_ids": [
    "read-around-the-layer"
   ]
  },
  {
   "section_id": "end-to-end-decisions",
   "chapter_id": "governance-end-to-end",
   "title": "What this chapter decided",
   "order": 8,
   "level": 2,
   "parent_id": null,
   "sha256": "253790ed3131700a950c207d60dcf9c913da6b45467ee3167d79fd07924c4e13",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "keep-metadata-in-a-reviewed-file",
   "chapter_id": "a-catalog-you-can-test",
   "title": "Keep the metadata in a reviewed file",
   "order": 9,
   "level": 2,
   "parent_id": null,
   "sha256": "c625585550aeddb14606ba284825c2c6cd4d606c9dc5d6b37742bbf392effb59",
   "changed": true,
   "example_ids": [
    "metadata-model"
   ]
  },
  {
   "section_id": "key-column-metadata-by-field-id",
   "chapter_id": "a-catalog-you-can-test",
   "title": "Key column metadata by field ID",
   "order": 10,
   "level": 2,
   "parent_id": null,
   "sha256": "ae42216b02a533401db1abaf6c5660b1b69a5777a6ca6f18e61a7d44b94dc55e",
   "changed": true,
   "example_ids": [
    "rename-orphans-name-keys"
   ]
  },
  {
   "section_id": "write-descriptions-into-the-schema",
   "chapter_id": "a-catalog-you-can-test",
   "title": "Write descriptions into the table's schema",
   "order": 11,
   "level": 2,
   "parent_id": null,
   "sha256": "978c088f8c358cc38867e5199dc85770d4c210e5d97aa44c3e9acf34c75ebf1c",
   "changed": true,
   "example_ids": [
    "apply-metadata"
   ]
  },
  {
   "section_id": "a-description-edit-is-a-schema-change",
   "chapter_id": "a-catalog-you-can-test",
   "title": "A description edit is a schema change",
   "order": 12,
   "level": 3,
   "parent_id": "write-descriptions-into-the-schema",
   "sha256": "3f039bb1f4a108c39d792debf3b9c3d31ab7d0ef92ded0ac08978d6626e43593",
   "changed": true,
   "example_ids": [
    "doc-edit-schema-id"
   ]
  },
  {
   "section_id": "test-the-catalog-against-the-metadata",
   "chapter_id": "a-catalog-you-can-test",
   "title": "Test the catalog against the metadata",
   "order": 13,
   "level": 2,
   "parent_id": null,
   "sha256": "60e629e85c005496ab89fed32e7a4cffea7ef17400cb53c6425a38ed68bbd7b5",
   "changed": true,
   "example_ids": [
    "metadata-gaps"
   ]
  },
  {
   "section_id": "catch-schema-changes",
   "chapter_id": "a-catalog-you-can-test",
   "title": "Catch schema changes before the metadata goes stale",
   "order": 14,
   "level": 2,
   "parent_id": null,
   "sha256": "82d8ef41dfe0521e5d7ae13e422f5f7b10bbd338a4d8b6fb1ab01be4cfad6fb8",
   "changed": true,
   "example_ids": [
    "schema-changes-checked"
   ]
  },
  {
   "section_id": "classify-pseudonymous-ids",
   "chapter_id": "a-catalog-you-can-test",
   "title": "Classify pseudonymous IDs for joining",
   "order": 15,
   "level": 2,
   "parent_id": null,
   "sha256": "2022dd9feaea272aff39b9a7944b9c8aa57a03e1e113398eb8f0068b8cdc4051",
   "changed": true,
   "example_ids": [
    "pseudonymous-learner-id"
   ]
  },
  {
   "section_id": "draft-descriptions-with-a-local-model",
   "chapter_id": "a-catalog-you-can-test",
   "title": "Draft metadata with a local model",
   "order": 16,
   "level": 2,
   "parent_id": null,
   "sha256": "fbf184c7c4e0f6e820487ac688a544d59cf75d71608edbe370d41a51baed8e91",
   "changed": true,
   "example_ids": [
    "suggestion-agreement"
   ]
  },
  {
   "section_id": "prompt-examples-give-answers-away",
   "chapter_id": "a-catalog-you-can-test",
   "title": "Examples in a prompt can give the answer away",
   "order": 17,
   "level": 3,
   "parent_id": "draft-descriptions-with-a-local-model",
   "sha256": "4b6568834b6a50297160d86b481df982dc5c07b1db7bfbdea0715bbf1a3f3c24",
   "changed": true,
   "example_ids": [
    "suggestions-with-platform-examples"
   ]
  },
  {
   "section_id": "measure-where-the-drafts-are-wrong",
   "chapter_id": "a-catalog-you-can-test",
   "title": "Measure where the model's drafts are wrong",
   "order": 18,
   "level": 2,
   "parent_id": null,
   "sha256": "adfbce9075404668ac04d1babd714a4f3d6827005bdbb3cf256497e0fedd14e0",
   "changed": true,
   "example_ids": [
    "suggestion-mistakes",
    "suggestion-descriptions"
   ]
  },
  {
   "section_id": "catalog-in-production",
   "chapter_id": "a-catalog-you-can-test",
   "title": "What goes wrong in production",
   "order": 19,
   "level": 2,
   "parent_id": null,
   "sha256": "041b5fd63af33f8e72517da5005124a0b11448f710f45046320fb9c78ca3ea31",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "catalog-decisions",
   "chapter_id": "a-catalog-you-can-test",
   "title": "What this chapter decided",
   "order": 20,
   "level": 2,
   "parent_id": null,
   "sha256": "c5741339e528bf9b32c5500ee009195753de44091d18a9056cdc09aeb5cdc0c5",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "classify-columns-from-the-schema",
   "chapter_id": "finding-personal-data",
   "title": "Classify columns from the schema",
   "order": 21,
   "level": 2,
   "parent_id": null,
   "sha256": "750f91fa15d643be7f78f02dac944b8b04d517339c35ca1184c944e9634e711a",
   "changed": true,
   "example_ids": [
    "column-name-rules"
   ]
  },
  {
   "section_id": "run-presidio-offline",
   "chapter_id": "finding-personal-data",
   "title": "Run Presidio offline",
   "order": 22,
   "level": 2,
   "parent_id": null,
   "sha256": "18bce715d8faead954325a46837b40805be49f34d460e02f6918a0d4c6e59c81",
   "changed": true,
   "example_ids": [
    "presidio-offline-engine"
   ]
  },
  {
   "section_id": "sample-column-values",
   "chapter_id": "finding-personal-data",
   "title": "Sample a column's values the same way every run",
   "order": 23,
   "level": 2,
   "parent_id": null,
   "sha256": "6badc30e01c478a9b95d6d17227f85467c8661e4cc8922237fe57466350ca053",
   "changed": true,
   "example_ids": [
    "seeded-column-sample"
   ]
  },
  {
   "section_id": "classify-columns-from-their-values",
   "chapter_id": "finding-personal-data",
   "title": "Classify columns from their values",
   "order": 24,
   "level": 2,
   "parent_id": null,
   "sha256": "ce60f70d2ef27563c8b6efee1c260c3768d4d9ce7f27117fd1e9a7f79767fe20",
   "changed": true,
   "example_ids": [
    "classify-sampled-columns"
   ]
  },
  {
   "section_id": "measure-against-labelled-spans",
   "chapter_id": "finding-personal-data",
   "title": "Measure a detector against labelled spans",
   "order": 25,
   "level": 2,
   "parent_id": null,
   "sha256": "a2aa2e2fa05c14bcc3ed2523014f6f1b50c6751c06b6c96ec787a0ea963db37e",
   "changed": true,
   "example_ids": [
    "measure-pattern-recognizers"
   ]
  },
  {
   "section_id": "tune-the-recognizers",
   "chapter_id": "finding-personal-data",
   "title": "Tune the recognizers against the truth",
   "order": 26,
   "level": 2,
   "parent_id": null,
   "sha256": "da037689fe885d320d5bb8b240fc1780267daae52b6228fb25dd4bf9c862c8d6",
   "changed": true,
   "example_ids": [
    "tune-pattern-recognizers"
   ]
  },
  {
   "section_id": "where-patterns-fail",
   "chapter_id": "finding-personal-data",
   "title": "See where patterns fail",
   "order": 27,
   "level": 2,
   "parent_id": null,
   "sha256": "6207906ec9182ef60fef812bce6ec95bf48e51cc7859b57ecd8f93319526d28e",
   "changed": true,
   "example_ids": [
    "pattern-hard-cases"
   ]
  },
  {
   "section_id": "compare-a-named-entity-model",
   "chapter_id": "finding-personal-data",
   "title": "Compare a PII model",
   "order": 28,
   "level": 2,
   "parent_id": null,
   "sha256": "738247238208ce760356e94ad909b2f2267732e4d366494abc49ac0031becef4",
   "changed": true,
   "example_ids": [
    "privacy-filter-spans"
   ]
  },
  {
   "section_id": "read-the-models-misses",
   "chapter_id": "finding-personal-data",
   "title": "Read the model's misses",
   "order": 29,
   "level": 3,
   "parent_id": "compare-a-named-entity-model",
   "sha256": "064a7c3b916c16ff26d1e760e3b91cc94a1e9b52fc9efe5e13b3cf9b81cb8a20",
   "changed": true,
   "example_ids": [
    "privacy-filter-hard-cases"
   ]
  },
  {
   "section_id": "what-a-wrong-label-costs",
   "chapter_id": "finding-personal-data",
   "title": "Count what a wrong label costs",
   "order": 30,
   "level": 2,
   "parent_id": null,
   "sha256": "d71262d4627868debab3f5fc6f78375313ad6718411861dd564fb2fdbf8f0e68",
   "changed": true,
   "example_ids": [
    "privacy-filter-labels"
   ]
  },
  {
   "section_id": "reclassify-on-schema-change",
   "chapter_id": "finding-personal-data",
   "title": "Classify again when the schema changes",
   "order": 31,
   "level": 2,
   "parent_id": null,
   "sha256": "7e461a8c70ca22631bbdca2b7a650dd6c6fd9b79958bab29e85c41073f4ac5c9",
   "changed": true,
   "example_ids": [
    "reclassify-new-columns"
   ]
  },
  {
   "section_id": "personal-data-in-production",
   "chapter_id": "finding-personal-data",
   "title": "What goes wrong in production",
   "order": 32,
   "level": 2,
   "parent_id": null,
   "sha256": "144c6037c2464397b8660511ec7aff3995f62e2689da1e79db7dae758d708dd7",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "personal-data-decisions",
   "chapter_id": "finding-personal-data",
   "title": "What this chapter decided",
   "order": 33,
   "level": 2,
   "parent_id": null,
   "sha256": "5cab546f69202c5408787aa1652efb75109428e88cac0eeed28f6829278034fa",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "send-run-events",
   "chapter_id": "lineage-from-pipelines",
   "title": "Send a run event from every pipeline",
   "order": 34,
   "level": 2,
   "parent_id": null,
   "sha256": "e28cba214c52c082d06004b733215adc09b2cde185eecb4ff8c3de2e18ca13e9",
   "changed": true,
   "example_ids": [
    "pipeline-run-events"
   ]
  },
  {
   "section_id": "trace-output-columns",
   "chapter_id": "lineage-from-pipelines",
   "title": "Trace each output column to its sources",
   "order": 35,
   "level": 2,
   "parent_id": null,
   "sha256": "b03f17c735f008fa13d8661bdb1918b7d74ae80500154e05bda84c1cb00959bf",
   "changed": true,
   "example_ids": [
    "sqlglot-misses-row-inputs"
   ]
  },
  {
   "section_id": "add-indirect-inputs",
   "chapter_id": "lineage-from-pipelines",
   "title": "Add the inputs that decide which rows exist",
   "order": 36,
   "level": 2,
   "parent_id": null,
   "sha256": "67e4e9898d84ff46476e32ff5bd1036060f012cca89ae3f52b32f80c17132666",
   "changed": true,
   "example_ids": [
    "indirect-column-lineage"
   ]
  },
  {
   "section_id": "fail-on-unreadable-lineage",
   "chapter_id": "lineage-from-pipelines",
   "title": "Fail on statements the parser can't read",
   "order": 37,
   "level": 2,
   "parent_id": null,
   "sha256": "ebd618731abb72ae2884e3f533040a84befbbc7787c90f577e1c636a684f05e1",
   "changed": true,
   "example_ids": [
    "insert-and-merge-lineage",
    "misspelt-column-lineage"
   ]
  },
  {
   "section_id": "impact-of-a-column-change",
   "chapter_id": "lineage-from-pipelines",
   "title": "Find what a column change breaks",
   "order": 38,
   "level": 2,
   "parent_id": null,
   "sha256": "cfd74357680cb551f5a82070583105b16f2dd5f06662fe0aa72b6c88e4c940d1",
   "changed": true,
   "example_ids": [
    "column-impact"
   ]
  },
  {
   "section_id": "classifications-from-lineage",
   "chapter_id": "lineage-from-pipelines",
   "title": "Propose classifications from lineage",
   "order": 39,
   "level": 2,
   "parent_id": null,
   "sha256": "371b628f610ff89ee7dc9ab9745a4e2647aea63eec50b86be23807491d14dbb7",
   "changed": true,
   "example_ids": [
    "propagate-classifications",
    "personal-filter-propagates"
   ]
  },
  {
   "section_id": "lineage-in-production",
   "chapter_id": "lineage-from-pipelines",
   "title": "What goes wrong in production",
   "order": 40,
   "level": 2,
   "parent_id": null,
   "sha256": "6a42234770a2d1c5203efd7f30107054fac4e461e998296a7d787c8f265a9365",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "events-that-never-arrive",
   "chapter_id": "lineage-from-pipelines",
   "title": "Events that never arrive",
   "order": 41,
   "level": 3,
   "parent_id": "lineage-in-production",
   "sha256": "390801e261bcbaf79f87a432d71496d65c56fb2dbae2b57baca4f6aed8c9bc48",
   "changed": true,
   "example_ids": [
    "lineage-disabled-silently"
   ]
  },
  {
   "section_id": "job-nobody-instrumented",
   "chapter_id": "lineage-from-pipelines",
   "title": "A job nobody instrumented",
   "order": 42,
   "level": 3,
   "parent_id": "lineage-in-production",
   "sha256": "0b193fba2dffc0df3ef58487e3c830ca11177aa747d4069734e266b4490bdbad",
   "changed": true,
   "example_ids": [
    "uninstrumented-job"
   ]
  },
  {
   "section_id": "personal-data-tagged-internal",
   "chapter_id": "lineage-from-pipelines",
   "title": "Personal data in a table classified internal",
   "order": 43,
   "level": 3,
   "parent_id": "lineage-in-production",
   "sha256": "13385ca85209a1ee2da762b5b19302cb21a1118634f6050dd62276b7237ad93f",
   "changed": true,
   "example_ids": [
    "personal-copy-tagged-internal"
   ]
  },
  {
   "section_id": "lineage-decisions",
   "chapter_id": "lineage-from-pipelines",
   "title": "What this chapter decided",
   "order": 44,
   "level": 2,
   "parent_id": null,
   "sha256": "3c75d105c88df4c2878d32a32e082356c7c386c7352455235487c177086ae4ee",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "shape-the-request-like-trinos",
   "chapter_id": "access-policies-as-code",
   "title": "Shape the request like Trino's",
   "order": 45,
   "level": 2,
   "parent_id": null,
   "sha256": "94de2d01155785bce9335b595cf852f10812905fe16087cc69c97b64064d8a40",
   "changed": true,
   "example_ids": [
    "trino-shaped-request"
   ]
  },
  {
   "section_id": "generate-the-data-the-policy-reads",
   "chapter_id": "access-policies-as-code",
   "title": "Generate the data the policy reads",
   "order": 46,
   "level": 2,
   "parent_id": null,
   "sha256": "1e3f11a5b74bed4524b8360adf344f51bafccb1f2c4672c1723ca119c9508bb4",
   "changed": true,
   "example_ids": [
    "generated-policy-data"
   ]
  },
  {
   "section_id": "deny-by-default-then-allow-by-role",
   "chapter_id": "access-policies-as-code",
   "title": "Deny by default, then allow by role",
   "order": 47,
   "level": 2,
   "parent_id": null,
   "sha256": "99521b2e594eb9a9caf0f0ad2814a393aefe1ea89c2535718078dabab4a0059a",
   "changed": true,
   "example_ids": [
    "allow-by-role"
   ]
  },
  {
   "section_id": "narrow-by-attribute",
   "chapter_id": "access-policies-as-code",
   "title": "Narrow by attribute: region, consent and purpose",
   "order": 48,
   "level": 2,
   "parent_id": null,
   "sha256": "9ade8f4c42c5101d507584492631706e5d7b5a02d857e1e7cb8352f6cc6a3517",
   "changed": true,
   "example_ids": [
    "attributes-as-row-filters"
   ]
  },
  {
   "section_id": "return-the-decision-as-one-document",
   "chapter_id": "access-policies-as-code",
   "title": "Return the decision as one document",
   "order": 49,
   "level": 2,
   "parent_id": null,
   "sha256": "3be0bc692b482920f0af2d649481404bddda83b7b710c7e3e58576423451c2e5",
   "changed": true,
   "example_ids": [
    "one-decision-document"
   ]
  },
  {
   "section_id": "unit-test-the-policy-in-rego",
   "chapter_id": "access-policies-as-code",
   "title": "Unit-test the policy in Rego",
   "order": 50,
   "level": 2,
   "parent_id": null,
   "sha256": "a9f6053ae3b410df582a39676ae2e1971c35b71d5fef42537a4525b919e7a3d3",
   "changed": true,
   "example_ids": [
    "policy-unit-tests"
   ]
  },
  {
   "section_id": "check-who-sees-what",
   "chapter_id": "access-policies-as-code",
   "title": "Check who sees what from a decision table",
   "order": 51,
   "level": 2,
   "parent_id": null,
   "sha256": "d7eb87d326e8efc187b000ad11ef7aa6ffdc24be42293755aa5c039acb0020e7",
   "changed": true,
   "example_ids": [
    "who-sees-what"
   ]
  },
  {
   "section_id": "where-regopy-differs-from-opa",
   "chapter_id": "access-policies-as-code",
   "title": "Know where regopy differs from OPA",
   "order": 52,
   "level": 2,
   "parent_id": null,
   "sha256": "265e890cf2ed7681b924e9cdc8085179984bdc1a86d989db7d707072db10ade3",
   "changed": true,
   "example_ids": [
    "regopy-silent-differences",
    "regopy-failed-outputs",
    "regopy-sprintf-quotes"
   ]
  },
  {
   "section_id": "the-same-rules-in-cedar",
   "chapter_id": "access-policies-as-code",
   "title": "Write the same rules in Cedar",
   "order": 53,
   "level": 2,
   "parent_id": null,
   "sha256": "1732bea2de804759ee405a3adb537f99ec92213ec98c1253b819f5d5ff204859",
   "changed": true,
   "example_ids": [
    "cedar-same-rules"
   ]
  },
  {
   "section_id": "policies-in-production",
   "chapter_id": "access-policies-as-code",
   "title": "What goes wrong in production",
   "order": 54,
   "level": 2,
   "parent_id": null,
   "sha256": "358187e766634d6725122f00c242abc3de5f3890646be8352c37e81e3625d4fd",
   "changed": true,
   "example_ids": [
    "missing-region-guard",
    "cedar-missing-region"
   ]
  },
  {
   "section_id": "policies-decisions",
   "chapter_id": "access-policies-as-code",
   "title": "What this chapter decided",
   "order": 55,
   "level": 2,
   "parent_id": null,
   "sha256": "14a1fbc611a31b43ef43638e41e9e6cbabf4fbb7547d70809ad00c55a1130c10",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "find-what-a-query-reads",
   "chapter_id": "enforcing-policies-on-queries",
   "title": "Find every table and column a query reads",
   "order": 56,
   "level": 2,
   "parent_id": null,
   "sha256": "80b6e2b7fb83063d58575e3c40a2876242a51516fdd44df1ad2e8f722c622e80",
   "changed": true,
   "example_ids": [
    "tables-a-query-reads",
    "unknown-tables-denied"
   ]
  },
  {
   "section_id": "allow-only-catalog-sources",
   "chapter_id": "enforcing-policies-on-queries",
   "title": "Allow only catalog tables, CTEs and subqueries",
   "order": 57,
   "level": 2,
   "parent_id": null,
   "sha256": "9aeb1b84196635af160813c70556744f5c084301ae4bb337543e1a48f7468b07",
   "changed": true,
   "example_ids": [
    "catalog-sources-only"
   ]
  },
  {
   "section_id": "column-masks-leak",
   "chapter_id": "enforcing-policies-on-queries",
   "title": "Masking column references leaks",
   "order": 58,
   "level": 2,
   "parent_id": null,
   "sha256": "a99b226914e805e42fd9c127498ec363883e2dfa9f11c74f6db67063699fe894",
   "changed": true,
   "example_ids": [
    "select-list-masks-leak"
   ]
  },
  {
   "section_id": "replace-each-table",
   "chapter_id": "enforcing-policies-on-queries",
   "title": "Replace each table with a filtered, masked subquery",
   "order": 59,
   "level": 2,
   "parent_id": null,
   "sha256": "7332e996f1da03385300b451362d61d9757c084b93c68df7bb749c0eec363553",
   "changed": true,
   "example_ids": [
    "table-rewrite",
    "table-rewrite-holds"
   ]
  },
  {
   "section_id": "write-masks-as-sql",
   "chapter_id": "enforcing-policies-on-queries",
   "title": "Write each mask as SQL in one place",
   "order": 60,
   "level": 2,
   "parent_id": null,
   "sha256": "392a96393a2fd9d172128e4d95f8b7b2d8a1ca8e091c5cb156489e8e8030e928",
   "changed": true,
   "example_ids": [
    "masks-as-sql",
    "pseudonym-key",
    "redact-contacts-recall"
   ]
  },
  {
   "section_id": "build-row-filters-from-data",
   "chapter_id": "enforcing-policies-on-queries",
   "title": "Build row filters from the decision's data",
   "order": 61,
   "level": 2,
   "parent_id": null,
   "sha256": "83e6d61efb851c4bf05d9d7d7b200daa0acb047f7fb470bccb348f2d0fb45883",
   "changed": true,
   "example_ids": [
    "row-filters-from-data"
   ]
  },
  {
   "section_id": "gate-columns-on-row-filters",
   "chapter_id": "enforcing-policies-on-queries",
   "title": "Gate every column on the row filters",
   "order": 62,
   "level": 2,
   "parent_id": null,
   "sha256": "002a3e21dc3ac9df50654748228dfcd991b97be41ebfa2832af97ff5398e02b5",
   "changed": true,
   "example_ids": [
    "row-filter-order"
   ]
  },
  {
   "section_id": "test-who-sees-what",
   "chapter_id": "enforcing-policies-on-queries",
   "title": "Test who sees what by running queries",
   "order": 63,
   "level": 2,
   "parent_id": null,
   "sha256": "9dc57fcb484b557a367b3e988ba665e8c68c2b60e44564f1cf089b8fc5ca8996",
   "changed": true,
   "example_ids": [
    "who-sees-what-in-queries",
    "group-change-caught"
   ]
  },
  {
   "section_id": "hold-back-small-groups",
   "chapter_id": "enforcing-policies-on-queries",
   "title": "Hold back small groups in reports",
   "order": 64,
   "level": 2,
   "parent_id": null,
   "sha256": "e0b4b5f0775d7cc8e2d2995bf3faac18904f4729f90902cfbb8139cccbacda44",
   "changed": true,
   "example_ids": [
    "small-groups-difference"
   ]
  },
  {
   "section_id": "engine-enforcement",
   "chapter_id": "enforcing-policies-on-queries",
   "title": "Hand the same policies to an engine that enforces them",
   "order": 65,
   "level": 2,
   "parent_id": null,
   "sha256": "3f1abe38696001a08d4f047d6a5624180679aa293e7f866fc4a84c50908986a5",
   "changed": true,
   "example_ids": [
    "trino-requests"
   ]
  },
  {
   "section_id": "query-on-someones-behalf",
   "chapter_id": "enforcing-policies-on-queries",
   "title": "Query on someone's behalf",
   "order": 66,
   "level": 2,
   "parent_id": null,
   "sha256": "9850130a7dcee0bf5f168de1ae8d40d2295806feb8e697f54848e9285593d277",
   "changed": true,
   "example_ids": [
    "assistant-on-behalf"
   ]
  },
  {
   "section_id": "enforcement-in-production",
   "chapter_id": "enforcing-policies-on-queries",
   "title": "What goes wrong in production",
   "order": 67,
   "level": 2,
   "parent_id": null,
   "sha256": "456334146a4929e065f763a58ed3b3d688acccdacd2146a4aa204efc462fda5b",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "enforcement-decisions",
   "chapter_id": "enforcing-policies-on-queries",
   "title": "What this chapter decided",
   "order": 68,
   "level": 2,
   "parent_id": null,
   "sha256": "672befc21e76ef2b8b9ba8ad44c393d184f43f3c7cdc1f299c5799e48dffd654",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "retention-rules-in-a-file",
   "chapter_id": "retention-consent-erasure",
   "title": "Keep retention rules in a reviewed file",
   "order": 69,
   "level": 2,
   "parent_id": null,
   "sha256": "2ee5a27b043637f1be02c8c7427c8551ecb86811d4ab22aba756f3132716f565",
   "changed": true,
   "example_ids": [
    "retention-rules-due"
   ]
  },
  {
   "section_id": "delete-expired-rows",
   "chapter_id": "retention-consent-erasure",
   "title": "Delete expired rows with row deletes",
   "order": 70,
   "level": 2,
   "parent_id": null,
   "sha256": "bfad4ed09fa070c8bd58ec2dff56c3ab803312c9ae88ba255491e89e0a0f485a",
   "changed": true,
   "example_ids": [
    "apply-retention"
   ]
  },
  {
   "section_id": "consent-at-query-time",
   "chapter_id": "retention-consent-erasure",
   "title": "Read consent where the query runs",
   "order": 71,
   "level": 2,
   "parent_id": null,
   "sha256": "37b6cbb9a5a2558d2b8a858f494a6ea04fd8b0620e18bf4826ef9ec853a527c8",
   "changed": true,
   "example_ids": [
    "consent-withdrawal"
   ]
  },
  {
   "section_id": "plan-erasure-from-lineage",
   "chapter_id": "retention-consent-erasure",
   "title": "Plan an erasure from lineage",
   "order": 72,
   "level": 2,
   "parent_id": null,
   "sha256": "86537598bc67993906168ef602c64d85b8d8d37ae6d14c83266ee5951c08a4a8",
   "changed": true,
   "example_ids": [
    "erasure-plan"
   ]
  },
  {
   "section_id": "erase-the-rows",
   "chapter_id": "retention-consent-erasure",
   "title": "Erase the rows the plan lists",
   "order": 73,
   "level": 2,
   "parent_id": null,
   "sha256": "4aa494ca182b55c141b5e5537a2a0f9c17950f341eb12079b20cfb183abd1847",
   "changed": true,
   "example_ids": [
    "erase-learner"
   ]
  },
  {
   "section_id": "expire-snapshots",
   "chapter_id": "retention-consent-erasure",
   "title": "Expire snapshots by the table's own settings",
   "order": 74,
   "level": 2,
   "parent_id": null,
   "sha256": "0120629d20bc0ca6310bc8033fd57eba03cefe088a4acd30bd81b3ec088ed8ff",
   "changed": true,
   "example_ids": [
    "expiry-ignores-table-settings",
    "erasure-refuses-to-start"
   ]
  },
  {
   "section_id": "remove-unreferenced-files",
   "chapter_id": "retention-consent-erasure",
   "title": "Remove the files no snapshot references",
   "order": 75,
   "level": 2,
   "parent_id": null,
   "sha256": "0f64620228b3dca816d0e36735d9ba334bb434f39eeabe4f176b2ba6701078bf",
   "changed": true,
   "example_ids": [
    "sweep-unreferenced-files"
   ]
  },
  {
   "section_id": "keep-values-out-of-manifests",
   "chapter_id": "retention-consent-erasure",
   "title": "Keep personal values out of manifests",
   "order": 76,
   "level": 2,
   "parent_id": null,
   "sha256": "22a10052c4ad4a46c6191cf3a9981733d0b3638d1d05139cf4f2b0ed5989baa5",
   "changed": true,
   "example_ids": [
    "statistics-off-for-personal-columns"
   ]
  },
  {
   "section_id": "verify-the-erasure",
   "chapter_id": "retention-consent-erasure",
   "title": "Prove the erasure by reading every file",
   "order": 77,
   "level": 2,
   "parent_id": null,
   "sha256": "85f56e0acd86ef13fda30425d21357ff977adbb3122f616281cae4c5edab3288",
   "changed": true,
   "example_ids": [
    "verify-erasure"
   ]
  },
  {
   "section_id": "retention-in-production",
   "chapter_id": "retention-consent-erasure",
   "title": "What goes wrong in production",
   "order": 78,
   "level": 2,
   "parent_id": null,
   "sha256": "bbf2efd6201fd0ff0c9d566507b60b2d99de9386bcc17fbac353ee971cd05974",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "erased-learner-comes-back",
   "chapter_id": "retention-consent-erasure",
   "title": "An erased learner comes back",
   "order": 79,
   "level": 3,
   "parent_id": "retention-in-production",
   "sha256": "50ee84cbd3721054600e6302130cd455c23dfb012c4758da6a317ca331de1b80",
   "changed": true,
   "example_ids": [
    "erased-learner-returns"
   ]
  },
  {
   "section_id": "other-retention-failures",
   "chapter_id": "retention-consent-erasure",
   "title": "Other failures",
   "order": 80,
   "level": 3,
   "parent_id": "retention-in-production",
   "sha256": "ea2a001f0d1b7e0c118ac4a7b47d60571aa046944670d971b3993bf21b8e8c33",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "retention-decisions",
   "chapter_id": "retention-consent-erasure",
   "title": "What this chapter decided",
   "order": 81,
   "level": 2,
   "parent_id": null,
   "sha256": "b4e90d5817b3a379778d8fd8dbcc1cf745dda7f55acadd57b531b512a647991a",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "record-every-decision",
   "chapter_id": "audit-and-evidence",
   "title": "Record every decision where it's made",
   "order": 82,
   "level": 2,
   "parent_id": null,
   "sha256": "6b109c1e079b693cdc601f056680bef192c991c5491f66f953ae652b22567fb6",
   "changed": true,
   "example_ids": [
    "decision-record"
   ]
  },
  {
   "section_id": "keep-values-out-of-the-record",
   "chapter_id": "audit-and-evidence",
   "title": "Keep values out of the record",
   "order": 83,
   "level": 2,
   "parent_id": null,
   "sha256": "c5375ffdec810d51c49c67b6983805b46616d7181db158ae637d1379d046f15a",
   "changed": true,
   "example_ids": [
    "query-without-literals",
    "query-shape-hard-cases"
   ]
  },
  {
   "section_id": "replay-old-decisions",
   "chapter_id": "audit-and-evidence",
   "title": "Replay an old decision under its own policy",
   "order": 84,
   "level": 2,
   "parent_id": null,
   "sha256": "6073305f67c382ef7b29d03104db5eb3bd3a737231f6d6e9a7a5b04622030b9d",
   "changed": true,
   "example_ids": [
    "explain-old-decision"
   ]
  },
  {
   "section_id": "chain-the-records",
   "chapter_id": "audit-and-evidence",
   "title": "Chain the records so an edit shows",
   "order": 85,
   "level": 2,
   "parent_id": null,
   "sha256": "31948c092c36479281a8c7212aade94c7b3412df589e61a840339de8ce82a01e",
   "changed": true,
   "example_ids": [
    "chain-catches-edit"
   ]
  },
  {
   "section_id": "cross-check-the-query-log",
   "chapter_id": "audit-and-evidence",
   "title": "Cross-check the log against DuckDB's query log",
   "order": 86,
   "level": 2,
   "parent_id": null,
   "sha256": "e9fe5fc1d518ba3171601ce3cc2a6248e78fef4db07b29b3bf0a1f49854faf07",
   "changed": true,
   "example_ids": [
    "query-log-cross-check"
   ]
  },
  {
   "section_id": "generate-the-access-review",
   "chapter_id": "audit-and-evidence",
   "title": "Generate the access review from the log",
   "order": 87,
   "level": 2,
   "parent_id": null,
   "sha256": "5fe6bf05354dd6583b3068e4a4ec907f065c912b78429d0e4946831cf8457866",
   "changed": true,
   "example_ids": [
    "access-review"
   ]
  },
  {
   "section_id": "produce-evidence-as-data",
   "chapter_id": "audit-and-evidence",
   "title": "Produce evidence as data",
   "order": 88,
   "level": 2,
   "parent_id": null,
   "sha256": "676637bebf8b960cd3f86a5fa7b324fac0675023683faf5fbd7cd5b0dff2dbe1",
   "changed": true,
   "example_ids": [
    "evidence-report"
   ]
  },
  {
   "section_id": "audit-in-production",
   "chapter_id": "audit-and-evidence",
   "title": "What goes wrong in production",
   "order": 89,
   "level": 2,
   "parent_id": null,
   "sha256": "c529740ce74f276467bbc72d12d4f25d8813224e3035f46540a5afcd48ac6ef7",
   "changed": true,
   "example_ids": [
    "query-log-switched-off"
   ]
  },
  {
   "section_id": "audit-decisions",
   "chapter_id": "audit-and-evidence",
   "title": "What this chapter decided",
   "order": 90,
   "level": 2,
   "parent_id": null,
   "sha256": "a1d1908549efc778ea0f8a5aafdb8906edb2e2e5b110d3333f22278c33b9fb56",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "admit-consented-reviews",
   "chapter_id": "governing-data-for-ai",
   "title": "Admit only reviews whose authors consented",
   "order": 91,
   "level": 2,
   "parent_id": null,
   "sha256": "ab4a8b4acc1f470425103f9b1667f4874876b8e66d2d93b5fbc16485ec47e126",
   "changed": true,
   "example_ids": [
    "corpus-consent-filter"
   ]
  },
  {
   "section_id": "replace-personal-data",
   "chapter_id": "governing-data-for-ai",
   "title": "Replace personal data in the text, then measure what's left",
   "order": 92,
   "level": 2,
   "parent_id": null,
   "sha256": "aa97940628bea9b85469df70e536ceeb572d8ed6de8f70bae9477bfdd3105d77",
   "changed": true,
   "example_ids": [
    "corpus-personal-data-left",
    "privacy-filter-on-the-corpus"
   ]
  },
  {
   "section_id": "consistent-pseudonyms",
   "chapter_id": "governing-data-for-ai",
   "title": "Keep pseudonyms consistent with a keyed hash",
   "order": 93,
   "level": 2,
   "parent_id": null,
   "sha256": "04febd909481bbd8c2712cd0dae5f510e7957fd5a4c3de6719f4dc4b72c3689e",
   "changed": true,
   "example_ids": [
    "keyed-pseudonyms"
   ]
  },
  {
   "section_id": "near-duplicates-with-minhash",
   "chapter_id": "governing-data-for-ai",
   "title": "Find near-duplicates with MinHash",
   "order": 94,
   "level": 2,
   "parent_id": null,
   "sha256": "deca40b7477ed52ff7d3108b6462af29845213967f86d330255be8c1471647cf",
   "changed": true,
   "example_ids": [
    "corpus-duplicates",
    "names-and-near-duplicates"
   ]
  },
  {
   "section_id": "tune-lsh-then-confirm",
   "chapter_id": "governing-data-for-ai",
   "title": "Tune LSH for recall, then confirm every pair",
   "order": 95,
   "level": 2,
   "parent_id": null,
   "sha256": "b854f1eec27208733e663bb1ba7af8b6f6c99072ce2314d054e8bc3782936f31",
   "changed": true,
   "example_ids": [
    "lsh-misses-near-duplicates"
   ]
  },
  {
   "section_id": "carry-provenance",
   "chapter_id": "governing-data-for-ai",
   "title": "Carry provenance on every record",
   "order": 96,
   "level": 2,
   "parent_id": null,
   "sha256": "b52efddca1b72c94a8dd5657b1af1f875094777701a005011717094358b99717",
   "changed": true,
   "example_ids": [
    "corpus-provenance"
   ]
  },
  {
   "section_id": "generate-the-dataset-card",
   "chapter_id": "governing-data-for-ai",
   "title": "Generate the dataset card from the run",
   "order": 97,
   "level": 2,
   "parent_id": null,
   "sha256": "5b3a256a0cc68a3ba36c98785935f40d21ce5f41ac3ac76aafc83544b0e853e3",
   "changed": true,
   "example_ids": [
    "corpus-dataset-card"
   ]
  },
  {
   "section_id": "what-the-ai-act-says",
   "chapter_id": "governing-data-for-ai",
   "title": "Quote what the EU AI Act says about training data",
   "order": 98,
   "level": 2,
   "parent_id": null,
   "sha256": "705d1f5e06c3dad6b9459c39a28f2e4a4660084a5eba60a708b9501379d9b243",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "ai-data-in-production",
   "chapter_id": "governing-data-for-ai",
   "title": "What goes wrong in production",
   "order": 99,
   "level": 2,
   "parent_id": null,
   "sha256": "1a16f2faccedfa4da8e45b6ed59209b11ec40dc09aae674f2d57b5a634813385",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "withdrawn-after-the-build",
   "chapter_id": "governing-data-for-ai",
   "title": "A learner withdraws after the build",
   "order": 100,
   "level": 3,
   "parent_id": "ai-data-in-production",
   "sha256": "da7d97a119bd7ffd098f3d07b00d5423f2446a32c814e66af852d9ad87658359",
   "changed": true,
   "example_ids": [
    "consent-withdrawn-after-build"
   ]
  },
  {
   "section_id": "other-ai-data-failures",
   "chapter_id": "governing-data-for-ai",
   "title": "Other failures",
   "order": 101,
   "level": 3,
   "parent_id": "ai-data-in-production",
   "sha256": "f292699ebfa08977cb25cc47ed392f153176576bd8aad72e71a3a51e819b273d",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "ai-data-decisions",
   "chapter_id": "governing-data-for-ai",
   "title": "What this chapter decided",
   "order": 102,
   "level": 2,
   "parent_id": null,
   "sha256": "f5d03a8157dde839d985b39c128b3fa00d89be028b4789729661f53ffcf89b89",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "run-every-rule-as-one-job",
   "chapter_id": "governance-in-ci",
   "title": "Run every check as one job",
   "order": 103,
   "level": 2,
   "parent_id": null,
   "sha256": "a10a97df598b4ec2b2a8f5fed34ff3310647d16a797deff272542e5e4abf9740",
   "changed": true,
   "example_ids": [
    "governance-ci-report"
   ]
  },
  {
   "section_id": "gate-the-pull-request",
   "chapter_id": "governance-in-ci",
   "title": "Gate the pull request, not the commit",
   "order": 104,
   "level": 2,
   "parent_id": null,
   "sha256": "01be07a71df8374163e27f4c5c864c0e6d45ec58bdc9fcfc327351ce4f6922a3",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "report-what-a-schema-change-reaches",
   "chapter_id": "governance-in-ci",
   "title": "Report what a schema change reaches",
   "order": 105,
   "level": 2,
   "parent_id": null,
   "sha256": "4f4867c068bad75148b41b7c7e5333e9e5a6d7620a2a18a550655a39e37ce351",
   "changed": true,
   "example_ids": [
    "schema-change-impact"
   ]
  },
  {
   "section_id": "ask-the-owner-before-lowering",
   "chapter_id": "governance-in-ci",
   "title": "Ask the owner before lowering a classification",
   "order": 106,
   "level": 2,
   "parent_id": null,
   "sha256": "0eb857310e656566f97ebfbc02c1fd3884f1ee4a997d9a62bef0e4b4c911db49",
   "changed": true,
   "example_ids": [
    "classification-downgrade"
   ]
  },
  {
   "section_id": "deprecate-before-removing",
   "chapter_id": "governance-in-ci",
   "title": "Deprecate a column before removing it",
   "order": 107,
   "level": 2,
   "parent_id": null,
   "sha256": "abebf257ca74a564d39c730b0a3ce27e2e17ff15adad3552e40840ca08238044",
   "changed": true,
   "example_ids": [
    "deprecate-then-remove"
   ]
  },
  {
   "section_id": "a-folder-and-a-code-owner-per-domain",
   "chapter_id": "governance-in-ci",
   "title": "Route each domain's reviews by path",
   "order": 108,
   "level": 2,
   "parent_id": null,
   "sha256": "80993825bee314118cac6a4283c04cffdb5e431a53cbd333e6678d23cf57c2b3",
   "changed": true,
   "example_ids": [
    "domain-contracts"
   ]
  },
  {
   "section_id": "run-global-and-domain-rules",
   "chapter_id": "governance-in-ci",
   "title": "Layer domain rules on the global rules",
   "order": 109,
   "level": 2,
   "parent_id": null,
   "sha256": "4cbfee3acdda670bc7747c5140a812f0b9376364e50eb4bf4f16c87bed4bd7f1",
   "changed": true,
   "example_ids": [
    "global-and-domain-rules"
   ]
  },
  {
   "section_id": "count-waived-findings",
   "chapter_id": "governance-in-ci",
   "title": "Count waived findings per check",
   "order": 110,
   "level": 2,
   "parent_id": null,
   "sha256": "2132976523abf5900174cdc23f65fd7a70b325c7035fef44ff8e5917bd2b4ff5",
   "changed": true,
   "example_ids": [
    "waived-findings"
   ]
  },
  {
   "section_id": "ci-in-production",
   "chapter_id": "governance-in-ci",
   "title": "What goes wrong in production",
   "order": 111,
   "level": 2,
   "parent_id": null,
   "sha256": "cb91ee565975f5f4821be44c71e9b62cdbcbbca4fc1e02dd1a0aad09c743fab2",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "a-check-that-reads-every-row",
   "chapter_id": "governance-in-ci",
   "title": "A check that reads every row",
   "order": 112,
   "level": 3,
   "parent_id": "ci-in-production",
   "sha256": "302d08cc63425037bdde88bbcb44af2805a173761158efd6929011f89985d76a",
   "changed": true,
   "example_ids": [
    "slow-check-every-row"
   ]
  },
  {
   "section_id": "a-check-that-flags-every-id",
   "chapter_id": "governance-in-ci",
   "title": "A check that flags every ID",
   "order": 113,
   "level": 3,
   "parent_id": "ci-in-production",
   "sha256": "1a007e9072227c845d69d09ef9f684c73358ae25bf7e6b68c3f922479c9c17b3",
   "changed": true,
   "example_ids": [
    "noisy-check-waivers"
   ]
  },
  {
   "section_id": "a-broken-file-becomes-a-finding",
   "chapter_id": "governance-in-ci",
   "title": "A broken file becomes a finding",
   "order": 114,
   "level": 3,
   "parent_id": "ci-in-production",
   "sha256": "c7033ad112fcef2d8ae3271afd84398a0d4cce82c6e2293f6bc73f56fb13112c",
   "changed": true,
   "example_ids": [
    "broken-files-become-findings"
   ]
  },
  {
   "section_id": "other-ci-failures",
   "chapter_id": "governance-in-ci",
   "title": "Other failures",
   "order": 115,
   "level": 3,
   "parent_id": "ci-in-production",
   "sha256": "6db16c31ad2a2b65f31a08adf010bf8dd7f462452f846e93d316e9ce7db76168",
   "changed": true,
   "example_ids": []
  },
  {
   "section_id": "ci-decisions",
   "chapter_id": "governance-in-ci",
   "title": "What this chapter decided",
   "order": 116,
   "level": 2,
   "parent_id": null,
   "sha256": "fb9a3d84dbaddfffbd9951deb793d88f5fe71a9065e286b8daea1eea776a6845",
   "changed": true,
   "example_ids": []
  }
 ],
 "examples": [
  {
   "example_id": "catalog-the-learners",
   "chapter_id": "governance-end-to-end",
   "section_id": "catalog-a-table",
   "file": "examples/catalog-the-learners.py",
   "sha256": "7f9a1cb422e70cfc62713ea60df6eab54675fb3e59eae8cfae018911c0cec54c",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "audience-pipeline-lineage",
   "chapter_id": "governance-end-to-end",
   "section_id": "capture-one-pipelines-lineage",
   "file": "examples/audience-pipeline-lineage.py",
   "sha256": "03773db25fb1fd2fddea524b687dd4fe939ea48832b34d81240e070b4793af81",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "support-region-enforced",
   "chapter_id": "governance-end-to-end",
   "section_id": "enforce-one-access-decision",
   "file": "examples/support-region-enforced.py",
   "sha256": "a9e172fd01c9e4f5de14e241f8f1fadbe5585bc5760766e4c087d264d32926c0",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "unclassified-column-fails",
   "chapter_id": "governance-end-to-end",
   "section_id": "fail-the-pull-request",
   "file": "examples/unclassified-column-fails.py",
   "sha256": "14c5d3cb56e2d8f7a3da53898ec0fee00d63e47c3d4a966ea8e25e4b7f94a568",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "spreadsheet-misses-new-column",
   "chapter_id": "governance-end-to-end",
   "section_id": "a-spreadsheet-nobody-updates",
   "file": "examples/spreadsheet-misses-new-column.py",
   "sha256": "9d3659a42328024e7936e6404f08746ea9f9609a7ca325561ad3bf6dcb62ac6e",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "read-around-the-layer",
   "chapter_id": "governance-end-to-end",
   "section_id": "a-policy-another-tool-bypasses",
   "file": "examples/read-around-the-layer.py",
   "sha256": "19bf871327b1935e5ea8fe5738f6f789e46d0b7dc1277a33bdcac39a9b0bb69e",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "metadata-model",
   "chapter_id": "a-catalog-you-can-test",
   "section_id": "keep-metadata-in-a-reviewed-file",
   "file": "examples/metadata-model.py",
   "sha256": "5b7bfd858a4c5aaa5ef3812d3b7d7ed19c5fad23bc6b3d6b3e56bf9fec59e682",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "rename-orphans-name-keys",
   "chapter_id": "a-catalog-you-can-test",
   "section_id": "key-column-metadata-by-field-id",
   "file": "examples/rename-orphans-name-keys.py",
   "sha256": "36f506175f8dc72e00faec42b5b36ae15385c259f0cf48128de38f70e3402abe",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "apply-metadata",
   "chapter_id": "a-catalog-you-can-test",
   "section_id": "write-descriptions-into-the-schema",
   "file": "examples/apply-metadata.py",
   "sha256": "8cba2f20b8295e73f9d6045311afc9f4fc64e09eaf0016fccad54e50b5cbed1b",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "doc-edit-schema-id",
   "chapter_id": "a-catalog-you-can-test",
   "section_id": "a-description-edit-is-a-schema-change",
   "file": "examples/doc-edit-schema-id.py",
   "sha256": "0eab8e38a581ee9152ea621038a25bccf1dee690e446e2c697e74aba3af88009",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "metadata-gaps",
   "chapter_id": "a-catalog-you-can-test",
   "section_id": "test-the-catalog-against-the-metadata",
   "file": "examples/metadata-gaps.py",
   "sha256": "c727c7ba59b8afe71472c8771ce178315f31eda5a771dce9be1c3b85f18eac22",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "schema-changes-checked",
   "chapter_id": "a-catalog-you-can-test",
   "section_id": "catch-schema-changes",
   "file": "examples/schema-changes-checked.py",
   "sha256": "8f08cfba27cb7cc5a053abaa8792cc09fe0247c1227238983a52871acbcb4a7b",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "pseudonymous-learner-id",
   "chapter_id": "a-catalog-you-can-test",
   "section_id": "classify-pseudonymous-ids",
   "file": "examples/pseudonymous-learner-id.py",
   "sha256": "4f4474836146f300356b53937a5730aab7e3674e2453d7c0bad5813c027416d9",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "suggestion-agreement",
   "chapter_id": "a-catalog-you-can-test",
   "section_id": "draft-descriptions-with-a-local-model",
   "file": "examples/suggestion-agreement.py",
   "sha256": "133909603e1bb8eeeb3e211aaf82879195e085674da45d7468a4d2f50a3a7109",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "suggestions-with-platform-examples",
   "chapter_id": "a-catalog-you-can-test",
   "section_id": "prompt-examples-give-answers-away",
   "file": "examples/suggestions-with-platform-examples.py",
   "sha256": "1f6469b231497698d4f204a6accab5be96e36df33db379d9dd3ffc723fa89780",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "suggestion-mistakes",
   "chapter_id": "a-catalog-you-can-test",
   "section_id": "measure-where-the-drafts-are-wrong",
   "file": "examples/suggestion-mistakes.py",
   "sha256": "88d4084325fb3a1ae59c619125b1f980cdc0a07590626d2a564f97def81e5b1d",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "suggestion-descriptions",
   "chapter_id": "a-catalog-you-can-test",
   "section_id": "measure-where-the-drafts-are-wrong",
   "file": "examples/suggestion-descriptions.py",
   "sha256": "898a0f0beff5b5401bae05bfe644fb66a381f2d2e2920663701936384c246376",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "column-name-rules",
   "chapter_id": "finding-personal-data",
   "section_id": "classify-columns-from-the-schema",
   "file": "examples/column-name-rules.py",
   "sha256": "cd3b5fa724cffcbcfbb3e3ced73aa449f49d74525eec1df6eb45d83cc36f6cc2",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "httpx": "0.28.1",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "presidio-offline-engine",
   "chapter_id": "finding-personal-data",
   "section_id": "run-presidio-offline",
   "file": "examples/presidio-offline-engine.py",
   "sha256": "39aa1bca439923ffd86cbc6387c405c1371185b7a7ec1d64870db3a0ad68dcfe",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "httpx": "0.28.1",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "spacy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "seeded-column-sample",
   "chapter_id": "finding-personal-data",
   "section_id": "sample-column-values",
   "file": "examples/seeded-column-sample.py",
   "sha256": "7791eb065812d44f506da13cc6e3b8f4261156e6cf9d18647a2ed710be1690ae",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "httpx": "0.28.1",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "classify-sampled-columns",
   "chapter_id": "finding-personal-data",
   "section_id": "classify-columns-from-their-values",
   "file": "examples/classify-sampled-columns.py",
   "sha256": "8aa4e43a0ed4040ed7626d1dd83c9eec5751543c113729ae4704f8cfbb7239ab",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "httpx": "0.28.1",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "measure-pattern-recognizers",
   "chapter_id": "finding-personal-data",
   "section_id": "measure-against-labelled-spans",
   "file": "examples/measure-pattern-recognizers.py",
   "sha256": "93d20472db6e415d33835e9a3bfba428d8ba8f9c77850f4597f8a85a09bc5d13",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "httpx": "0.28.1",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "tune-pattern-recognizers",
   "chapter_id": "finding-personal-data",
   "section_id": "tune-the-recognizers",
   "file": "examples/tune-pattern-recognizers.py",
   "sha256": "d2dd4e10f908ca29a665070b927ec45cd812572a79c24cf2c0e767a013e830b2",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "httpx": "0.28.1",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "pattern-hard-cases",
   "chapter_id": "finding-personal-data",
   "section_id": "where-patterns-fail",
   "file": "examples/pattern-hard-cases.py",
   "sha256": "c1b93b1aab4322b079abef8e7f2ded6c381e96a339073f4be5c7d4a06fd4699c",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "httpx": "0.28.1",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "privacy-filter-spans",
   "chapter_id": "finding-personal-data",
   "section_id": "compare-a-named-entity-model",
   "file": "examples/privacy-filter-spans.py",
   "sha256": "356ca60605c740bfe8ab5d3a728f9988b07de7e9943faece3441b3464f21f3f7",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "httpx": "0.28.1",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "privacy-filter-hard-cases",
   "chapter_id": "finding-personal-data",
   "section_id": "read-the-models-misses",
   "file": "examples/privacy-filter-hard-cases.py",
   "sha256": "345b6563a26d7b3414ce016b74e447a0a19bbbb38af323e64a6967e97f1d7b58",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "httpx": "0.28.1",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "privacy-filter-labels",
   "chapter_id": "finding-personal-data",
   "section_id": "what-a-wrong-label-costs",
   "file": "examples/privacy-filter-labels.py",
   "sha256": "6ba60d51324a0f9b2b3f4d823f8698f4433684625752d95de653aed840c7d545",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "httpx": "0.28.1",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "reclassify-new-columns",
   "chapter_id": "finding-personal-data",
   "section_id": "reclassify-on-schema-change",
   "file": "examples/reclassify-new-columns.py",
   "sha256": "d3c726637bd4664a9f6af42ac1139c55f2cf9df29e2cd406806f6902911e1034",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "httpx": "0.28.1",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "pipeline-run-events",
   "chapter_id": "lineage-from-pipelines",
   "section_id": "send-run-events",
   "file": "examples/pipeline-run-events.py",
   "sha256": "6b09eb78f9529a1c68f581624f372ca05f9d559662c14ed6ae843026c99e5e22",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "sqlglot-misses-row-inputs",
   "chapter_id": "lineage-from-pipelines",
   "section_id": "trace-output-columns",
   "file": "examples/sqlglot-misses-row-inputs.py",
   "sha256": "afa9374b0b9a23b0fca78d5db71a4aad99d57734373e98c220edd0fe541dccd6",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "indirect-column-lineage",
   "chapter_id": "lineage-from-pipelines",
   "section_id": "add-indirect-inputs",
   "file": "examples/indirect-column-lineage.py",
   "sha256": "c944db151c5599bac4432cc549817aad46b07efe0cea173951ad16f2686bd807",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "insert-and-merge-lineage",
   "chapter_id": "lineage-from-pipelines",
   "section_id": "fail-on-unreadable-lineage",
   "file": "examples/insert-and-merge-lineage.py",
   "sha256": "53c11f29b736f5f71fc5777b584312b9c2ff6e79b5315d4bd3e03def7c4b49ab",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "misspelt-column-lineage",
   "chapter_id": "lineage-from-pipelines",
   "section_id": "fail-on-unreadable-lineage",
   "file": "examples/misspelt-column-lineage.py",
   "sha256": "44bd282a61c06ae39e45d17ae929596662df6131714089615ad7586b15eb35c7",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "column-impact",
   "chapter_id": "lineage-from-pipelines",
   "section_id": "impact-of-a-column-change",
   "file": "examples/column-impact.py",
   "sha256": "a2276291f26f7da3c48f7fe50c782f3b78fda5ad535b5524ffdeb07c2fbf2f25",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "propagate-classifications",
   "chapter_id": "lineage-from-pipelines",
   "section_id": "classifications-from-lineage",
   "file": "examples/propagate-classifications.py",
   "sha256": "0e8ca207579d9387a6d5740d61b7df8a68a305bbb9275e6eada25c8519dd3e3e",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "personal-filter-propagates",
   "chapter_id": "lineage-from-pipelines",
   "section_id": "classifications-from-lineage",
   "file": "examples/personal-filter-propagates.py",
   "sha256": "7c4b185ea56eacb7adbfd99194691c7d87f28463b6f1a99aa9ae63fcfe3231e8",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "lineage-disabled-silently",
   "chapter_id": "lineage-from-pipelines",
   "section_id": "events-that-never-arrive",
   "file": "examples/lineage-disabled-silently.py",
   "sha256": "7fe0a105544ccd2f91029f517e9b2f5e38383f343fd4937fe82f361a01229b5a",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "uninstrumented-job",
   "chapter_id": "lineage-from-pipelines",
   "section_id": "job-nobody-instrumented",
   "file": "examples/uninstrumented-job.py",
   "sha256": "531c7661e5308470031490cf5b68e96ebfbcdbb4e3f56d96b7c02c18499c5d62",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "personal-copy-tagged-internal",
   "chapter_id": "lineage-from-pipelines",
   "section_id": "personal-data-tagged-internal",
   "file": "examples/personal-copy-tagged-internal.py",
   "sha256": "f2f34e3d2ca7b06205d5a314656677d9f106fb32da7488a3964b0a422a1475bf",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "trino-shaped-request",
   "chapter_id": "access-policies-as-code",
   "section_id": "shape-the-request-like-trinos",
   "file": "examples/trino-shaped-request.py",
   "sha256": "b77c2ace100a2eb060d0c67703d3794684da5b56dc450a9e098267ef2301d709",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "generated-policy-data",
   "chapter_id": "access-policies-as-code",
   "section_id": "generate-the-data-the-policy-reads",
   "file": "examples/generated-policy-data.py",
   "sha256": "cff36e87cd700e31b959061c5195b6afdd2304d3509ebd83e26d285cc889a1ee",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "allow-by-role",
   "chapter_id": "access-policies-as-code",
   "section_id": "deny-by-default-then-allow-by-role",
   "file": "examples/allow-by-role.py",
   "sha256": "c282f63077b8ade53d3a301c2f346238b5746ae371a6b30648d619804bb1c660",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "attributes-as-row-filters",
   "chapter_id": "access-policies-as-code",
   "section_id": "narrow-by-attribute",
   "file": "examples/attributes-as-row-filters.py",
   "sha256": "d9dfe4be5838b88a24e4df4e7409afb9892ca1feb74ce7162c6809b3ddb67ec6",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "one-decision-document",
   "chapter_id": "access-policies-as-code",
   "section_id": "return-the-decision-as-one-document",
   "file": "examples/one-decision-document.py",
   "sha256": "29b09a8c4550969fd6ec6894aaa525b33fdb2dfbb924ee876b2d49bef2d8a881",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "policy-unit-tests",
   "chapter_id": "access-policies-as-code",
   "section_id": "unit-test-the-policy-in-rego",
   "file": "examples/policy-unit-tests.py",
   "sha256": "b36aeb06160b1af512e7dc576c39c4297d4524e78b548f92cce2cef431878be4",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "who-sees-what",
   "chapter_id": "access-policies-as-code",
   "section_id": "check-who-sees-what",
   "file": "examples/who-sees-what.py",
   "sha256": "b497214758710f54bc3be9e26109c95a666ff023a06348cf82c449f6bf1fa1f6",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "regopy-silent-differences",
   "chapter_id": "access-policies-as-code",
   "section_id": "where-regopy-differs-from-opa",
   "file": "examples/regopy-silent-differences.py",
   "sha256": "c695196cfedf0559acfc6a2af467fd14cec4f919b6fdab18ebc37c3f897378de",
   "versions": {
    "python": "3.12.15",
    "regopy": "1.5.2",
    "setuptools": "84.2.1"
   },
   "direct": [
    "regopy"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "regopy-failed-outputs",
   "chapter_id": "access-policies-as-code",
   "section_id": "where-regopy-differs-from-opa",
   "file": "examples/regopy-failed-outputs.py",
   "sha256": "a70b21cb1e8d7dba5a0034eca52cc20c0ae0ac640de65717fe66ba1c984f81f0",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "regopy-sprintf-quotes",
   "chapter_id": "access-policies-as-code",
   "section_id": "where-regopy-differs-from-opa",
   "file": "examples/regopy-sprintf-quotes.py",
   "sha256": "a4cc72a3396770b0343d0550ededec858775573da3a94b66ca143f48336d4e1c",
   "versions": {
    "python": "3.12.15",
    "regopy": "1.5.2",
    "setuptools": "84.2.1"
   },
   "direct": [
    "regopy"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "cedar-same-rules",
   "chapter_id": "access-policies-as-code",
   "section_id": "the-same-rules-in-cedar",
   "file": "examples/cedar-same-rules.py",
   "sha256": "80350163102325511b9dd2a329b9fb3ace152a41697fedde73792da227af8882",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "cedarpy": "4.12.2",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "cedarpy",
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "missing-region-guard",
   "chapter_id": "access-policies-as-code",
   "section_id": "policies-in-production",
   "file": "examples/missing-region-guard.py",
   "sha256": "92c23047980a414ac809e81eb101de767f875e02b1d29b6d947d2f00c797d9ef",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "cedar-missing-region",
   "chapter_id": "access-policies-as-code",
   "section_id": "policies-in-production",
   "file": "examples/cedar-missing-region.py",
   "sha256": "175f5780f5d5054d8138618b98580d7d590da06d4059cbd343359c9df81580e9",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "cedarpy": "4.12.2",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "cedarpy",
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "tables-a-query-reads",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "find-what-a-query-reads",
   "file": "examples/tables-a-query-reads.py",
   "sha256": "b1291a818b5b909925439e769f4aeb592761daa958d1f56a5b4b32e40eaf599b",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "unknown-tables-denied",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "find-what-a-query-reads",
   "file": "examples/unknown-tables-denied.py",
   "sha256": "3addcdafb229b1a7935862718b84f39bb531abde05f1afe748702bc1eaedccd4",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "catalog-sources-only",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "allow-only-catalog-sources",
   "file": "examples/catalog-sources-only.py",
   "sha256": "440158e0ca5c7be93318c7e7b69cadda67caf2a7ccca7392d91760203f025519",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "select-list-masks-leak",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "column-masks-leak",
   "file": "examples/select-list-masks-leak.py",
   "sha256": "bbb552d2b6d30ebf1e0e3b484d2b30c5256aabbcce86b397501e891bea839ee1",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "table-rewrite",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "replace-each-table",
   "file": "examples/table-rewrite.py",
   "sha256": "42c040150375c6dfa6998877ad860cbc8144294b4d9f1b3301ace3eca1318c33",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "table-rewrite-holds",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "replace-each-table",
   "file": "examples/table-rewrite-holds.py",
   "sha256": "24b116116014ec18a70303fff0f48952c60d354096831848c798816448f854ce",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "masks-as-sql",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "write-masks-as-sql",
   "file": "examples/masks-as-sql.py",
   "sha256": "c68f609deb4eb8d9b4c8555ad0aee1e0c0c5e4559ffe7818ecdcc8a2a96bd6c1",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "pseudonym-key",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "write-masks-as-sql",
   "file": "examples/pseudonym-key.py",
   "sha256": "2dea9829ac424b95dd1f89fd635ff3fdd18855edcbb0ef24fe3152cc17fc5c47",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "redact-contacts-recall",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "write-masks-as-sql",
   "file": "examples/redact-contacts-recall.py",
   "sha256": "d1dbbae36ad8240c0a36f73c8558da5fc816c30c9f8442b1380eeb05cd92fbb4",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "row-filters-from-data",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "build-row-filters-from-data",
   "file": "examples/row-filters-from-data.py",
   "sha256": "70e91ecef6138968b1099ab37225f9c309002d67aee9f2fecf02ca20f64cca17",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "row-filter-order",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "gate-columns-on-row-filters",
   "file": "examples/row-filter-order.py",
   "sha256": "8c326470c2b976c53781ee86cdebee0bc1260e763c98640a26536a72fc2723c9",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "who-sees-what-in-queries",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "test-who-sees-what",
   "file": "examples/who-sees-what-in-queries.py",
   "sha256": "2ffb09d36a3ee042a3e583ab151ef01ba331f77d33a8acef3b4b2d35fd92732c",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "group-change-caught",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "test-who-sees-what",
   "file": "examples/group-change-caught.py",
   "sha256": "127a49566d7b701cdf55cf315ce1df5f447a93f31d8092caf97eabefa73650f6",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "small-groups-difference",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "hold-back-small-groups",
   "file": "examples/small-groups-difference.py",
   "sha256": "dfb85025fb0ebabfee361d4da9697e664e57444039a2e8ddf6c9e25367f92f5e",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "trino-requests",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "engine-enforcement",
   "file": "examples/trino-requests.py",
   "sha256": "9f60d673e17c352a2d2ff274bcf2983aa592fb627b6ed215d27b26994fa6362e",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "assistant-on-behalf",
   "chapter_id": "enforcing-policies-on-queries",
   "section_id": "query-on-someones-behalf",
   "file": "examples/assistant-on-behalf.py",
   "sha256": "d1fd171affb76ba274af0ba082fd138fdf973bf52363f86ca0f39b391cbff18b",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "retention-rules-due",
   "chapter_id": "retention-consent-erasure",
   "section_id": "retention-rules-in-a-file",
   "file": "examples/retention-rules-due.py",
   "sha256": "3a11feaf10bb9f7fc9569407164a13792c4f9c4d0f3f07a78c32ee792c7ea7a8",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "apply-retention",
   "chapter_id": "retention-consent-erasure",
   "section_id": "delete-expired-rows",
   "file": "examples/apply-retention.py",
   "sha256": "c62ff4a9834a2d2a4614ac4715e4b958301d7a57d281a87821bf1e34e96c782a",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "consent-withdrawal",
   "chapter_id": "retention-consent-erasure",
   "section_id": "consent-at-query-time",
   "file": "examples/consent-withdrawal.py",
   "sha256": "e35fde2954f36b85d7e6dab0d9fccfa9f105c5d870b309590f357b1904a8a8df",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "erasure-plan",
   "chapter_id": "retention-consent-erasure",
   "section_id": "plan-erasure-from-lineage",
   "file": "examples/erasure-plan.py",
   "sha256": "d67596bfc0fcba8a38709e6c5e852eca18d90c2ba473fac523a9ff7df6e9f3ba",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "erase-learner",
   "chapter_id": "retention-consent-erasure",
   "section_id": "erase-the-rows",
   "file": "examples/erase-learner.py",
   "sha256": "157ea51230c54b7d0470bcbafecd688e7436087511d2257ef35e7cb74a4e1d0c",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "expiry-ignores-table-settings",
   "chapter_id": "retention-consent-erasure",
   "section_id": "expire-snapshots",
   "file": "examples/expiry-ignores-table-settings.py",
   "sha256": "245d4c92b29419fd96d322371b56b3e7cb139a50a1ff4259c073a6a348592e17",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "erasure-refuses-to-start",
   "chapter_id": "retention-consent-erasure",
   "section_id": "expire-snapshots",
   "file": "examples/erasure-refuses-to-start.py",
   "sha256": "74946c0bd35771a8ef916756cdfaf4f4a9a7acb67af25de914682e9cf51876c2",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "sweep-unreferenced-files",
   "chapter_id": "retention-consent-erasure",
   "section_id": "remove-unreferenced-files",
   "file": "examples/sweep-unreferenced-files.py",
   "sha256": "7aba7a3d92b82c02a75f88c4c73bf613d1882c341ed9b5b3bd9c9a6cc5fad3f4",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "statistics-off-for-personal-columns",
   "chapter_id": "retention-consent-erasure",
   "section_id": "keep-values-out-of-manifests",
   "file": "examples/statistics-off-for-personal-columns.py",
   "sha256": "29b96713b312515ae55a6ad20c8cc4b6ec1fd5371c771d8b639a7d8218f60178",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "verify-erasure",
   "chapter_id": "retention-consent-erasure",
   "section_id": "verify-the-erasure",
   "file": "examples/verify-erasure.py",
   "sha256": "eaf57731689c9799668de57ed84275a66b95865dc884a1bb650f85e1e59ee72c",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "erased-learner-returns",
   "chapter_id": "retention-consent-erasure",
   "section_id": "erased-learner-comes-back",
   "file": "examples/erased-learner-returns.py",
   "sha256": "002576344a6a3c4736cbb9b71510a0fa8ffb2a2a00dbab85fb434f8e19826736",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "decision-record",
   "chapter_id": "audit-and-evidence",
   "section_id": "record-every-decision",
   "file": "examples/decision-record.py",
   "sha256": "21cd7469b95e21bde5add32af4eaf03e1d1eba6a10b1b4caff0f35eadbdf855e",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "query-without-literals",
   "chapter_id": "audit-and-evidence",
   "section_id": "keep-values-out-of-the-record",
   "file": "examples/query-without-literals.py",
   "sha256": "6717f8090fb98e1afb2d0e7681043a7508355e66ded2cc6f4209ead175a193e5",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "query-shape-hard-cases",
   "chapter_id": "audit-and-evidence",
   "section_id": "keep-values-out-of-the-record",
   "file": "examples/query-shape-hard-cases.py",
   "sha256": "3401f6b2f298c56618c67de6c8c559fc8f2b00364cc89186518664c68b0bb251",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "explain-old-decision",
   "chapter_id": "audit-and-evidence",
   "section_id": "replay-old-decisions",
   "file": "examples/explain-old-decision.py",
   "sha256": "ffd95d60fcdbe5f58bc7c6b923c8247cce469bddc52c5ab93e94ad51d22d6f7b",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "chain-catches-edit",
   "chapter_id": "audit-and-evidence",
   "section_id": "chain-the-records",
   "file": "examples/chain-catches-edit.py",
   "sha256": "e89a5b6483bbc95781cd7651033d5c3ac41badad4856fc2894fbbe2536313e94",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "query-log-cross-check",
   "chapter_id": "audit-and-evidence",
   "section_id": "cross-check-the-query-log",
   "file": "examples/query-log-cross-check.py",
   "sha256": "9f2a1f61dceb45c2776180a3d25709a11dce956043505f5688651663b4f998cc",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "access-review",
   "chapter_id": "audit-and-evidence",
   "section_id": "generate-the-access-review",
   "file": "examples/access-review.py",
   "sha256": "ebfe15a82e856352b80788af57e66fad2ea898d184e17bd21403d7d42d13dd10",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "evidence-report",
   "chapter_id": "audit-and-evidence",
   "section_id": "produce-evidence-as-data",
   "file": "examples/evidence-report.py",
   "sha256": "de07c7fafcd6df6f7eeda333a9c524db4275181f1387fae990c7775d635e527f",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "cachetools": "7.2.4",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "duckdb": "2.0.0",
    "fsspec": "2026.9.0",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "query-log-switched-off",
   "chapter_id": "audit-and-evidence",
   "section_id": "audit-in-production",
   "file": "examples/query-log-switched-off.py",
   "sha256": "4f318c331db2b093b8ad5b901aa32f98d4e46845010dbdc800ebe5ef4dd5c71d",
   "versions": {
    "python": "3.12.15",
    "annotated-types": "0.8.0",
    "cachetools": "7.2.4",
    "duckdb": "2.0.0",
    "mmh3": "5.3.1",
    "numpy": "2.4.6",
    "pandas": "3.1.0",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "regopy": "1.5.2",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "six": "1.17.0",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "strictyaml": "1.7.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "corpus-consent-filter",
   "chapter_id": "governing-data-for-ai",
   "section_id": "admit-consented-reviews",
   "file": "examples/corpus-consent-filter.py",
   "sha256": "d704b279316f2d6eed41be35c7923d5c7b5235992c0715d992dea7f2dd2fc64e",
   "versions": {
    "python": "3.12.15",
    "absl-py": "2.5.1",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "cffi": "2.1.1",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cryptography": "48.0.1",
    "cymem": "2.0.13",
    "datasketch": "2.0.0",
    "duckdb": "2.0.0",
    "etils": "1.14.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "jsonpath-rw": "1.4.0",
    "markupsafe": "3.0.4",
    "mlcroissant": "1.1.1",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "networkx": "3.7",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "ply": "3.11",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "presidio-anonymizer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "rdflib": "7.6.0",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "scipy": "1.18.1",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "corpus-personal-data-left",
   "chapter_id": "governing-data-for-ai",
   "section_id": "replace-personal-data",
   "file": "examples/corpus-personal-data-left.py",
   "sha256": "281367c34f80e38b9eb3c7b8eb27fcc02a43cc3d10403d7e6d7dddc584da39f0",
   "versions": {
    "python": "3.12.15",
    "absl-py": "2.5.1",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "cffi": "2.1.1",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cryptography": "48.0.1",
    "cymem": "2.0.13",
    "datasketch": "2.0.0",
    "duckdb": "2.0.0",
    "etils": "1.14.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "jsonpath-rw": "1.4.0",
    "markupsafe": "3.0.4",
    "mlcroissant": "1.1.1",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "networkx": "3.7",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "ply": "3.11",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "presidio-anonymizer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "rdflib": "7.6.0",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "scipy": "1.18.1",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "privacy-filter-on-the-corpus",
   "chapter_id": "governing-data-for-ai",
   "section_id": "replace-personal-data",
   "file": "examples/privacy-filter-on-the-corpus.py",
   "sha256": "f8b9bf31f0bb18b279c8dd8db84b8fd0a9b7fea117ee8f085b5acff18bc208e4",
   "versions": {
    "python": "3.12.15",
    "absl-py": "2.5.1",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "cffi": "2.1.1",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cryptography": "48.0.1",
    "cymem": "2.0.13",
    "datasketch": "2.0.0",
    "duckdb": "2.0.0",
    "etils": "1.14.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "jsonpath-rw": "1.4.0",
    "markupsafe": "3.0.4",
    "mlcroissant": "1.1.1",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "networkx": "3.7",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "ply": "3.11",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "presidio-anonymizer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "rdflib": "7.6.0",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "scipy": "1.18.1",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "keyed-pseudonyms",
   "chapter_id": "governing-data-for-ai",
   "section_id": "consistent-pseudonyms",
   "file": "examples/keyed-pseudonyms.py",
   "sha256": "57a22640e752cf68bf809ebf4948d9ccea6b4b4db2d4fd2bd24e08f303fb55af",
   "versions": {
    "python": "3.12.15",
    "absl-py": "2.5.1",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "cffi": "2.1.1",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cryptography": "48.0.1",
    "cymem": "2.0.13",
    "datasketch": "2.0.0",
    "duckdb": "2.0.0",
    "etils": "1.14.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "jsonpath-rw": "1.4.0",
    "markupsafe": "3.0.4",
    "mlcroissant": "1.1.1",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "networkx": "3.7",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "ply": "3.11",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "presidio-anonymizer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "rdflib": "7.6.0",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "scipy": "1.18.1",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "corpus-duplicates",
   "chapter_id": "governing-data-for-ai",
   "section_id": "near-duplicates-with-minhash",
   "file": "examples/corpus-duplicates.py",
   "sha256": "0b49a904e35aa45cabbbd18e688df10f523194b6ea5a56a7d4b64bcead96add5",
   "versions": {
    "python": "3.12.15",
    "absl-py": "2.5.1",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "cffi": "2.1.1",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cryptography": "48.0.1",
    "cymem": "2.0.13",
    "datasketch": "2.0.0",
    "duckdb": "2.0.0",
    "etils": "1.14.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "jsonpath-rw": "1.4.0",
    "markupsafe": "3.0.4",
    "mlcroissant": "1.1.1",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "networkx": "3.7",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "ply": "3.11",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "presidio-anonymizer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "rdflib": "7.6.0",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "scipy": "1.18.1",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "names-and-near-duplicates",
   "chapter_id": "governing-data-for-ai",
   "section_id": "near-duplicates-with-minhash",
   "file": "examples/names-and-near-duplicates.py",
   "sha256": "285d1b62ad1a96a32a0297ea92749e9754710d12d04a3f0fb4a6eabb32c44a61",
   "versions": {
    "python": "3.12.15",
    "absl-py": "2.5.1",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "cffi": "2.1.1",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cryptography": "48.0.1",
    "cymem": "2.0.13",
    "datasketch": "2.0.0",
    "duckdb": "2.0.0",
    "etils": "1.14.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "jsonpath-rw": "1.4.0",
    "markupsafe": "3.0.4",
    "mlcroissant": "1.1.1",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "networkx": "3.7",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "ply": "3.11",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "presidio-anonymizer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "rdflib": "7.6.0",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "scipy": "1.18.1",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "lsh-misses-near-duplicates",
   "chapter_id": "governing-data-for-ai",
   "section_id": "tune-lsh-then-confirm",
   "file": "examples/lsh-misses-near-duplicates.py",
   "sha256": "9ae4ea9f71a5578d9ab07deea2e252aadf5a6e67b2e7e709cc00b50579c07d7b",
   "versions": {
    "python": "3.12.15",
    "absl-py": "2.5.1",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "cffi": "2.1.1",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cryptography": "48.0.1",
    "cymem": "2.0.13",
    "datasketch": "2.0.0",
    "duckdb": "2.0.0",
    "etils": "1.14.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "jsonpath-rw": "1.4.0",
    "markupsafe": "3.0.4",
    "mlcroissant": "1.1.1",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "networkx": "3.7",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "ply": "3.11",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "presidio-anonymizer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "rdflib": "7.6.0",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "scipy": "1.18.1",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "corpus-provenance",
   "chapter_id": "governing-data-for-ai",
   "section_id": "carry-provenance",
   "file": "examples/corpus-provenance.py",
   "sha256": "d2b423e6f34590e11a54606cecc7dc3d41a80b16191edcafcf0fbef3f9a8ca80",
   "versions": {
    "python": "3.12.15",
    "absl-py": "2.5.1",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "cffi": "2.1.1",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cryptography": "48.0.1",
    "cymem": "2.0.13",
    "datasketch": "2.0.0",
    "duckdb": "2.0.0",
    "etils": "1.14.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "jsonpath-rw": "1.4.0",
    "markupsafe": "3.0.4",
    "mlcroissant": "1.1.1",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "networkx": "3.7",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "ply": "3.11",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "presidio-anonymizer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "rdflib": "7.6.0",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "scipy": "1.18.1",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "corpus-dataset-card",
   "chapter_id": "governing-data-for-ai",
   "section_id": "generate-the-dataset-card",
   "file": "examples/corpus-dataset-card.py",
   "sha256": "e79b39d68d339fd6b3ef2b3b2492e3de9aa0e78cc2c847835b0661c165e1345a",
   "versions": {
    "python": "3.12.15",
    "absl-py": "2.5.1",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "cffi": "2.1.1",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cryptography": "48.0.1",
    "cymem": "2.0.13",
    "datasketch": "2.0.0",
    "duckdb": "2.0.0",
    "etils": "1.14.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "jsonpath-rw": "1.4.0",
    "markupsafe": "3.0.4",
    "mlcroissant": "1.1.1",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "networkx": "3.7",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "ply": "3.11",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "presidio-anonymizer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "rdflib": "7.6.0",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "scipy": "1.18.1",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "consent-withdrawn-after-build",
   "chapter_id": "governing-data-for-ai",
   "section_id": "withdrawn-after-the-build",
   "file": "examples/consent-withdrawn-after-build.py",
   "sha256": "e8c3ffc14b2543587ea7da0fd9f6fe1f692f9b3fb75cadb22a7f8ba126a4bf80",
   "versions": {
    "python": "3.12.15",
    "absl-py": "2.5.1",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "cffi": "2.1.1",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cryptography": "48.0.1",
    "cymem": "2.0.13",
    "datasketch": "2.0.0",
    "duckdb": "2.0.0",
    "etils": "1.14.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "jsonpath-rw": "1.4.0",
    "markupsafe": "3.0.4",
    "mlcroissant": "1.1.1",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "networkx": "3.7",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "ply": "3.11",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "presidio-anonymizer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "rdflib": "7.6.0",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "scipy": "1.18.1",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "governance-ci-report",
   "chapter_id": "governance-in-ci",
   "section_id": "run-every-rule-as-one-job",
   "file": "examples/governance-ci-report.py",
   "sha256": "4c788d1815da5344094eae1bf18278997061e699754e8fc2ac41fec592226017",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "schema-change-impact",
   "chapter_id": "governance-in-ci",
   "section_id": "report-what-a-schema-change-reaches",
   "file": "examples/schema-change-impact.py",
   "sha256": "731ab3ad98b236c4d57a6eea930a1d2b197f7a44176908c5fcdb6d348524ef73",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "classification-downgrade",
   "chapter_id": "governance-in-ci",
   "section_id": "ask-the-owner-before-lowering",
   "file": "examples/classification-downgrade.py",
   "sha256": "c1c56b8bc8162a93be631340f428db1182689aff37e3a41359cd75a51dfdc06f",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "deprecate-then-remove",
   "chapter_id": "governance-in-ci",
   "section_id": "deprecate-before-removing",
   "file": "examples/deprecate-then-remove.py",
   "sha256": "45b6e1f3cb54757a98d20069779486ebd85a4869ff9a3b1e2d0dd7a10136e504",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "domain-contracts",
   "chapter_id": "governance-in-ci",
   "section_id": "a-folder-and-a-code-owner-per-domain",
   "file": "examples/domain-contracts.py",
   "sha256": "d96a975379205fa634c3ebd656c1f48c0e858bfe9b2db9c10f917b27036ab584",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "global-and-domain-rules",
   "chapter_id": "governance-in-ci",
   "section_id": "run-global-and-domain-rules",
   "file": "examples/global-and-domain-rules.py",
   "sha256": "b01fde91149be10cb53aba0427e70016845e075cb4d2f2fa32bb9ec3c25fd2bd",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "waived-findings",
   "chapter_id": "governance-in-ci",
   "section_id": "count-waived-findings",
   "file": "examples/waived-findings.py",
   "sha256": "b6a772e1b32ee5c19409326a17eb1f7122cd9d0cbfd8c2a2e9a2d1636d5fa1c8",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "slow-check-every-row",
   "chapter_id": "governance-in-ci",
   "section_id": "a-check-that-reads-every-row",
   "file": "examples/slow-check-every-row.py",
   "sha256": "7cc72bd815f2f53a0f024fb49ab9e77d535a726e77f8b9fee691846f09bbde8c",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "noisy-check-waivers",
   "chapter_id": "governance-in-ci",
   "section_id": "a-check-that-flags-every-id",
   "file": "examples/noisy-check-waivers.py",
   "sha256": "7d6fb34319a3b6236c943827e8a3b79d4f643decd3336e3a5013f58f65ffc71d",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  },
  {
   "example_id": "broken-files-become-findings",
   "chapter_id": "governance-in-ci",
   "section_id": "a-broken-file-becomes-a-finding",
   "file": "examples/broken-files-become-findings.py",
   "sha256": "715474c69fcad0f8d7ab65ba72304db7e12ea0dae19b4de1e07a7399fc4d22c1",
   "versions": {
    "python": "3.12.15",
    "annotated-doc": "0.0.5",
    "annotated-types": "0.8.0",
    "attrs": "26.1.0",
    "blis": "1.3.3",
    "cachetools": "7.2.4",
    "catalogue": "2.0.10",
    "certifi": "2026.10.19",
    "charset-normalizer": "3.5.2",
    "click": "8.5.0",
    "confection": "1.3.3",
    "cymem": "2.0.13",
    "duckdb": "2.0.0",
    "filelock": "4.2.4",
    "fsspec": "2026.9.0",
    "httpx": "0.28.1",
    "httpx2": "2.16.0",
    "idna": "3.20",
    "jinja2": "3.1.6",
    "markupsafe": "3.0.4",
    "mmh3": "5.3.1",
    "murmurhash": "1.0.15",
    "numpy": "2.4.6",
    "openlineage-python": "1.54.0",
    "packaging": "26.3",
    "pandas": "3.1.0",
    "phonenumbers": "9.0.41",
    "preshed": "3.0.13",
    "presidio-analyzer": "2.2.364",
    "pyarrow": "26.0.0",
    "pydantic": "2.14.1",
    "pydantic-core": "2.50.1",
    "pygments": "2.21.0",
    "pyiceberg": "0.12.0",
    "pyparsing": "3.3.3",
    "pyroaring": "1.2.0",
    "python-dateutil": "3.0.0",
    "pytz": "2026.5",
    "pyyaml": "6.0.3",
    "regex": "2026.9.29",
    "regopy": "1.5.2",
    "requests": "2.34.2",
    "requests-file": "3.0.1",
    "rich": "15.0.0",
    "setuptools": "84.2.1",
    "shellingham": "1.5.4",
    "six": "1.17.0",
    "spacy": "3.8.16",
    "sqlalchemy": "2.1.6",
    "sqlglot": "30.24.0",
    "srsly": "2.5.4",
    "strictyaml": "1.7.3",
    "thinc": "8.3.13",
    "tldextract": "5.4.0",
    "tqdm": "4.70.1",
    "typer": "0.27.3",
    "typing-extensions": "4.16.0",
    "typing-inspection": "0.4.4",
    "urllib3": "2.8.0",
    "wasabi": "1.1.3",
    "weasel": "1.0.0",
    "zstandard": "0.25.0"
   },
   "direct": [
    "datasketch",
    "duckdb",
    "mlcroissant",
    "openlineage-python",
    "phonenumbers",
    "presidio-analyzer",
    "presidio-anonymizer",
    "pyarrow",
    "pyiceberg",
    "pyyaml",
    "regopy",
    "sqlglot",
    "tldextract"
   ],
   "passing": true,
   "changed": true
  }
 ],
 "redirects": {}
}
