Skip to content

Settle the seam a warichu's sublines meet at, and give a furawake its two ends - #28

Merged
P4suta merged 3 commits into
mainfrom
fix/in-block-boundaries-and-the-far-edge
Aug 24, 2026
Merged

Settle the seam a warichu's sublines meet at, and give a furawake its two ends#28
P4suta merged 3 commits into
mainfrom
fix/in-block-boundaries-and-the-far-edge

Conversation

@P4suta

@P4suta P4suta commented Aug 24, 2026

Copy link
Copy Markdown
Owner

Two coordinates a block hides from the line, one at each end of the reading
docs/decisions/stacked-structure-geometry.md
publishes. The first is the sixth constructs variant PR #25 deliberately withheld,
because it was the first shape two of the three engines answered differently from each
other
; the second is the furawake half of #24, which needed a structure to be able to say
what it is at each of its two ends.

Fixes #26
Fixes #27

The seam, and which engine was right (#26)

Where a note's two sublines meet, Table 1 states an amount between the character that ends
the first and the character that begins the second. crates/jlreq/src/pipeline.rs offered
that boundary to §3.8.3's ladder; engines/ocaml/lib/pipeline.ml and
engines/racket/compose.rkt did not. Nothing had adjudicated it.

The decision already settles it, and it settles it against the ladder. The published
reading is not "Table 1 states nothing here" — Table 1 states plenty. It is that the line
was not composed from the boundary
: the character that ends a subline reports its body
alone and the character after it begins its own row at that row's origin, so the amount at
the seam stands nowhere in any engine's answer. The reading's own sentence for the block's
interior — "a boundary the line was not composed from is not a boundary the line can
adjust, which is why the two of them read the line's geometry and stop at the block" — is
about which object a boundary belongs to, and the seam belongs to the same object the rest
of the block's interior does. §3.8.3 adjusts the spacing of a line; there was no spacing of
the line there to adjust.

The measurement is what makes it more than a preference. A ladder handed a site that cannot
pay divides the arrears over it anyway and recovers only the other share:

※〈〉あ※  half-em note, warichu [3,12), 250 units to give back
             measure   needed   given back   inline_extent
before          3000      250          125   3125  layout.overfull
after           3000      250          250   3000  (none)

An engine that hands back half of what it needs and then reports the line overfull is
contradicting its own diagnostic, which is what tipped this from "two readings" to "one
reading and one defect". The expansion ladder already stopped at the block; the reduction
ladder now asks the same question.

The alternative is publishable and the decision says so: a revision of §3.8.3 that said
what a boundary of a line is, or an Appendix D note saying whether a stage may be offered
a coordinate no amount stands at, would settle it either way. Today the only argument is
the one above, and it is this project's.

A furawake's two ends (#27)

compose.rkt gathers a furawake into one item of the line where a warichu's members stay
items of their own, and two things followed. A column was measured from bare cluster
advances, so a member before a Table 1 amount inside its own column reported 1000 while the
engine placed the next member 1000 units on and charged the line 1500 — the defect #24
fixed for a warichu, at the other structure the same reading is addressed to. And the one
item carried the class of its first cluster, so the boundary after the block was
answered at the wrong end of it, and the amount missing from the column reappeared beside
the structure.

The two are equal and opposite wherever the two amounts are equal, which is why the shape
had to be swept over all 529 class pairs before it could be seen at all:

※〉〈日※ furawake [3,12), two columns, one-fifth-em gap
before  (4500/2200) [... 1000:-600+1000 2000:-600+1000 ...]  ← cancels
after   (4500/2200) [... 1000:-600+1500 2500:-600+1000 ...]  ← Rust and OCaml, byte for byte

※・・日※ the same shape, 500 units inside the column against 250 after the block
before  (4500/2200)   after  (4750/2200)                     ← does not cancel

Both halves had to move together. item now carries a trailing edge — the occurrence a
boundary after the item is read against, which is the item itself for everything one
character wide — and every reading of the before side of a boundary asks for it. A
tate-chu-yoko run carries none: §3.2.5 makes it cl-30 at both of its edges however many
characters it holds.

What changed

  • crates/jlreq/src/pipeline.rs: reduction_sites skips a boundary strictly inside a
    warichu or a furawake, the way it already skipped one inside a jidori and the way
    boundary_expansion_site already skipped all of them. Public API unchanged.
  • crates/jlreq/tests/public_api.rs: the seam at three measures — the natural width, where
    the amount stands nowhere; the width that needs half of it; and the width that needs all
    of it. It fails on the previous engine at 3,125 against 3,000.
  • engines/racket/compose.rkt and spacing.rkt: a furawake's columns are laid out from
    the advances the structure was composed from, and the block carries the character its far
    boundary is read against. across in furawake-item, computed and read by nobody since
    the block's depth moved to block-room, goes with them.
  • engines/racket/tests/test-compose.rkt: three cases computed by hand from §3.7.2 and
    Table 1 — the in-column amount and the advance that reaches it, the pair whose two errors
    do not cancel, and the block's own two extents, which neither reading moves. Two of the
    three fail on the previous engine.
  • engines/ocaml/probe/census.ml: warichu-pair-inside-reduced, furawake-pair-inside and
    its vertical mirror. Against the previous engines the constructs census reports 15
    differing responses for the Rust one and 434 for the Racket one; against these, none.
  • docs/decisions/stacked-structure-geometry.md publishes both readings, why each follows
    from sentences already there, and what a revision would have to say to settle either one
    the other way. engines/ocaml/README.md's census counts were three pull requests stale
    and are now current.

Measurements

Census Requests Rust vs OCaml Rust vs Racket OCaml vs Racket
spacing 2,116 0 0 0
break 2,116 0 0 0
reduction 3,174 0 0 0
expansion 3,174 0 0 0
vertical 5,290 0 0 0
tate-chu-yoko 4,761 0 0 0
ruby 37,030 0 0 0
constructs 20,102 0 0 0
tabs 31,211 0 0 0
widow 13,225 0 0 0
total 122,199 0 0 0

The Rust sample engine, just conform-ocaml and just conform-racket each answer all
eighty-nine built-in cases at exit 0; raco test engines/racket/tests is 10,196 passing;
just check, just design and just ci are green locally.

No known disagreement between the three engines is left open.

🤖 Generated with Claude Code

https://claude.ai/code/session_01N8KNy2ejPqy81P2hVcRUjs

P4suta and others added 3 commits August 24, 2026 23:56
`reduction_sites` offered the ladder every interior boundary of a stacked
structure. Two characters of one subline are one such boundary, and so is
the SEAM where a note's two sublines meet -- the last character of the
first and the first character of the second are adjacent in the text, so
Table 1 states an amount between them like anywhere else.

That amount stands nowhere. The character that ends a subline reports its
body alone and the character that begins the next one begins it at its own
row's origin, so the line was never composed from the seam and there is
nothing there to give back. Offering it to the ladder divides the line's
arrears over a site that cannot pay them: `※〈〉あ※` at a three-em measure
needs 250 units back, has one boundary on the line that can give them and
one seam that cannot, halves the debt between the two, recovers 125 and
reports `layout.overfull` about a line it could have made fit.

The expansion ladder already stopped at the block, through the same
construct-interior test `boundary_expansion_site` runs; the reduction
ladder now asks the same question of a warichu and a furawake. Neither
public API nor any other engine changed, and no other census coordinate
moves: this is the only shape where a boundary Table 1 names is not a
boundary the line was composed from.

Fixes #26

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N8KNy2ejPqy81P2hVcRUjs
… edge

`compose.rkt` gathers a §3.7.2 furawake into ONE item of the line, where a
§3.4.2 warichu's members stay items of their own. Two things followed from
that and both were wrong.

A column was measured from bare cluster advances, so a member standing
before a Table 1 amount inside its own column -- `cl-02` then `cl-01`, half
of the member's own em -- reported 1000 while the same engine placed the
next member 1000 units on and charged the line 1500 for the step. That is
the defect #24 fixed for a warichu, at the other structure the same reading
is addressed to: a column is ordinary text of the structure, so a member's
advance is its body plus the amount after it inside its row, and the member
that ends a row reports its body alone.

And the one item carried the class of its FIRST cluster, so the boundary
AFTER the block was answered at the wrong end of it. A structure has two
edges and they are two different characters: the amount before the block is
Table 1's answer at the block's first character and the amount after it the
answer at its last. The `item` struct now carries a `trailing` edge -- the
occurrence a boundary after the item is read against, which is the item
itself for anything one character wide -- and every reading of the before
side of a boundary asks for it. A tate-chu-yoko run carries none: §3.2.5
makes it cl-30 at both of its edges however many characters it holds.

The two errors are equal and opposite wherever the two amounts are, which
is why `※〉〈日※` comes out 4500 wide either way and `※・・日※` does not.
Both halves had to move together. Neither public API nor any other engine
changed, and `across` in `furawake-item` -- computed and read by nobody
since the block's depth moved to `block-room` -- goes with them.

Fixes #27

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N8KNy2ejPqy81P2hVcRUjs
…t every class pair

`engines/ocaml/probe/census.ml` gains three `constructs` variants. The
first is the sixth shape PR #25 deliberately withheld:
`warichu-pair-inside-reduced` stands the pair under test inside a note on a
line that has to give space back, which is where the two answers to
"does §3.8.3's ladder reach the seam" come apart in the line's own width.
The other two are `furawake-pair-inside` and its vertical mirror, which
stand the pair inside one of a furawake's columns and put an ordinary
character in the other, so one request asks both what Table 1 does inside a
column and which of the block's characters the boundary after it is read
against.

The `constructs` census is 20,102 requests and all ten are at zero
differences across the three engines over 122,199. Against the previous
engines the same census reports 15 differing responses for the Rust one and
434 for the Racket one.

`docs/decisions/stacked-structure-geometry.md` states both readings, why
they follow from the sentences already published there rather than from
anything new, and what a revision would have to say to settle either one
the other way. The seam is the only boundary of a block that is neither
strictly inside a subline nor at the block's edge, which is how an engine
can reach it by asking Table 1 about two adjacent characters without asking
which object they are adjacent on.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N8KNy2ejPqy81P2hVcRUjs
@P4suta
P4suta enabled auto-merge (squash) August 24, 2026 14:59
@P4suta
P4suta merged commit 31a92cf into main Aug 24, 2026
25 checks passed
@P4suta
P4suta deleted the fix/in-block-boundaries-and-the-far-edge branch August 24, 2026 15:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant