FA-80006 / Typography line breaking / Open access
CJK kinsoku line breaking: hanging punctuation set · case 01
Long vowel marks and closing brackets hang outside the measure.
ROOT CAUSE
The burasage test uses the whole line-start-prohibited set instead of the hanging comma/period set.
VERIFIED REPAIR
Hang only commas and periods.
Unsuccessful approach: Adding closing brackets to the hanging set still lets brackets protrude.
Case contract
Input [text of full-width characters, line length L]. Lines take L characters. If the next character is a hanging comma/period (、。,.) and is not itself followed by a line-start-prohibited character, it hangs on the line (burasage). Otherwise move characters to the next line while the next line would start with a prohibited character (、。,.)」』!?ー and small kana), then while the line would end with an opening bracket; a line keeps at least one character. Return the 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):
text, L = x
NO_START = '、。,.)」』!?ーぁぃぅぇぉっゃゅょ'
NO_END = '(「『'
HANG = '、。,.'
lines = []
pos = 0
n = len(text)
while pos < n:
end = pos + L
if end >= n:
lines.append(text[pos:])
break
if text[end] in NO_START and (end + 1 >= n or text[end + 1] not in NO_START):
end += 1
else:
while end > pos + 1 and text[end] in NO_START:
end -= 1
while end > pos + 1 and text[end - 1] in NO_END:
end -= 1
lines.append(text[pos:end])
pos = end
return lines
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('closing bracket pushes out', ['日本語文」字組版', 4], ['日本語', '文」字組', '版']), ('regression: hanging punctuation set', ['(ーう「語っい」えあえ', 7], ['(ーう「語っ', 'い」えあえ']), ('regression: hanging punctuation set', ['い本いおお()こーお』」きくこおきか', 3], ['い本い', 'おお', '()', 'こー', 'お』」', 'きくこ', 'おきか']), ('regression: hanging punctuation set', ['、あゃく文え、『か、)版」日ゃ(文『か', 3], ['、あゃ', 'く文え、', '『', 'か、)', '版」', '日ゃ', '(文', '『か']), ('period hangs past the measure', ['日本語文。字組版', 4], ['日本語文。', '字組版']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('control layout', ['文字くい「「いおい字こく字っーー、かお本', 6], ['文字くい', '「「いおい字', 'こく字っーー、', 'かお本']), ('control layout', ['』おゃ本版「文おゃ「」。語き', 7], ['』おゃ本版「文', 'おゃ「」。語き'])], [('regression: hanging punctuation set', ['版うゃかくかうけー', 4], ['版うゃか', 'くかう', 'けー']), ('regression: hanging punctuation set', ['文か)うこ「け組ゃ版ゃ字ゃい、本え版', 5], ['文か)うこ', '「け組ゃ', '版ゃ字ゃい、', '本え版']), ('regression: hanging punctuation set', ['文け『い、あ。「日っ」『', 3], ['文け', '『い、', 'あ。', '「', '日っ」', '『']), ('regression: hanging punctuation set', ['「『ゃうくゃ組え(日本う」」」語(ー', 3], ['「『ゃ', 'うくゃ', '組え', '(日本', 'う', '」」」', '語(ー']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('small kana prohibited at line start', ['日本語かっこいい', 4], ['日本語', 'かっこい', 'い']), ('control layout', ['かいあ』え」き』', 8], ['かいあ』え」き』']), ('control layout', ['」う』(文え))ー文、本うく語」え、ー』(』っ', 5], ['」う』(文', 'え))ー文、', '本うく語」', 'え、ー』', '(』っ'])], [('regression: hanging punctuation set', ['「うえ『いーあ』『ー日)字日こく', 5], ['「うえ', '『いーあ』', '『ー日)字', '日こく']), ('regression: hanging punctuation set', ['かかー語ういいえ『。組おくこ、く」', 4], ['かかー語', 'ういいえ', '『。組お', 'くこ、', 'く」']), ('regression: hanging punctuation set', ['ゃ(版)文う字あゃ本語『組」', 3], ['ゃ', '(版)', '文う字', 'あゃ本', '語', '『組」']), ('regression: hanging punctuation set', ['く』』えき字『(っおゃく」く版えあ版文、', 6], ['く』』えき字', '『(っおゃ', 'く」く版えあ', '版文、']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('opening bracket at line end', ['日本語「文字」組版', 4], ['日本語', '「文字」', '組版']), ('control layout', ['文語日(語く文あ', 4], ['文語日', '(語く文', 'あ']), ('control layout', ['(い)」『ーえけかえ字っーき組っ', 7], ['(い)」『ーえ', 'けかえ字っーき', '組っ'])], [('regression: hanging punctuation set', ['「版お語あ「)版」『字いか日本', 6], ['「版お語あ', '「)版」『字', 'いか日本']), ('regression: hanging punctuation set', ['きき組え』うおっ(い', 7], ['きき組え』う', 'おっ(い']), ('regression: hanging punctuation set', ['く文『けいえ「日)語)文』、こっ(か文お「)」', 4], ['く文『け', 'いえ', '「日)', '語)文』、', 'こっ(か', '文お', '「)」']), ('regression: hanging punctuation set', ['ゃ「、お。おっけ)い本文きっ』え版日』)本', 8], ['ゃ「、お。おっ', 'け)い本文きっ』', 'え版日』)本']), ('closing bracket pushes out', ['日本語文」字組版', 4], ['日本語', '文」字組', '版']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('control layout', ['か)ーお組こ『組文ーっ版っっ文。', 3], ['か)ー', 'お組こ', '『組', '文ーっ', '版っっ', '文。']), ('control layout', ['。き日く。文。き。', 8], ['。き日く。文。き。'])], [('regression: hanging punctuation set', ['え本『」お、版あ、くあゃお、かきこ語日」おい(語', 5], ['え本『」お、', '版あ、く', 'あゃお、か', 'きこ語日」', 'おい(語']), ('regression: hanging punctuation set', ['』(『組け字』、き『あ)っ組』か語ゃ', 3], ['』', '(『組', 'け字』、', 'き', '『', 'あ)っ', '組』か', '語ゃ']), ('regression: hanging punctuation set', ['お」本版「きうい)おかきえ字)', 5], ['お」本版', '「きうい)', 'おかきえ', '字)']), ('regression: hanging punctuation set', ['」日あっ日っ)うゃ文(版けうーくこ)「', 6], ['」日あっ', '日っ)うゃ文', '(版けうーく', 'こ)「']), ('closing bracket pushes out', ['日本語文」字組版', 4], ['日本語', '文」字組', '版']), ('small kana prohibited at line start', ['日本語かっこいい', 4], ['日本語', 'かっこい', 'い']), ('control layout', ['き字こ版、)語版い字ゃいお字こ字ゃ', 3], ['き字こ', '版、)', '語版い', '字ゃい', 'お字こ', '字ゃ']), ('control layout', ['え、かけ語か「『いい日う字え', 6], ['え、かけ語か', '「『いい日う', '字え'])]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| closing bracket pushes out | ['日本語文」', '字組版'] | ['日本語', '文」字組', '版'] | Failed |
| regression: hanging punctuation set | ['(ーう「語っい」', 'えあえ'] | ['(ーう「語っ', 'い」えあえ'] | Failed |
| regression: hanging punctuation set | ['い本い', 'おお()', 'こー', 'お』」', 'きくこ', 'おきか'] | ['い本い', 'おお', '()', 'こー', 'お』」', 'きくこ', 'おきか'] | Failed |
| regression: hanging punctuation set | ['、あゃ', 'く文え、', '『か、)', '版」日ゃ', '(文', '『か'] | ['、あゃ', 'く文え、', '『', 'か、)', '版」', '日ゃ', '(文', '『か'] | Failed |
| period hangs past the measure | ['日本語文。', '字組版'] | ['日本語文。', '字組版'] | Passed |
| period followed by bracket cannot hang | ['日本語', '文。」字', '組'] | ['日本語', '文。」字', '組'] | Passed |
| control layout | ['文字くい', '「「いおい字', 'こく字っーー、', 'かお本'] | ['文字くい', '「「いおい字', 'こく字っーー、', 'かお本'] | Passed |
| control layout | ['』おゃ本版「文', 'おゃ「」。語き'] | ['』おゃ本版「文', 'おゃ「」。語き'] | Passed |
SHA-256 / 196a46fcfa74c3ff730304f9fd78b13d38076ae51ce6abdd7938fa5c1e35c66b
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
text, L = x
NO_START = '、。,.)」』!?ーぁぃぅぇぉっゃゅょ'
NO_END = '(「『'
HANG = '、。,.'
lines = []
pos = 0
n = len(text)
while pos < n:
end = pos + L
if end >= n:
lines.append(text[pos:])
break
if text[end] in HANG + ')」' and (end + 1 >= n or text[end + 1] not in NO_START):
end += 1
else:
while end > pos + 1 and text[end] in NO_START:
end -= 1
while end > pos + 1 and text[end - 1] in NO_END:
end -= 1
lines.append(text[pos:end])
pos = end
return lines
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('closing bracket pushes out', ['日本語文」字組版', 4], ['日本語', '文」字組', '版']), ('regression: hanging punctuation set', ['(ーう「語っい」えあえ', 7], ['(ーう「語っ', 'い」えあえ']), ('regression: hanging punctuation set', ['い本いおお()こーお』」きくこおきか', 3], ['い本い', 'おお', '()', 'こー', 'お』」', 'きくこ', 'おきか']), ('regression: hanging punctuation set', ['、あゃく文え、『か、)版」日ゃ(文『か', 3], ['、あゃ', 'く文え、', '『', 'か、)', '版」', '日ゃ', '(文', '『か']), ('period hangs past the measure', ['日本語文。字組版', 4], ['日本語文。', '字組版']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('control layout', ['文字くい「「いおい字こく字っーー、かお本', 6], ['文字くい', '「「いおい字', 'こく字っーー、', 'かお本']), ('control layout', ['』おゃ本版「文おゃ「」。語き', 7], ['』おゃ本版「文', 'おゃ「」。語き'])], [('regression: hanging punctuation set', ['版うゃかくかうけー', 4], ['版うゃか', 'くかう', 'けー']), ('regression: hanging punctuation set', ['文か)うこ「け組ゃ版ゃ字ゃい、本え版', 5], ['文か)うこ', '「け組ゃ', '版ゃ字ゃい、', '本え版']), ('regression: hanging punctuation set', ['文け『い、あ。「日っ」『', 3], ['文け', '『い、', 'あ。', '「', '日っ」', '『']), ('regression: hanging punctuation set', ['「『ゃうくゃ組え(日本う」」」語(ー', 3], ['「『ゃ', 'うくゃ', '組え', '(日本', 'う', '」」」', '語(ー']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('small kana prohibited at line start', ['日本語かっこいい', 4], ['日本語', 'かっこい', 'い']), ('control layout', ['かいあ』え」き』', 8], ['かいあ』え」き』']), ('control layout', ['」う』(文え))ー文、本うく語」え、ー』(』っ', 5], ['」う』(文', 'え))ー文、', '本うく語」', 'え、ー』', '(』っ'])], [('regression: hanging punctuation set', ['「うえ『いーあ』『ー日)字日こく', 5], ['「うえ', '『いーあ』', '『ー日)字', '日こく']), ('regression: hanging punctuation set', ['かかー語ういいえ『。組おくこ、く」', 4], ['かかー語', 'ういいえ', '『。組お', 'くこ、', 'く」']), ('regression: hanging punctuation set', ['ゃ(版)文う字あゃ本語『組」', 3], ['ゃ', '(版)', '文う字', 'あゃ本', '語', '『組」']), ('regression: hanging punctuation set', ['く』』えき字『(っおゃく」く版えあ版文、', 6], ['く』』えき字', '『(っおゃ', 'く」く版えあ', '版文、']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('opening bracket at line end', ['日本語「文字」組版', 4], ['日本語', '「文字」', '組版']), ('control layout', ['文語日(語く文あ', 4], ['文語日', '(語く文', 'あ']), ('control layout', ['(い)」『ーえけかえ字っーき組っ', 7], ['(い)」『ーえ', 'けかえ字っーき', '組っ'])], [('regression: hanging punctuation set', ['「版お語あ「)版」『字いか日本', 6], ['「版お語あ', '「)版」『字', 'いか日本']), ('regression: hanging punctuation set', ['きき組え』うおっ(い', 7], ['きき組え』う', 'おっ(い']), ('regression: hanging punctuation set', ['く文『けいえ「日)語)文』、こっ(か文お「)」', 4], ['く文『け', 'いえ', '「日)', '語)文』、', 'こっ(か', '文お', '「)」']), ('regression: hanging punctuation set', ['ゃ「、お。おっけ)い本文きっ』え版日』)本', 8], ['ゃ「、お。おっ', 'け)い本文きっ』', 'え版日』)本']), ('closing bracket pushes out', ['日本語文」字組版', 4], ['日本語', '文」字組', '版']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('control layout', ['か)ーお組こ『組文ーっ版っっ文。', 3], ['か)ー', 'お組こ', '『組', '文ーっ', '版っっ', '文。']), ('control layout', ['。き日く。文。き。', 8], ['。き日く。文。き。'])], [('regression: hanging punctuation set', ['え本『」お、版あ、くあゃお、かきこ語日」おい(語', 5], ['え本『」お、', '版あ、く', 'あゃお、か', 'きこ語日」', 'おい(語']), ('regression: hanging punctuation set', ['』(『組け字』、き『あ)っ組』か語ゃ', 3], ['』', '(『組', 'け字』、', 'き', '『', 'あ)っ', '組』か', '語ゃ']), ('regression: hanging punctuation set', ['お」本版「きうい)おかきえ字)', 5], ['お」本版', '「きうい)', 'おかきえ', '字)']), ('regression: hanging punctuation set', ['」日あっ日っ)うゃ文(版けうーくこ)「', 6], ['」日あっ', '日っ)うゃ文', '(版けうーく', 'こ)「']), ('closing bracket pushes out', ['日本語文」字組版', 4], ['日本語', '文」字組', '版']), ('small kana prohibited at line start', ['日本語かっこいい', 4], ['日本語', 'かっこい', 'い']), ('control layout', ['き字こ版、)語版い字ゃいお字こ字ゃ', 3], ['き字こ', '版、)', '語版い', '字ゃい', 'お字こ', '字ゃ']), ('control layout', ['え、かけ語か「『いい日う字え', 6], ['え、かけ語か', '「『いい日う', '字え'])]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| closing bracket pushes out | ['日本語文」', '字組版'] | ['日本語', '文」字組', '版'] | Failed |
| regression: hanging punctuation set | ['(ーう「語っい」', 'えあえ'] | ['(ーう「語っ', 'い」えあえ'] | Failed |
| regression: hanging punctuation set | ['い本い', 'おお()', 'こー', 'お』」', 'きくこ', 'おきか'] | ['い本い', 'おお', '()', 'こー', 'お』」', 'きくこ', 'おきか'] | Failed |
| regression: hanging punctuation set | ['、あゃ', 'く文え、', '『か、)', '版」', '日ゃ', '(文', '『か'] | ['、あゃ', 'く文え、', '『', 'か、)', '版」', '日ゃ', '(文', '『か'] | Failed |
| period hangs past the measure | ['日本語文。', '字組版'] | ['日本語文。', '字組版'] | Passed |
| period followed by bracket cannot hang | ['日本語', '文。」字', '組'] | ['日本語', '文。」字', '組'] | Passed |
| control layout | ['文字くい', '「「いおい字', 'こく字っーー、', 'かお本'] | ['文字くい', '「「いおい字', 'こく字っーー、', 'かお本'] | Passed |
| control layout | ['』おゃ本版「文', 'おゃ「」。語き'] | ['』おゃ本版「文', 'おゃ「」。語き'] | Passed |
SHA-256 / a11b9b4a528b1bbab64410217315fbcf97a60494f57fef446ef3b97e6816b235
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
text, L = x
NO_START = '、。,.)」』!?ーぁぃぅぇぉっゃゅょ'
NO_END = '(「『'
HANG = '、。,.'
lines = []
pos = 0
n = len(text)
while pos < n:
end = pos + L
if end >= n:
lines.append(text[pos:])
break
if text[end] in HANG and (end + 1 >= n or text[end + 1] not in NO_START):
end += 1
else:
while end > pos + 1 and text[end] in NO_START:
end -= 1
while end > pos + 1 and text[end - 1] in NO_END:
end -= 1
lines.append(text[pos:end])
pos = end
return lines
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('closing bracket pushes out', ['日本語文」字組版', 4], ['日本語', '文」字組', '版']), ('regression: hanging punctuation set', ['(ーう「語っい」えあえ', 7], ['(ーう「語っ', 'い」えあえ']), ('regression: hanging punctuation set', ['い本いおお()こーお』」きくこおきか', 3], ['い本い', 'おお', '()', 'こー', 'お』」', 'きくこ', 'おきか']), ('regression: hanging punctuation set', ['、あゃく文え、『か、)版」日ゃ(文『か', 3], ['、あゃ', 'く文え、', '『', 'か、)', '版」', '日ゃ', '(文', '『か']), ('period hangs past the measure', ['日本語文。字組版', 4], ['日本語文。', '字組版']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('control layout', ['文字くい「「いおい字こく字っーー、かお本', 6], ['文字くい', '「「いおい字', 'こく字っーー、', 'かお本']), ('control layout', ['』おゃ本版「文おゃ「」。語き', 7], ['』おゃ本版「文', 'おゃ「」。語き'])], [('regression: hanging punctuation set', ['版うゃかくかうけー', 4], ['版うゃか', 'くかう', 'けー']), ('regression: hanging punctuation set', ['文か)うこ「け組ゃ版ゃ字ゃい、本え版', 5], ['文か)うこ', '「け組ゃ', '版ゃ字ゃい、', '本え版']), ('regression: hanging punctuation set', ['文け『い、あ。「日っ」『', 3], ['文け', '『い、', 'あ。', '「', '日っ」', '『']), ('regression: hanging punctuation set', ['「『ゃうくゃ組え(日本う」」」語(ー', 3], ['「『ゃ', 'うくゃ', '組え', '(日本', 'う', '」」」', '語(ー']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('small kana prohibited at line start', ['日本語かっこいい', 4], ['日本語', 'かっこい', 'い']), ('control layout', ['かいあ』え」き』', 8], ['かいあ』え」き』']), ('control layout', ['」う』(文え))ー文、本うく語」え、ー』(』っ', 5], ['」う』(文', 'え))ー文、', '本うく語」', 'え、ー』', '(』っ'])], [('regression: hanging punctuation set', ['「うえ『いーあ』『ー日)字日こく', 5], ['「うえ', '『いーあ』', '『ー日)字', '日こく']), ('regression: hanging punctuation set', ['かかー語ういいえ『。組おくこ、く」', 4], ['かかー語', 'ういいえ', '『。組お', 'くこ、', 'く」']), ('regression: hanging punctuation set', ['ゃ(版)文う字あゃ本語『組」', 3], ['ゃ', '(版)', '文う字', 'あゃ本', '語', '『組」']), ('regression: hanging punctuation set', ['く』』えき字『(っおゃく」く版えあ版文、', 6], ['く』』えき字', '『(っおゃ', 'く」く版えあ', '版文、']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('opening bracket at line end', ['日本語「文字」組版', 4], ['日本語', '「文字」', '組版']), ('control layout', ['文語日(語く文あ', 4], ['文語日', '(語く文', 'あ']), ('control layout', ['(い)」『ーえけかえ字っーき組っ', 7], ['(い)」『ーえ', 'けかえ字っーき', '組っ'])], [('regression: hanging punctuation set', ['「版お語あ「)版」『字いか日本', 6], ['「版お語あ', '「)版」『字', 'いか日本']), ('regression: hanging punctuation set', ['きき組え』うおっ(い', 7], ['きき組え』う', 'おっ(い']), ('regression: hanging punctuation set', ['く文『けいえ「日)語)文』、こっ(か文お「)」', 4], ['く文『け', 'いえ', '「日)', '語)文』、', 'こっ(か', '文お', '「)」']), ('regression: hanging punctuation set', ['ゃ「、お。おっけ)い本文きっ』え版日』)本', 8], ['ゃ「、お。おっ', 'け)い本文きっ』', 'え版日』)本']), ('closing bracket pushes out', ['日本語文」字組版', 4], ['日本語', '文」字組', '版']), ('period followed by bracket cannot hang', ['日本語文。」字組', 4], ['日本語', '文。」字', '組']), ('control layout', ['か)ーお組こ『組文ーっ版っっ文。', 3], ['か)ー', 'お組こ', '『組', '文ーっ', '版っっ', '文。']), ('control layout', ['。き日く。文。き。', 8], ['。き日く。文。き。'])], [('regression: hanging punctuation set', ['え本『」お、版あ、くあゃお、かきこ語日」おい(語', 5], ['え本『」お、', '版あ、く', 'あゃお、か', 'きこ語日」', 'おい(語']), ('regression: hanging punctuation set', ['』(『組け字』、き『あ)っ組』か語ゃ', 3], ['』', '(『組', 'け字』、', 'き', '『', 'あ)っ', '組』か', '語ゃ']), ('regression: hanging punctuation set', ['お」本版「きうい)おかきえ字)', 5], ['お」本版', '「きうい)', 'おかきえ', '字)']), ('regression: hanging punctuation set', ['」日あっ日っ)うゃ文(版けうーくこ)「', 6], ['」日あっ', '日っ)うゃ文', '(版けうーく', 'こ)「']), ('closing bracket pushes out', ['日本語文」字組版', 4], ['日本語', '文」字組', '版']), ('small kana prohibited at line start', ['日本語かっこいい', 4], ['日本語', 'かっこい', 'い']), ('control layout', ['き字こ版、)語版い字ゃいお字こ字ゃ', 3], ['き字こ', '版、)', '語版い', '字ゃい', 'お字こ', '字ゃ']), ('control layout', ['え、かけ語か「『いい日う字え', 6], ['え、かけ語か', '「『いい日う', '字え'])]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| closing bracket pushes out | ['日本語', '文」字組', '版'] | ['日本語', '文」字組', '版'] | Passed |
| regression: hanging punctuation set | ['(ーう「語っ', 'い」えあえ'] | ['(ーう「語っ', 'い」えあえ'] | Passed |
| regression: hanging punctuation set | ['い本い', 'おお', '()', 'こー', 'お』」', 'きくこ', 'おきか'] | ['い本い', 'おお', '()', 'こー', 'お』」', 'きくこ', 'おきか'] | Passed |
| regression: hanging punctuation set | ['、あゃ', 'く文え、', '『', 'か、)', '版」', '日ゃ', '(文', '『か'] | ['、あゃ', 'く文え、', '『', 'か、)', '版」', '日ゃ', '(文', '『か'] | Passed |
| period hangs past the measure | ['日本語文。', '字組版'] | ['日本語文。', '字組版'] | Passed |
| period followed by bracket cannot hang | ['日本語', '文。」字', '組'] | ['日本語', '文。」字', '組'] | Passed |
| control layout | ['文字くい', '「「いおい字', 'こく字っーー、', 'かお本'] | ['文字くい', '「「いおい字', 'こく字っーー、', 'かお本'] | Passed |
| control layout | ['』おゃ本版「文', 'おゃ「」。語き'] | ['』おゃ本版「文', 'おゃ「」。語き'] | Passed |
SHA-256 / 840136330e48d3376c9295ffbfe51f389d83f2ecada3c08f6bcd44eb2ac3a8b1
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:49.700730+00:00.
Case digest / 74752778644047801946ebee4c3010ec02783567f2225b230f0fe2d1c5738fc0