FAILURE MAP
← Case archive

FA-80181 / Typography line breaking / Open access

Ties and discretionary hyphens: tie breakability · case 01

Lines break inside "Dr.~Knuth" style ties.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The tie is tokenized like an ordinary space.

THE FAILURE

The tie is tokenized like an ordinary space.

Unsuccessful approach: Dropping the tie keeps the words together but glues them with no space.

Case contract

Input [source, width]. Runs of spaces are one breakable space; "~" is an unbreakable space rendered " "; "\-" is a discretionary hyphen: invisible unless the line breaks there, then rendered "-"; "|" is an invisible break opportunity. Greedy: append the next chunk if the line (without a potential hyphen) fits, else break at that opportunity. Return rendered lines.

Why this case matters

Line breaking decides where paragraphs wrap on screen and in print; a wrong decision point shifts every following line.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    src, width = x
    chunks = ['']
    ops = []
    i = 0
    while i < len(src):
        c = src[i]
        if src.startswith('\\-', i):
            ops.append('d')
            chunks.append('')
            i += 2
            continue
        if c in ' ~':
            j = i
            while j < len(src) and src[j] in ' ~':
                j += 1
            ops.append('s')
            chunks.append('')
            i = j
            continue
        if c == '|':
            ops.append('z')
            chunks.append('')
            i += 1
            continue
        chunks[-1] += ' ' if c == '~' else c
        i += 1
    line = chunks[0]
    lines = []
    for op, ch in zip(ops, chunks[1:]):
        sep = ' ' if op == 's' else ''
        if len(line + sep + ch) <= width:
            line = line + sep + ch
        else:
            lines.append(line + ('-' if op == 'd' else ''))
            line = ch
    lines.append(line)
    return lines
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('tie keeps title with name', ['see Dr.~Knuth now', 9], ['see', 'Dr. Knuth', 'now']), ('regression: tie breakability', ['com\\-po\\-si\\-tion word word  ~url|path com\\-po\\-si\\-tion 10~pt', 14], ['composition', 'word word  url', 'path composi-', 'tion 10 pt']), ('regression: tie breakability', ['ink  x Dr.~Knuth ink ink set x word', 7], ['ink x', 'Dr. Knuth', 'ink ink', 'set x', 'word']), ('regression: tie breakability', ['url|path type type com\\-po\\-si\\-tion Dr.~Knuth', 5], ['url', 'path', 'type', 'type', 'compo-', 'si-', 'tion', 'Dr. Knuth']), ('double space collapses', ['type  set', 20], ['type set']), ('invisible break', ['url|path|x', 5], ['url', 'pathx']), ('control layout', ['word  a a set', 7], ['word a', 'a set']), ('control layout', ['url|path com\\-po\\-si\\-tion x a url|path  a', 14], ['urlpath compo-', 'sition x a url', 'path a'])], [('regression: tie breakability', ['com\\-po\\-si\\-tion ~x  com\\-po\\-si\\-tion', 13], ['composition', ' x composi-', 'tion']), ('regression: tie breakability', ['hy\\-phen ~type set ~com\\-po\\-si\\-tion set  type  com\\-po\\-si\\-tion word set', 15], ['hyphen  type', 'set  composi-', 'tion set type', 'composition', 'word set']), ('regression: tie breakability', ['ink 10~pt ink b|c hy\\-phen ~set url|path word', 16], ['ink 10 pt ink bc', 'hyphen  set url', 'path word']), ('regression: tie breakability', ['hy\\-phen ~10~pt b|c hy\\-phen ~x  com\\-po\\-si\\-tion', 5], ['hy-', 'phen', ' 10 pt', 'bc hy-', 'phen', ' x', 'compo-', 'si-', 'tion']), ('tie keeps title with name', ['see Dr.~Knuth now', 9], ['see', 'Dr. Knuth', 'now']), ('discretionary taken', ['the com\\-po\\-si\\-tion', 9], ['the compo-', 'sition']), ('control layout', ['b|c ink hy\\-phen url|path type com\\-po\\-si\\-tion', 8], ['bc ink', 'hyphen', 'urlpath', 'type com-', 'position']), ('control layout', ['b|c  a ink  ink com\\-po\\-si\\-tion', 11], ['bc a ink', 'ink composi-', 'tion'])], [('regression: tie breakability', ['x com\\-po\\-si\\-tion ink ~type', 14], ['x composition', 'ink  type']), ('regression: tie breakability', ['Dr.~Knuth  hy\\-phen  com\\-po\\-si\\-tion Dr.~Knuth word ink', 6], ['Dr. Knuth', 'hyphen', 'compo-', 'sition', 'Dr. Knuth', 'word', 'ink']), ('regression: tie breakability', ['hy\\-phen type ~word  hy\\-phen ~x', 14], ['hyphen type', ' word hyphen', ' x']), ('partial-repair probe', ['b|c url|path word  Dr.~Knuth', 9], ['bc url', 'path word', 'Dr. Knuth']), ('double space collapses', ['type  set', 20], ['type set']), ('tie keeps title with name', ['see Dr.~Knuth now', 9], ['see', 'Dr. Knuth', 'now']), ('control layout', ['word com\\-po\\-si\\-tion a', 15], ['word composi-', 'tion a']), ('control layout', ['type set b|c', 6], ['type', 'set bc'])], [('regression: tie breakability', ['type a hy\\-phen com\\-po\\-si\\-tion ~set set ink  type', 8], ['type a', 'hyphen', 'composi-', 'tion', ' set set', 'ink type']), ('regression: tie breakability', ['ink ~10~pt type  com\\-po\\-si\\-tion url|path  a ~x 10~pt b|c', 9], ['ink', ' 10 pt', 'type com-', 'position', 'urlpath a', ' x 10 pt', 'bc']), ('partial-repair probe', ['ink com\\-po\\-si\\-tion Dr.~Knuth', 16], ['ink composition', 'Dr. Knuth']), ('regression: tie breakability', ['x set  type com\\-po\\-si\\-tion a ~ink b|c hy\\-phen url|path', 13], ['x set type', 'composition a', ' ink bc hy-', 'phen urlpath']), ('discretionary taken', ['the com\\-po\\-si\\-tion', 9], ['the compo-', 'sition']), ('tie keeps title with name', ['see Dr.~Knuth now', 9], ['see', 'Dr. Knuth', 'now']), ('control layout', ['a type  com\\-po\\-si\\-tion a', 6], ['a type', 'compo-', 'sition', 'a']), ('control layout', ['com\\-po\\-si\\-tion  hy\\-phen com\\-po\\-si\\-tion ink  b|c a', 10], ['composi-', 'tion hy-', 'phen compo-', 'sition ink', 'bc a'])], [('regression: tie breakability', ['Dr.~Knuth ink 10~pt  set x', 16], ['Dr. Knuth ink', '10 pt set x']), ('regression: tie breakability', ['hy\\-phen type ~x ~x hy\\-phen  10~pt  hy\\-phen 10~pt word', 14], ['hyphen type  x', ' x hyphen', '10 pt hyphen', '10 pt word']), ('partial-repair probe', ['url|path type  10~pt  word', 6], ['url', 'path', 'type', '10 pt', 'word']), ('regression: tie breakability', ['url|path type type com\\-po\\-si\\-tion Dr.~Knuth', 5], ['url', 'path', 'type', 'type', 'compo-', 'si-', 'tion', 'Dr. Knuth']), ('tie keeps title with name', ['see Dr.~Knuth now', 9], ['see', 'Dr. Knuth', 'now']), ('invisible break', ['url|path|x', 5], ['url', 'pathx']), ('control layout', ['com\\-po\\-si\\-tion type hy\\-phen hy\\-phen url|path ink', 13], ['composition', 'type hyphen', 'hyphen url', 'path ink']), ('control layout', ['word  a a set', 7], ['word a', 'a set'])]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
tie keeps title with name['see Dr.', 'Knuth now']['see', 'Dr. Knuth', 'now']Failed
regression: tie breakability['composition', 'word word url', 'path composi-', 'tion 10 pt']['composition', 'word word url', 'path composi-', 'tion 10 pt']Failed
regression: tie breakability['ink x', 'Dr.', 'Knuth', 'ink ink', 'set x', 'word']['ink x', 'Dr. Knuth', 'ink ink', 'set x', 'word']Failed
regression: tie breakability['url', 'path', 'type', 'type', 'compo-', 'si-', 'tion', 'Dr.', 'Knuth']['url', 'path', 'type', 'type', 'compo-', 'si-', 'tion', 'Dr. Knuth']Failed
double space collapses['type set']['type set']Passed
invisible break['url', 'pathx']['url', 'pathx']Passed
control layout['word a', 'a set']['word a', 'a set']Passed
control layout['urlpath compo-', 'sition x a url', 'path a']['urlpath compo-', 'sition x a url', 'path a']Passed

SHA-256 / f1eebb36a25b022ffb070d11b723682417ea1a3b6afd154c27479abbbb573576

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    src, width = x
    chunks = ['']
    ops = []
    i = 0
    while i < len(src):
        c = src[i]
        if src.startswith('\\-', i):
            ops.append('d')
            chunks.append('')
            i += 2
            continue
        if c == ' ':
            j = i
            while j < len(src) and src[j] == ' ':
                j += 1
            ops.append('s')
            chunks.append('')
            i = j
            continue
        if c == '|':
            ops.append('z')
            chunks.append('')
            i += 1
            continue
        chunks[-1] += '' if c == '~' else c
        i += 1
    line = chunks[0]
    lines = []
    for op, ch in zip(ops, chunks[1:]):
        sep = ' ' if op == 's' else ''
        if len(line + sep + ch) <= width:
            line = line + sep + ch
        else:
            lines.append(line + ('-' if op == 'd' else ''))
            line = ch
    lines.append(line)
    return lines
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('tie keeps title with name', ['see Dr.~Knuth now', 9], ['see', 'Dr. Knuth', 'now']), ('regression: tie breakability', ['com\\-po\\-si\\-tion word word  ~url|path com\\-po\\-si\\-tion 10~pt', 14], ['composition', 'word word  url', 'path composi-', 'tion 10 pt']), ('regression: tie breakability', ['ink  x Dr.~Knuth ink ink set x word', 7], ['ink x', 'Dr. Knuth', 'ink ink', 'set x', 'word']), ('regression: tie breakability', ['url|path type type com\\-po\\-si\\-tion Dr.~Knuth', 5], ['url', 'path', 'type', 'type', 'compo-', 'si-', 'tion', 'Dr. Knuth']), ('double space collapses', ['type  set', 20], ['type set']), ('invisible break', ['url|path|x', 5], ['url', 'pathx']), ('control layout', ['word  a a set', 7], ['word a', 'a set']), ('control layout', ['url|path com\\-po\\-si\\-tion x a url|path  a', 14], ['urlpath compo-', 'sition x a url', 'path a'])], [('regression: tie breakability', ['com\\-po\\-si\\-tion ~x  com\\-po\\-si\\-tion', 13], ['composition', ' x composi-', 'tion']), ('regression: tie breakability', ['hy\\-phen ~type set ~com\\-po\\-si\\-tion set  type  com\\-po\\-si\\-tion word set', 15], ['hyphen  type', 'set  composi-', 'tion set type', 'composition', 'word set']), ('regression: tie breakability', ['ink 10~pt ink b|c hy\\-phen ~set url|path word', 16], ['ink 10 pt ink bc', 'hyphen  set url', 'path word']), ('regression: tie breakability', ['hy\\-phen ~10~pt b|c hy\\-phen ~x  com\\-po\\-si\\-tion', 5], ['hy-', 'phen', ' 10 pt', 'bc hy-', 'phen', ' x', 'compo-', 'si-', 'tion']), ('tie keeps title with name', ['see Dr.~Knuth now', 9], ['see', 'Dr. Knuth', 'now']), ('discretionary taken', ['the com\\-po\\-si\\-tion', 9], ['the compo-', 'sition']), ('control layout', ['b|c ink hy\\-phen url|path type com\\-po\\-si\\-tion', 8], ['bc ink', 'hyphen', 'urlpath', 'type com-', 'position']), ('control layout', ['b|c  a ink  ink com\\-po\\-si\\-tion', 11], ['bc a ink', 'ink composi-', 'tion'])], [('regression: tie breakability', ['x com\\-po\\-si\\-tion ink ~type', 14], ['x composition', 'ink  type']), ('regression: tie breakability', ['Dr.~Knuth  hy\\-phen  com\\-po\\-si\\-tion Dr.~Knuth word ink', 6], ['Dr. Knuth', 'hyphen', 'compo-', 'sition', 'Dr. Knuth', 'word', 'ink']), ('regression: tie breakability', ['hy\\-phen type ~word  hy\\-phen ~x', 14], ['hyphen type', ' word hyphen', ' x']), ('partial-repair probe', ['b|c url|path word  Dr.~Knuth', 9], ['bc url', 'path word', 'Dr. Knuth']), ('double space collapses', ['type  set', 20], ['type set']), ('tie keeps title with name', ['see Dr.~Knuth now', 9], ['see', 'Dr. Knuth', 'now']), ('control layout', ['word com\\-po\\-si\\-tion a', 15], ['word composi-', 'tion a']), ('control layout', ['type set b|c', 6], ['type', 'set bc'])], [('regression: tie breakability', ['type a hy\\-phen com\\-po\\-si\\-tion ~set set ink  type', 8], ['type a', 'hyphen', 'composi-', 'tion', ' set set', 'ink type']), ('regression: tie breakability', ['ink ~10~pt type  com\\-po\\-si\\-tion url|path  a ~x 10~pt b|c', 9], ['ink', ' 10 pt', 'type com-', 'position', 'urlpath a', ' x 10 pt', 'bc']), ('partial-repair probe', ['ink com\\-po\\-si\\-tion Dr.~Knuth', 16], ['ink composition', 'Dr. Knuth']), ('regression: tie breakability', ['x set  type com\\-po\\-si\\-tion a ~ink b|c hy\\-phen url|path', 13], ['x set type', 'composition a', ' ink bc hy-', 'phen urlpath']), ('discretionary taken', ['the com\\-po\\-si\\-tion', 9], ['the compo-', 'sition']), ('tie keeps title with name', ['see Dr.~Knuth now', 9], ['see', 'Dr. Knuth', 'now']), ('control layout', ['a type  com\\-po\\-si\\-tion a', 6], ['a type', 'compo-', 'sition', 'a']), ('control layout', ['com\\-po\\-si\\-tion  hy\\-phen com\\-po\\-si\\-tion ink  b|c a', 10], ['composi-', 'tion hy-', 'phen compo-', 'sition ink', 'bc a'])], [('regression: tie breakability', ['Dr.~Knuth ink 10~pt  set x', 16], ['Dr. Knuth ink', '10 pt set x']), ('regression: tie breakability', ['hy\\-phen type ~x ~x hy\\-phen  10~pt  hy\\-phen 10~pt word', 14], ['hyphen type  x', ' x hyphen', '10 pt hyphen', '10 pt word']), ('partial-repair probe', ['url|path type  10~pt  word', 6], ['url', 'path', 'type', '10 pt', 'word']), ('regression: tie breakability', ['url|path type type com\\-po\\-si\\-tion Dr.~Knuth', 5], ['url', 'path', 'type', 'type', 'compo-', 'si-', 'tion', 'Dr. Knuth']), ('tie keeps title with name', ['see Dr.~Knuth now', 9], ['see', 'Dr. Knuth', 'now']), ('invisible break', ['url|path|x', 5], ['url', 'pathx']), ('control layout', ['com\\-po\\-si\\-tion type hy\\-phen hy\\-phen url|path ink', 13], ['composition', 'type hyphen', 'hyphen url', 'path ink']), ('control layout', ['word  a a set', 7], ['word a', 'a set'])]]
for label, args, expected in fixtures[N - 1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
tie keeps title with name['see', 'Dr.Knuth', 'now']['see', 'Dr. Knuth', 'now']Failed
regression: tie breakability['composition', 'word word url', 'path composi-', 'tion 10pt']['composition', 'word word url', 'path composi-', 'tion 10 pt']Failed
regression: tie breakability['ink x', 'Dr.Knuth', 'ink ink', 'set x', 'word']['ink x', 'Dr. Knuth', 'ink ink', 'set x', 'word']Failed
regression: tie breakability['url', 'path', 'type', 'type', 'compo-', 'si-', 'tion', 'Dr.Knuth']['url', 'path', 'type', 'type', 'compo-', 'si-', 'tion', 'Dr. Knuth']Failed
double space collapses['type set']['type set']Passed
invisible break['url', 'pathx']['url', 'pathx']Passed
control layout['word a', 'a set']['word a', 'a set']Passed
control layout['urlpath compo-', 'sition x a url', 'path a']['urlpath compo-', 'sition x a url', 'path a']Passed

SHA-256 / 6a04bc4cc3d83edb112ee960c2e54076756432e883c590461a1fc5d5abed1a2e

HELD IN THE MEMBER ARCHIVE

The verified repair and its recorded checks are member-only.

This mechanism has 8 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.

Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.

Member access is invitation-based. Sign in with your invited account to inspect the repair.

Sign in to the archive ↗

Verification & scope

A deterministic toy typesetting model with integer widths and a stipulated rule set; it does not claim conformance to any engine. 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.

Observations recorded using Python 3.12.14 at 2026-09-29T14:49:51.549302+00:00.

Case digest / 84f0a4eb737e2c8e6d0ffc13faab30f5ee253c05a82fd636546db24a7035128b