{"abstract":"Multi-word subtitles get recommended durations that are too long.","category":"Subtitle cue timing","checks":9,"contract":"rules [base,per_char,min,max]. Count characters other than spaces and line breaks; duration = base + count*per_char, clamped to [min,max]; then rounded up to whole frames at fps [N,D]. Return [frames, ceil(frames*1000*D/N)].","contract_signature":"text, fps, rules","evaluation_group":"w2-subtitle-cue-timing-recommended-duration","failed_approach":"Excluding spaces but not line breaks still inflates two-line cues.","family":"w2-subtitle-cue-timing-recommended-duration-character-counting","id":"FA-78266","implementations":{"attempt":{"sha256":"6efcbb1fc709542717e6bc78698d02b6bacbf449109bcdc224a18aff771be5f6","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(text, fps, rules):\n    base,per,lo,hi=rules\n    n=len(text.replace(' ',''))\n    d=base+n*per\n    d=max(lo,min(hi,d))\n    num,den=fps\n    fr=-((-d*num)//(1000*den))\n    return [fr,-((-fr*1000*den)//num)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('regression: character counting', ['Two\\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('regression variant: character counting', ['A much longer subtitle line to read', [24, 1], [0, 70, 800, 7000]], [49, 2042]), ('partial repair probe: character counting', ['Two\\nlines here', [24000, 1001], [700, 100, 1000, 2000]], [46, 1919]), ('partial repair variant: character counting', ['Two\\nlines here', [30000, 1001], [500, 60, 1000, 6000]], [37, 1235]), ('boundary control', ['Hi', [25, 1], [500, 60, 1000, 6000]], [25, 1000]), ('boundary control', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 2000]], [50, 2000]), ('normal control', ['   ', [25, 1], [700, 100, 1000, 2000]], [25, 1000]), ('normal control', ['Two\\nlines here', [25, 1], [300, 50, 1200, 1500]], [30, 1200]), ('normal control', ['A much longer subtitle line to read', [24000, 1001], [300, 50, 1200, 1500]], [36, 1502])], [('regression: character counting', ['Hello world', [30, 1], [700, 100, 1000, 2000]], [51, 1700]), ('regression variant: character counting', ['Hello world', [24000, 1001], [500, 60, 1000, 6000]], [27, 1127]), ('partial repair probe: character counting', ['Two\\nlines here', [24, 1], [0, 70, 800, 7000]], [21, 875]), ('partial repair variant: character counting', ['Two\\nlines here', [24, 1], [700, 100, 1000, 2000]], [46, 1917]), ('boundary control', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 2000]], [50, 2000]), ('boundary control', ['Hi', [25, 1], [500, 60, 1000, 6000]], [25, 1000]), ('normal control', ['Hi', [24, 1], [500, 60, 1000, 6000]], [24, 1000]), ('normal control', ['ok', [30, 1], [700, 100, 1000, 2000]], [30, 1000]), ('normal control', ['A much longer subtitle line to read', [30, 1], [700, 100, 1000, 2000]], [60, 2000])], [('regression: character counting', ['Two\\nlines here', [30, 1], [700, 100, 1000, 2000]], [57, 1900]), ('regression variant: character counting', ['Two\\nlines here', [24, 1], [0, 70, 800, 7000]], [21, 875]), ('partial repair probe: character counting', ['Two\\nlines here', [25, 1], [0, 70, 800, 7000]], [21, 840]), ('partial repair variant: character counting', ['Two\\nlines here', [25, 1], [700, 100, 1000, 2000]], [48, 1920]), ('boundary control', ['Hi', [25, 1], [500, 60, 1000, 6000]], [25, 1000]), ('boundary control', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 2000]], [50, 2000]), ('normal control', ['Hello world', [30, 1], [0, 70, 800, 7000]], [24, 800]), ('normal control', ['ok', [30000, 1001], [300, 50, 1200, 1500]], [36, 1202]), ('normal control', ['', [24, 1], [300, 50, 1200, 1500]], [29, 1209])], [('regression: character counting', ['Two\\nlines here', [24000, 1001], [700, 100, 1000, 2000]], [46, 1919]), ('regression variant: character counting', ['Two\\nlines here', [25, 1], [0, 70, 800, 7000]], [21, 840]), ('partial repair probe: character counting', ['Two\\nlines here', [24, 1], [500, 60, 1000, 6000]], [30, 1250]), ('partial repair variant: character counting', ['Two\\nlines here', [30, 1], [0, 70, 800, 7000]], [26, 867]), ('boundary control', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 2000]], [50, 2000]), ('boundary control', ['Hi', [25, 1], [500, 60, 1000, 6000]], [25, 1000]), ('normal control', ['Hi', [30, 1], [300, 50, 1200, 1500]], [36, 1200]), ('normal control', ['ok', [24, 1], [500, 60, 1000, 6000]], [24, 1000]), ('normal control', ['   ', [25, 1], [500, 60, 1000, 6000]], [25, 1000])], [('regression: character counting', ['Hello world', [30000, 1001], [500, 60, 1000, 6000]], [33, 1102]), ('regression variant: character counting', ['Hello world', [30, 1], [500, 60, 1000, 6000]], [33, 1100]), ('partial repair probe: character counting', ['Two\\nlines here', [24000, 1001], [500, 60, 1000, 6000]], [30, 1252]), ('partial repair variant: character counting', ['Two\\nlines here', [30000, 1001], [700, 100, 1000, 2000]], [57, 1902]), ('boundary control', ['Hi', [25, 1], [500, 60, 1000, 6000]], [25, 1000]), ('boundary control', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 2000]], [50, 2000]), ('normal control', ['ok', [25, 1], [300, 50, 1200, 1500]], [30, 1200]), ('normal control', ['   ', [30, 1], [0, 70, 800, 7000]], [24, 800]), ('normal control', ['Two\\nlines here', [30, 1], [300, 50, 1200, 1500]], [36, 1200])]]\nfor label, args, expected in fixtures[N-1]:\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":"6339139465b8317a54e5ac5b1c27dbcaece5f93da21945565815ce2ee85cfb0b","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(text, fps, rules):\n    base,per,lo,hi=rules\n    n=len(text)\n    d=base+n*per\n    d=max(lo,min(hi,d))\n    num,den=fps\n    fr=-((-d*num)//(1000*den))\n    return [fr,-((-fr*1000*den)//num)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('regression: character counting', ['Two\\nlines here', [30000, 1001], [0, 70, 800, 7000]], [26, 868]), ('regression variant: character counting', ['A much longer subtitle line to read', [24, 1], [0, 70, 800, 7000]], [49, 2042]), ('partial repair probe: character counting', ['Two\\nlines here', [24000, 1001], [700, 100, 1000, 2000]], [46, 1919]), ('partial repair variant: character counting', ['Two\\nlines here', [30000, 1001], [500, 60, 1000, 6000]], [37, 1235]), ('boundary control', ['Hi', [25, 1], [500, 60, 1000, 6000]], [25, 1000]), ('boundary control', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 2000]], [50, 2000]), ('normal control', ['   ', [25, 1], [700, 100, 1000, 2000]], [25, 1000]), ('normal control', ['Two\\nlines here', [25, 1], [300, 50, 1200, 1500]], [30, 1200]), ('normal control', ['A much longer subtitle line to read', [24000, 1001], [300, 50, 1200, 1500]], [36, 1502])], [('regression: character counting', ['Hello world', [30, 1], [700, 100, 1000, 2000]], [51, 1700]), ('regression variant: character counting', ['Hello world', [24000, 1001], [500, 60, 1000, 6000]], [27, 1127]), ('partial repair probe: character counting', ['Two\\nlines here', [24, 1], [0, 70, 800, 7000]], [21, 875]), ('partial repair variant: character counting', ['Two\\nlines here', [24, 1], [700, 100, 1000, 2000]], [46, 1917]), ('boundary control', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 2000]], [50, 2000]), ('boundary control', ['Hi', [25, 1], [500, 60, 1000, 6000]], [25, 1000]), ('normal control', ['Hi', [24, 1], [500, 60, 1000, 6000]], [24, 1000]), ('normal control', ['ok', [30, 1], [700, 100, 1000, 2000]], [30, 1000]), ('normal control', ['A much longer subtitle line to read', [30, 1], [700, 100, 1000, 2000]], [60, 2000])], [('regression: character counting', ['Two\\nlines here', [30, 1], [700, 100, 1000, 2000]], [57, 1900]), ('regression variant: character counting', ['Two\\nlines here', [24, 1], [0, 70, 800, 7000]], [21, 875]), ('partial repair probe: character counting', ['Two\\nlines here', [25, 1], [0, 70, 800, 7000]], [21, 840]), ('partial repair variant: character counting', ['Two\\nlines here', [25, 1], [700, 100, 1000, 2000]], [48, 1920]), ('boundary control', ['Hi', [25, 1], [500, 60, 1000, 6000]], [25, 1000]), ('boundary control', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 2000]], [50, 2000]), ('normal control', ['Hello world', [30, 1], [0, 70, 800, 7000]], [24, 800]), ('normal control', ['ok', [30000, 1001], [300, 50, 1200, 1500]], [36, 1202]), ('normal control', ['', [24, 1], [300, 50, 1200, 1500]], [29, 1209])], [('regression: character counting', ['Two\\nlines here', [24000, 1001], [700, 100, 1000, 2000]], [46, 1919]), ('regression variant: character counting', ['Two\\nlines here', [25, 1], [0, 70, 800, 7000]], [21, 840]), ('partial repair probe: character counting', ['Two\\nlines here', [24, 1], [500, 60, 1000, 6000]], [30, 1250]), ('partial repair variant: character counting', ['Two\\nlines here', [30, 1], [0, 70, 800, 7000]], [26, 867]), ('boundary control', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 2000]], [50, 2000]), ('boundary control', ['Hi', [25, 1], [500, 60, 1000, 6000]], [25, 1000]), ('normal control', ['Hi', [30, 1], [300, 50, 1200, 1500]], [36, 1200]), ('normal control', ['ok', [24, 1], [500, 60, 1000, 6000]], [24, 1000]), ('normal control', ['   ', [25, 1], [500, 60, 1000, 6000]], [25, 1000])], [('regression: character counting', ['Hello world', [30000, 1001], [500, 60, 1000, 6000]], [33, 1102]), ('regression variant: character counting', ['Hello world', [30, 1], [500, 60, 1000, 6000]], [33, 1100]), ('partial repair probe: character counting', ['Two\\nlines here', [24000, 1001], [500, 60, 1000, 6000]], [30, 1252]), ('partial repair variant: character counting', ['Two\\nlines here', [30000, 1001], [700, 100, 1000, 2000]], [57, 1902]), ('boundary control', ['Hi', [25, 1], [500, 60, 1000, 6000]], [25, 1000]), ('boundary control', ['A much longer subtitle line to read', [25, 1], [500, 60, 1000, 2000]], [50, 2000]), ('normal control', ['ok', [25, 1], [300, 50, 1200, 1500]], [30, 1200]), ('normal control', ['   ', [30, 1], [0, 70, 800, 7000]], [24, 800]), ('normal control', ['Two\\nlines here', [30, 1], [300, 50, 1200, 1500]], [36, 1200])]]\nfor label, args, expected in fixtures[N-1]:\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":"A deterministic bounded teaching model with a stipulated toy contract; it does not claim conformance to any subtitle standard. 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-subtitle-cue-timing-recommended-duration-character-counting","generated_at":"2026-09-29T14:49:33.736816+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Subtitle timing defects shift, hide or overlap captions that viewers depend on for comprehension and accessibility.","root_cause":"Spaces and line breaks are counted as reading characters.","sha256":"0c62dafa54cf253cf7bb2c500318206620d532c1ccc89e1eea9d2768ad0ce6e4","title":"Recommended cue duration on frame grid: character counting · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verified":true,"visibility":"public","verification":{"attempt":{"elapsed_ms":38.719,"exit_code":1,"observations":[{"actual":[28,935],"check":"regression: character counting","expected":[26,868],"passed":false},{"actual":[49,2042],"check":"regression variant: character counting","expected":[49,2042],"passed":true},{"actual":[48,2002],"check":"partial repair probe: character counting","expected":[46,1919],"passed":false},{"actual":[39,1302],"check":"partial repair variant: character counting","expected":[37,1235],"passed":false},{"actual":[25,1000],"check":"boundary control","expected":[25,1000],"passed":true},{"actual":[50,2000],"check":"boundary control","expected":[50,2000],"passed":true},{"actual":[25,1000],"check":"normal control","expected":[25,1000],"passed":true},{"actual":[30,1200],"check":"normal control","expected":[30,1200],"passed":true},{"actual":[36,1502],"check":"normal control","expected":[36,1502],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: character counting\", \"actual\": [28, 935], \"expected\": [26, 868], \"passed\": false}, {\"check\": \"regression variant: character counting\", \"actual\": [49, 2042], \"expected\": [49, 2042], \"passed\": true}, {\"check\": \"partial repair probe: character counting\", \"actual\": [48, 2002], \"expected\": [46, 1919], \"passed\": false}, {\"check\": \"partial repair variant: character counting\", \"actual\": [39, 1302], \"expected\": [37, 1235], \"passed\": false}, {\"check\": \"boundary control\", \"actual\": [25, 1000], \"expected\": [25, 1000], \"passed\": true}, {\"check\": \"boundary control\", \"actual\": [50, 2000], \"expected\": [50, 2000], \"passed\": true}, {\"check\": \"normal control\", \"actual\": [25, 1000], \"expected\": [25, 1000], \"passed\": true}, {\"check\": \"normal control\", \"actual\": [30, 1200], \"expected\": [30, 1200], \"passed\": true}, {\"check\": \"normal control\", \"actual\": [36, 1502], \"expected\": [36, 1502], \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":40.614,"exit_code":1,"observations":[{"actual":[30,1001],"check":"regression: character counting","expected":[26,868],"passed":false},{"actual":[59,2459],"check":"regression variant: character counting","expected":[49,2042],"passed":false},{"actual":[48,2002],"check":"partial repair probe: character counting","expected":[46,1919],"passed":false},{"actual":[41,1369],"check":"partial repair variant: character counting","expected":[37,1235],"passed":false},{"actual":[25,1000],"check":"boundary control","expected":[25,1000],"passed":true},{"actual":[50,2000],"check":"boundary control","expected":[50,2000],"passed":true},{"actual":[25,1000],"check":"normal control","expected":[25,1000],"passed":true},{"actual":[30,1200],"check":"normal control","expected":[30,1200],"passed":true},{"actual":[36,1502],"check":"normal control","expected":[36,1502],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: character counting\", \"actual\": [30, 1001], \"expected\": [26, 868], \"passed\": false}, {\"check\": \"regression variant: character counting\", \"actual\": [59, 2459], \"expected\": [49, 2042], \"passed\": false}, {\"check\": \"partial repair probe: character counting\", \"actual\": [48, 2002], \"expected\": [46, 1919], \"passed\": false}, {\"check\": \"partial repair variant: character counting\", \"actual\": [41, 1369], \"expected\": [37, 1235], \"passed\": false}, {\"check\": \"boundary control\", \"actual\": [25, 1000], \"expected\": [25, 1000], \"passed\": true}, {\"check\": \"boundary control\", \"actual\": [50, 2000], \"expected\": [50, 2000], \"passed\": true}, {\"check\": \"normal control\", \"actual\": [25, 1000], \"expected\": [25, 1000], \"passed\": true}, {\"check\": \"normal control\", \"actual\": [30, 1200], \"expected\": [30, 1200], \"passed\": true}, {\"check\": \"normal control\", \"actual\": [36, 1502], \"expected\": [36, 1502], \"passed\": true}], \"passed\": false}\n"}},"member_only":{"stages":["fixed"],"fields":["implementations.fixed","verification.fixed","harness","repair"],"note":"The verified repair, its recorded checks, the repair description, and the scoring harness are available to members."}}