{"abstract":"The HTML root is placed after the images inside multipart/related.","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":"Moving the root to second place still puts an image first. The attempted `['img'] + ['html'] + ['img'] * (inline_images - 1)` still disagrees with a fixture.","family":"w2-email_mime_structure-compose-skeleton-related-root-first","id":"FA-76571","implementations":{"attempt":{"sha256":"f8281d157bf0f136e8b31044f298c6105ca02a5d4970f7c11fc309d741867c6c","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(['img'] + ['html'] + ['img'] * (inline_images - 1)) + ')'\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"},"broken":{"sha256":"cc62a02a245085764ecfaa902008ad4d8a5472d77d2179fcd9737005d15a457f","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(['img'] * inline_images + ['html']) + ')'\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"},"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-related-root-first","generated_at":"2026-09-29T14:49:17.418669+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 `['html'] + ['img'] * inline_images` for the related root first decision and keep every other rule of the model unchanged.","root_cause":"The related root first decision evaluates `['img'] * inline_images + ['html']` where the contract requires `['html'] + ['img'] * inline_images`.","sha256":"e8d1f48e136fd5ff5d030a9353cc87a6a77878f1573bf9dcb60779358b8b5126","title":"Choose the MIME skeleton for an outgoing message: related root first · 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":38.446,"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(text,related(img,html,img))","check":"text html and images","expected":"alternative(text,related(html,img,img))","passed":false},{"actual":"mixed(related(img,html),att)","check":"html images and attachment","expected":"mixed(related(html,img),att)","passed":false},{"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(img,html,img)),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(text,related(img,html,img))\", \"expected\": \"alternative(text,related(html,img,img))\", \"passed\": false}, {\"check\": \"html images and attachment\", \"actual\": \"mixed(related(img,html),att)\", \"expected\": \"mixed(related(html,img),att)\", \"passed\": false}, {\"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(img,html,img)),att)\", \"expected\": \"mixed(alternative(text,related(html,img,img)),att)\", \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":38.581,"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(text,related(img,img,html))","check":"text html and images","expected":"alternative(text,related(html,img,img))","passed":false},{"actual":"mixed(related(img,html),att)","check":"html images and attachment","expected":"mixed(related(html,img),att)","passed":false},{"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(img,img,html)),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(text,related(img,img,html))\", \"expected\": \"alternative(text,related(html,img,img))\", \"passed\": false}, {\"check\": \"html images and attachment\", \"actual\": \"mixed(related(img,html),att)\", \"expected\": \"mixed(related(html,img),att)\", \"passed\": false}, {\"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(img,img,html)),att)\", \"expected\": \"mixed(alternative(text,related(html,img,img)),att)\", \"passed\": false}], \"passed\": false}\n"},"fixed":{"elapsed_ms":38.039,"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"}