{"abstract":"The plain-text alternative is placed after the HTML one, so clients prefer plain text.","category":"Email MIME structure","checks":7,"contract":"The body is multipart/alternative(text, html) when both versions exist, the html alone when only html exists, else text. Inline images go into multipart/related with the html root first; without html they become attachments. When there are attachments the result is multipart/mixed(body, attachments...). Output is a compact string such as \"mixed(alternative(text,related(html,img)),att)\".","evaluation_group":"w2-email_mime_structure-compose-skeleton","failed_approach":"Fixing the order only for messages without images keeps the wrong order when images are present. The attempted `'alternative(' + html + ',text)' if inline_images else 'alternative(text,' + html + ')'` still disagrees with a fixture.","family":"w2-email_mime_structure-compose-skeleton-alternative-order","id":"FA-76561","implementations":{"attempt":{"sha256":"fce8b320ffd51a22394ac19f0ce9e2b97dfe7e980c7239e9330edad8ca5b030c","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(has_text, has_html, inline_images, attachments):\n    atts = attachments\n    html = None\n    if has_html:\n        html = 'html' if inline_images == 0 else 'related(' + ','.join(['html'] + ['img'] * inline_images) + ')'\n    else:\n        atts += inline_images\n    if has_text and html:\n        body = 'alternative(' + html + ',text)' if inline_images else 'alternative(text,' + html + ')'\n    elif html:\n        body = html\n    else:\n        body = 'text'\n    if atts:\n        return 'mixed(' + ','.join([body] + ['att'] * atts) + ')'\n    return body\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\n_CASES = {1: [('images without html', (False, False, 2, 0), 'mixed(text,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 2, 0), 'alternative(text,related(html,img,img))'), ('html images and attachment', (False, True, 1, 1), 'mixed(related(html,img),att)'), ('text and attachments', (True, False, 0, 1), 'mixed(text,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 1), 'mixed(alternative(text,related(html,img,img)),att)')], 2: [('images without html', (False, False, 3, 0), 'mixed(text,att,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 3, 0), 'alternative(text,related(html,img,img,img))'), ('html images and attachment', (False, True, 2, 1), 'mixed(related(html,img,img),att)'), ('text and attachments', (True, False, 0, 2), 'mixed(text,att,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 2), 'mixed(alternative(text,related(html,img,img)),att,att)')], 3: [('images without html', (False, False, 4, 0), 'mixed(text,att,att,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 4, 0), 'alternative(text,related(html,img,img,img,img))'), ('html images and attachment', (False, True, 3, 1), 'mixed(related(html,img,img,img),att)'), ('text and attachments', (True, False, 0, 3), 'mixed(text,att,att,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 3), 'mixed(alternative(text,related(html,img,img)),att,att,att)')], 4: [('images without html', (False, False, 5, 0), 'mixed(text,att,att,att,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 5, 0), 'alternative(text,related(html,img,img,img,img,img))'), ('html images and attachment', (False, True, 4, 1), 'mixed(related(html,img,img,img,img),att)'), ('text and attachments', (True, False, 0, 4), 'mixed(text,att,att,att,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 4), 'mixed(alternative(text,related(html,img,img)),att,att,att,att)')], 5: [('images without html', (False, False, 6, 0), 'mixed(text,att,att,att,att,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 6, 0), 'alternative(text,related(html,img,img,img,img,img,img))'), ('html images and attachment', (False, True, 5, 1), 'mixed(related(html,img,img,img,img,img),att)'), ('text and attachments', (True, False, 0, 5), 'mixed(text,att,att,att,att,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 5), 'mixed(alternative(text,related(html,img,img)),att,att,att,att,att)')]}\nfor _label, _args, _expected in _CASES[N]:\n    check(_label, solve(*_args), _expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"5f4a370f3b1725a3de0934f7199c8f054ac2dabefcb5973d856cddc8de82cf87","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(has_text, has_html, inline_images, attachments):\n    atts = attachments\n    html = None\n    if has_html:\n        html = 'html' if inline_images == 0 else 'related(' + ','.join(['html'] + ['img'] * inline_images) + ')'\n    else:\n        atts += inline_images\n    if has_text and html:\n        body = 'alternative(' + html + ',text)'\n    elif html:\n        body = html\n    else:\n        body = 'text'\n    if atts:\n        return 'mixed(' + ','.join([body] + ['att'] * atts) + ')'\n    return body\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\n_CASES = {1: [('images without html', (False, False, 2, 0), 'mixed(text,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 2, 0), 'alternative(text,related(html,img,img))'), ('html images and attachment', (False, True, 1, 1), 'mixed(related(html,img),att)'), ('text and attachments', (True, False, 0, 1), 'mixed(text,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 1), 'mixed(alternative(text,related(html,img,img)),att)')], 2: [('images without html', (False, False, 3, 0), 'mixed(text,att,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 3, 0), 'alternative(text,related(html,img,img,img))'), ('html images and attachment', (False, True, 2, 1), 'mixed(related(html,img,img),att)'), ('text and attachments', (True, False, 0, 2), 'mixed(text,att,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 2), 'mixed(alternative(text,related(html,img,img)),att,att)')], 3: [('images without html', (False, False, 4, 0), 'mixed(text,att,att,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 4, 0), 'alternative(text,related(html,img,img,img,img))'), ('html images and attachment', (False, True, 3, 1), 'mixed(related(html,img,img,img),att)'), ('text and attachments', (True, False, 0, 3), 'mixed(text,att,att,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 3), 'mixed(alternative(text,related(html,img,img)),att,att,att)')], 4: [('images without html', (False, False, 5, 0), 'mixed(text,att,att,att,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 5, 0), 'alternative(text,related(html,img,img,img,img,img))'), ('html images and attachment', (False, True, 4, 1), 'mixed(related(html,img,img,img,img),att)'), ('text and attachments', (True, False, 0, 4), 'mixed(text,att,att,att,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 4), 'mixed(alternative(text,related(html,img,img)),att,att,att,att)')], 5: [('images without html', (False, False, 6, 0), 'mixed(text,att,att,att,att,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 6, 0), 'alternative(text,related(html,img,img,img,img,img,img))'), ('html images and attachment', (False, True, 5, 1), 'mixed(related(html,img,img,img,img,img),att)'), ('text and attachments', (True, False, 0, 5), 'mixed(text,att,att,att,att,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 5), 'mixed(alternative(text,related(html,img,img)),att,att,att,att,att)')]}\nfor _label, _args, _expected in _CASES[N]:\n    check(_label, solve(*_args), _expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"ec74f87d73b4fa1010c8151d39edf169ac8f01d74a67260bb62559e9e13dab15","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(has_text, has_html, inline_images, attachments):\n    atts = attachments\n    html = None\n    if has_html:\n        html = 'html' if inline_images == 0 else 'related(' + ','.join(['html'] + ['img'] * inline_images) + ')'\n    else:\n        atts += inline_images\n    if has_text and html:\n        body = 'alternative(text,' + html + ')'\n    elif html:\n        body = html\n    else:\n        body = 'text'\n    if atts:\n        return 'mixed(' + ','.join([body] + ['att'] * atts) + ')'\n    return body\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\n_CASES = {1: [('images without html', (False, False, 2, 0), 'mixed(text,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 2, 0), 'alternative(text,related(html,img,img))'), ('html images and attachment', (False, True, 1, 1), 'mixed(related(html,img),att)'), ('text and attachments', (True, False, 0, 1), 'mixed(text,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 1), 'mixed(alternative(text,related(html,img,img)),att)')], 2: [('images without html', (False, False, 3, 0), 'mixed(text,att,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 3, 0), 'alternative(text,related(html,img,img,img))'), ('html images and attachment', (False, True, 2, 1), 'mixed(related(html,img,img),att)'), ('text and attachments', (True, False, 0, 2), 'mixed(text,att,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 2), 'mixed(alternative(text,related(html,img,img)),att,att)')], 3: [('images without html', (False, False, 4, 0), 'mixed(text,att,att,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 4, 0), 'alternative(text,related(html,img,img,img,img))'), ('html images and attachment', (False, True, 3, 1), 'mixed(related(html,img,img,img),att)'), ('text and attachments', (True, False, 0, 3), 'mixed(text,att,att,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 3), 'mixed(alternative(text,related(html,img,img)),att,att,att)')], 4: [('images without html', (False, False, 5, 0), 'mixed(text,att,att,att,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 5, 0), 'alternative(text,related(html,img,img,img,img,img))'), ('html images and attachment', (False, True, 4, 1), 'mixed(related(html,img,img,img,img),att)'), ('text and attachments', (True, False, 0, 4), 'mixed(text,att,att,att,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 4), 'mixed(alternative(text,related(html,img,img)),att,att,att,att)')], 5: [('images without html', (False, False, 6, 0), 'mixed(text,att,att,att,att,att,att)'), ('text and html', (True, True, 0, 0), 'alternative(text,html)'), ('text html and images', (True, True, 6, 0), 'alternative(text,related(html,img,img,img,img,img,img))'), ('html images and attachment', (False, True, 5, 1), 'mixed(related(html,img,img,img,img,img),att)'), ('text and attachments', (True, False, 0, 5), 'mixed(text,att,att,att,att,att)'), ('plain text only', (True, False, 0, 0), 'text'), ('everything', (True, True, 2, 5), 'mixed(alternative(text,related(html,img,img)),att,att,att,att,att)')]}\nfor _label, _args, _expected in _CASES[N]:\n    check(_label, solve(*_args), _expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"Stipulated offline model over pre-parsed MIME dictionaries; not a conforming MIME parser, generator or mail client. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-email_mime_structure-compose-skeleton-alternative-order","generated_at":"2026-09-29T14:49:17.381581+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Composing the wrong skeleton makes clients show images as attachments, hide the plain-text version or drop parts.","repair":"Use `'alternative(text,' + html + ')'` for the alternative order decision and keep every other rule of the model unchanged.","root_cause":"The alternative order decision evaluates `'alternative(' + html + ',text)'` where the contract requires `'alternative(text,' + html + ')'`.","sha256":"f6214d5ea3b8ba16d29258806f5e11774dfff71c28a59ea1689c581c19a2d62a","title":"Choose the MIME skeleton for an outgoing message: alternative order · case 01","variant":1,"variant_policy":"N selects a different enumerated fixture set (renamed identifiers, part counts and sizes); boundary fixtures recur across variants.","verification":{"attempt":{"elapsed_ms":39.087,"exit_code":1,"observations":[{"actual":"mixed(text,att,att)","check":"images without html","expected":"mixed(text,att,att)","passed":true},{"actual":"alternative(text,html)","check":"text and html","expected":"alternative(text,html)","passed":true},{"actual":"alternative(related(html,img,img),text)","check":"text html and images","expected":"alternative(text,related(html,img,img))","passed":false},{"actual":"mixed(related(html,img),att)","check":"html images and attachment","expected":"mixed(related(html,img),att)","passed":true},{"actual":"mixed(text,att)","check":"text and attachments","expected":"mixed(text,att)","passed":true},{"actual":"text","check":"plain text only","expected":"text","passed":true},{"actual":"mixed(alternative(related(html,img,img),text),att)","check":"everything","expected":"mixed(alternative(text,related(html,img,img)),att)","passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"images without html\", \"actual\": \"mixed(text,att,att)\", \"expected\": \"mixed(text,att,att)\", \"passed\": true}, {\"check\": \"text and html\", \"actual\": \"alternative(text,html)\", \"expected\": \"alternative(text,html)\", \"passed\": true}, {\"check\": \"text html and images\", \"actual\": \"alternative(related(html,img,img),text)\", \"expected\": \"alternative(text,related(html,img,img))\", \"passed\": false}, {\"check\": \"html images and attachment\", \"actual\": \"mixed(related(html,img),att)\", \"expected\": \"mixed(related(html,img),att)\", \"passed\": true}, {\"check\": \"text and attachments\", \"actual\": \"mixed(text,att)\", \"expected\": \"mixed(text,att)\", \"passed\": true}, {\"check\": \"plain text only\", \"actual\": \"text\", \"expected\": \"text\", \"passed\": true}, {\"check\": \"everything\", \"actual\": \"mixed(alternative(related(html,img,img),text),att)\", \"expected\": \"mixed(alternative(text,related(html,img,img)),att)\", \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":39.447,"exit_code":1,"observations":[{"actual":"mixed(text,att,att)","check":"images without html","expected":"mixed(text,att,att)","passed":true},{"actual":"alternative(html,text)","check":"text and html","expected":"alternative(text,html)","passed":false},{"actual":"alternative(related(html,img,img),text)","check":"text html and images","expected":"alternative(text,related(html,img,img))","passed":false},{"actual":"mixed(related(html,img),att)","check":"html images and attachment","expected":"mixed(related(html,img),att)","passed":true},{"actual":"mixed(text,att)","check":"text and attachments","expected":"mixed(text,att)","passed":true},{"actual":"text","check":"plain text only","expected":"text","passed":true},{"actual":"mixed(alternative(related(html,img,img),text),att)","check":"everything","expected":"mixed(alternative(text,related(html,img,img)),att)","passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"images without html\", \"actual\": \"mixed(text,att,att)\", \"expected\": \"mixed(text,att,att)\", \"passed\": true}, {\"check\": \"text and html\", \"actual\": \"alternative(html,text)\", \"expected\": \"alternative(text,html)\", \"passed\": false}, {\"check\": \"text html and images\", \"actual\": \"alternative(related(html,img,img),text)\", \"expected\": \"alternative(text,related(html,img,img))\", \"passed\": false}, {\"check\": \"html images and attachment\", \"actual\": \"mixed(related(html,img),att)\", \"expected\": \"mixed(related(html,img),att)\", \"passed\": true}, {\"check\": \"text and attachments\", \"actual\": \"mixed(text,att)\", \"expected\": \"mixed(text,att)\", \"passed\": true}, {\"check\": \"plain text only\", \"actual\": \"text\", \"expected\": \"text\", \"passed\": true}, {\"check\": \"everything\", \"actual\": \"mixed(alternative(related(html,img,img),text),att)\", \"expected\": \"mixed(alternative(text,related(html,img,img)),att)\", \"passed\": false}], \"passed\": false}\n"},"fixed":{"elapsed_ms":39.556,"exit_code":0,"observations":[{"actual":"mixed(text,att,att)","check":"images without html","expected":"mixed(text,att,att)","passed":true},{"actual":"alternative(text,html)","check":"text and html","expected":"alternative(text,html)","passed":true},{"actual":"alternative(text,related(html,img,img))","check":"text html and images","expected":"alternative(text,related(html,img,img))","passed":true},{"actual":"mixed(related(html,img),att)","check":"html images and attachment","expected":"mixed(related(html,img),att)","passed":true},{"actual":"mixed(text,att)","check":"text and attachments","expected":"mixed(text,att)","passed":true},{"actual":"text","check":"plain text only","expected":"text","passed":true},{"actual":"mixed(alternative(text,related(html,img,img)),att)","check":"everything","expected":"mixed(alternative(text,related(html,img,img)),att)","passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"images without html\", \"actual\": \"mixed(text,att,att)\", \"expected\": \"mixed(text,att,att)\", \"passed\": true}, {\"check\": \"text and html\", \"actual\": \"alternative(text,html)\", \"expected\": \"alternative(text,html)\", \"passed\": true}, {\"check\": \"text html and images\", \"actual\": \"alternative(text,related(html,img,img))\", \"expected\": \"alternative(text,related(html,img,img))\", \"passed\": true}, {\"check\": \"html images and attachment\", \"actual\": \"mixed(related(html,img),att)\", \"expected\": \"mixed(related(html,img),att)\", \"passed\": true}, {\"check\": \"text and attachments\", \"actual\": \"mixed(text,att)\", \"expected\": \"mixed(text,att)\", \"passed\": true}, {\"check\": \"plain text only\", \"actual\": \"text\", \"expected\": \"text\", \"passed\": true}, {\"check\": \"everything\", \"actual\": \"mixed(alternative(text,related(html,img,img)),att)\", \"expected\": \"mixed(alternative(text,related(html,img,img)),att)\", \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}