Skip to content

compiler: carry rubber lengths on Block::VSpace (GH-VSKIP-GLUE-STRETCH slice 1) - #606

Merged
GoKubar merged 1 commit into
mainfrom
agent/daniel-muse-lead/vskip-glue
Sep 15, 2026
Merged

GoKubar merged 1 commit into
mainfrom
agent/daniel-muse-lead/vskip-glue

Conversation

@d-q222

@d-q222 d-q222 commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Scope

Compiler-only slice 1 of GH-VSKIP-GLUE-STRETCH, per daniel-parent's split-PR requirement (the render-pipeline half is a separate follow-up draft, since it builds against the frozen vendor/compiler pin).

Block::VSpace (crates/compiler/src/parser.rs) now carries stretch_pt/shrink_pt alongside pt; anything that doesn't specify rubber gets 0.0/0.0 (matching real TeX — a bare \vspace{1in} has no rubber length). \bigskip/\medskip/\smallskip now emit real LaTeX's glue: (12, 4, 4), (6, 2, 2), (3, 1, 1) pt. New parse_glue_pt_at parses TeX glue syntax for \vspace: a natural dimension followed by optional plus <dimen>/minus <dimen> in either order; repeated keywords, trailing garbage, and unrecognised components are rejected. Finite dimensions only — infinite (fil/fill/filll) stretch is an explicit non-goal, rejected with the existing \vspace requires a recognised dimension diagnostic.

The stale "this layout model has no rubber lengths" comment on the skip constants was corrected — the compiler's own layout.rs still applies only the natural length (no page-stretch model there); threading the rubber into actual page-break glue is the render-pipeline follow-up's job.

Cross-crate check: crates/render-pipeline/Cargo.toml depends on the compiler via the frozen vendor/compiler copy (still the old flat VSpace shape), and this diff touches nothing under crates/render-pipeline/, so no break occurs in the real build — confirmed via a clean cargo check in render-pipeline, bridge, and paragraph-layout (the two crates besides render-pipeline that consume the live ../compiler; neither matches on VSpace).

No crates/render-pipeline/ touch at all (including vendor/), per daniel-parent's split-PR instruction.

Overlap check

coord.py claims — no other claim. Checked against #568/#583/#504 (page/paragraph-control node types) and the amsthm Sep stretch/shrink precedent — no overlap, different node types.

Test results

Focused (crates/compiler):

test parser::tests::skips_carry_their_plus_minus_rubber_lengths ... ok
test parser::tests::vspace_reads_plus_and_minus_in_either_order ... ok
test parser::tests::bare_vspace_has_no_rubber_length ... ok
test result: ok. 3 passed; 0 failed

Independent mutation check (supervisor-run, fresh CARGO_TARGET_DIR): zeroed all six skip stretch/shrink constants → skips_carry_their_plus_minus_rubber_lengths FAILED (left: (12.0, 0.0, 0.0), right: (12.0, 4.0, 4.0)), the other two unaffected as expected (they don't depend on the skip constants); restored → all 3 pass.

Full cargo test in crates/compiler (supervisor-run independently, fresh CARGO_TARGET_DIR): every suite ok, 0 failures.

Entry-point repro (flashtex_compiler::protocol::handle_line, temporary test file, deleted after; independently re-run by the supervisor with the same result): a\bigskip b and a\vspace{1em plus 1pt minus 1pt} b both return "diagnostics":[], "status":"ok".

Not done

Slice 2 (separate render-pipeline draft PR, to be marked "needs re-pin past this PR"): thread stretch/shrink only through Block::VSpacestyle::Skip in adapter.rs, per daniel-parent's explicit scope limit — not touching pagebuild.rs or typeset/floatpage.rs, which are daniel-parent's own stacked drafts #569/#584/#599. Also filed as future work: infinite (fil/fill/filll) stretch in parse_glue_pt_at (currently rejected), and consuming the recorded rubber in the compiler's own layout.rs page model if one is ever added.

🤖 Generated with Claude Code

…H slice 1)

Block::VSpace gains stretch_pt/shrink_pt alongside pt. bigskip/medskip/
smallskip now carry real LaTeX's glue (12/4/4, 6/2/2, 3/1/1 pt), and
\vspace{<dimen> plus <dimen> minus <dimen>} parses the optional
plus/minus components in either order via parse_glue_pt_at (finite
dimensions only; fil/fill/filll rejected). A bare dimension keeps
0.0/0.0. The compiler's own layout still sets only the natural length;
threading the rubber into page breaking is the render-pipeline slice.

Implementation-Agent: muse-spark-1.3-contributor
d-q222 added a commit that referenced this pull request Sep 15, 2026
…KIP-GLUE-STRETCH slice 2)

Adapter only: accumulate CBlock::VSpace stretch_pt/shrink_pt through
pending_vspace into Unit/Block::Paragraph vspace_flex, alongside the
existing natural sum; the gap re-read now parses plus/minus glue into
the existing style::Skip. Stops at the flat Block shapes (Rule,
Heading, Picture, LongTable) and their rigid typeset consumption.

Draft: needs vendor/compiler re-pin past #606 for the new fields.

Implementation-Agent: muse-spark-1.3-contributor
@d-q222
d-q222 force-pushed the agent/daniel-muse-lead/vskip-glue branch from 6e6f4a9 to 3a09898 Compare September 15, 2026 10:05
@GoKubar
GoKubar merged commit 5373e22 into main Sep 15, 2026
31 of 42 checks passed
GoKubar added a commit that referenced this pull request Sep 15, 2026
…in's VSpace pattern break

Generated artefacts (docs/user/compiler.md, supported/supported-latex.json,
coverage.md, Mac bundled copy) conflicted after main's inventory grew; took
main's copies and regenerated so both sides appear, sync --check clean.

Also carries a one-line semantic merge fix main itself needs: #606 added
stretch_pt/shrink_pt to Block::VSpace but left the pattern in
tests/kernel_untested_b.rs:251 as 'Block::VSpace { pt }', which fails
E0027 on current main; widened to 'Block::VSpace { pt, .. }'.

Implementation-Agent: fable-rebase-a
Commit-Executor: fable-rebase-a (direct; Cursor usage limit)
GoKubar added a commit that referenced this pull request Sep 15, 2026
Clean merge (#606 rubber lengths, #576 kern spans, #499, #624); no conflicts.

Implementation-Agent: fable-rebase-c
Commit-Executor: fable-rebase-c (direct; Cursor usage limit)
GoKubar added a commit that referenced this pull request Sep 15, 2026
…fields

The #568 squash and this branch both carried
pagebreak_inside_a_paragraph_ends_the_page_after_its_line_not_the_paragraph
(byte-identical); kept one. kernel_untested_b.rs's Block::VSpace pattern now
ignores #606's stretch_pt/shrink_pt (it asserts only pt) - note main's tip has
the same flat pattern and needs the same fix.

Implementation-Agent: fable-rebase-c
Commit-Executor: fable-rebase-c (direct; Cursor usage limit)
GoKubar added a commit that referenced this pull request Sep 15, 2026
 glue)

Conflict: crates/compiler/src/parser.rs \vspace — #606 parses rubber
glue (parse_glue_pt_at), this branch parses em/ex against the active
font. Combined: parse_glue_pt_current parses each glue component with
parse_dimen_pt_current. Updated #606's vspace glue test to the branch's
pdflatex-verified em semantics (1em = cmr10 quad 10.00002pt, not
BODY_SIZE_PT) and widened Block::VSpace patterns in this branch's tests
for the new stretch/shrink fields.

Implementation-Agent: fable-rebase-d
Commit-Executor: fable-rebase-d (direct; Cursor usage limit)
GoKubar added a commit that referenced this pull request Sep 15, 2026
…NMENTS; regenerate docs; fix main's VSpace pattern break

crates/compiler/src/vocabulary.rs conflicted because this branch removed
dcases/rcases (now implemented here) while main removed samepage/sloppypar
(implemented by #568); kept both removals (the intersection).
docs/user/compiler.md and the supported artefacts were regenerated via
render_supported_latex.sh; Mac bundled copy sync --check clean.

Also carries the one-line semantic fix current main needs: #606 added
stretch_pt/shrink_pt to Block::VSpace but tests/kernel_untested_b.rs:251
still matched 'Block::VSpace { pt }' (E0027); widened to '{ pt, .. }'.

Implementation-Agent: fable-rebase-a
Commit-Executor: fable-rebase-a (direct; Cursor usage limit)
GoKubar added a commit that referenced this pull request Sep 15, 2026
…in's VSpace pattern break

Generated artefacts (docs/user/compiler.md, supported/supported-latex.json,
coverage.md, Mac bundled copy) conflicted after main's inventory grew; took
main's copies and regenerated so \underbar and main's additions both
appear, sync --check clean. Also the one-line fix current main needs:
tests/kernel_untested_b.rs:251 'Block::VSpace { pt }' fails E0027 after
#606 added stretch_pt/shrink_pt; widened to '{ pt, .. }'.

Implementation-Agent: fable-rebase-a
Commit-Executor: fable-rebase-a (direct; Cursor usage limit)
GoKubar added a commit that referenced this pull request Sep 15, 2026
…NMENTS; regenerate docs; fix main's VSpace pattern break

crates/compiler/src/vocabulary.rs conflicted because this branch removed
'frame' (implemented here) while main removed samepage/sloppypar
(implemented by #568); kept both removals. Regenerated the supported-latex
artefacts via render_supported_latex.sh; Mac bundled copy sync --check
clean. Also the one-line fix current main needs:
tests/kernel_untested_b.rs:251 'Block::VSpace { pt }' fails E0027 after
#606 added stretch_pt/shrink_pt; widened to '{ pt, .. }'.

Implementation-Agent: fable-rebase-a
Commit-Executor: fable-rebase-a (direct; Cursor usage limit)
GoKubar added a commit that referenced this pull request Sep 15, 2026
Clean textual merge of current main; regenerated supported-latex artefacts
(no drift, sync --check clean). Carries the one-line semantic fix current
main needs: #606 added stretch_pt/shrink_pt to Block::VSpace but
tests/kernel_untested_b.rs:251 still matched 'Block::VSpace { pt }'
(E0027 on main itself); widened to '{ pt, .. }'.

Implementation-Agent: fable-rebase-a
Commit-Executor: fable-rebase-a (direct; Cursor usage limit)
GoKubar added a commit that referenced this pull request Sep 15, 2026
…fields (#636)

#606 gave `Block::VSpace` `stretch_pt` and `shrink_pt`. `tests/kernel_untested_b.rs`
still destructured the two-field form, so that test target stopped compiling the
moment #606 landed:

  error[E0027]: pattern does not mention fields `stretch_pt`, `shrink_pt`

main has been in that state since #606 merged. `{ pt, .. }` restores it.

Worth noting how it hid: a target that fails to COMPILE emits no `test result:`
line at all, so a summary that sums those lines reports a clean run while
silently omitting the whole target. The count goes 762 -> 776 with this fix --
those 14 tests were not running.

Implementation-Agent: orchestrator-astra
Commit-Executor: orchestrator-astra (direct; Cursor usage limit)
GoKubar added a commit that referenced this pull request Sep 15, 2026
…#64; stacked on #568) (#583)

* compiler: page and paragraph control commands as penalty, discretionary and parameter nodes (#64)

What changed:
- New AST: Inline::Penalty {value, unskip} (\penalty, \nobreak, \allowbreak,
  \linebreak[n], \nolinebreak[n]), Inline::PagePenalty (\pagebreak[n] and
  \nopagebreak[n] inside a paragraph: \vadjust, the paragraph is not broken),
  Inline::Discretionary (\-, \discretionary{}{}{}), Block::Penalty {value, fil}
  (vertical-mode \penalty/\nobreak, \pagebreak[n<4], \nopagebreak[n],
  \goodbreak, \filbreak). Values are latex.ltx's \@getpen 0/51/151/301/10000.
- Parsed::parameters: \tolerance, \pretolerance, \looseness, \widowpenalty,
  \clubpenalty, \interlinepenalty, \emergencystretch (also \setlength),
  \sloppy, \fussy, sloppypar, \samepage (and its environment), \raggedbottom,
  \flushbottom, \enlargethispage(*), each with the group end that restores it.
  Parsed::hyphenation: \hyphenation words.
- \- is a command in the lexer and the expansion pass, so it is never typeset
  as a hyphen; \penalty's number and parameter values no longer leak as text.
- Core 14 layout: forced penalties break lines/pages; \pagebreak in a paragraph
  ends the page after its line (FlowState carries the pending eject).
- Inventory, vocabulary and generated supported-LaTeX artefacts regenerated.

What was run:
- cargo test (crates/compiler): 573 passed; 0 failed before the inventory move,
  then --lib: test result: ok. 347 passed; 0 failed
- --test supported_latex: test result: ok. 8 passed; 0 failed
- --test hw1_preamble/hw2_gate/corpus_gate/pinned_fixtures/incremental_json_identity/
  local_recovery/preamble_page_commands/line_break_skip: all ok
- pdflatex \showlists / \showthe oracle for every value (in the PR body).

Next step: render-pipeline consumes the nodes after vendor/compiler is re-pinned.

Implementation-Agent: claude-opus-5 subagent of daniel-parent
Commit-Executor: daniel-parent subagent
Claude-Session: https://claude.ai/code/session_012c9XLkHjePPGBuarrmE2mz

* compiler: penalty nodes' spans cover their number and priority bracket (#64)

What changed:
- Inline::Penalty/PagePenalty spans now include `[n]` and `\penalty`'s number,
  so a consumer reading the source after a node starts past them (the
  pipeline decides whether LaTeX ate the blanks after the command from this).

What was run:
- cargo test --lib (crates/compiler): test result: ok. 347 passed; 0 failed

Next step: open the compiler PR and the render-pipeline draft.

Implementation-Agent: claude-opus-5 subagent of daniel-parent
Commit-Executor: daniel-parent subagent
Claude-Session: https://claude.ai/code/session_012c9XLkHjePPGBuarrmE2mz

* compiler: \include clears the page, vertical \pagebreak is a bare penalty, \nobreakdash (#64)

What changed:
- \include{file} emits latex.ltx \@include's \clearpage before the file and
  after it (expansion.rs: the closing one precedes the first token read once
  the engine has left the file). A file \includeonly skips keeps only the
  first; a missing file keeps both. \input is unchanged.
- A vertical-mode \pagebreak (priority 4) is Block::Penalty { value: -10000 }
  instead of Block::PageBreak: latex.ltx has no \vfil before it, unlike
  \newpage, so a \flushbottom page it ends is stretched.
- amsmath \nobreakdash: the following -, -- or --- as text, then
  Inline::Penalty 10000 (\setboxz@h{--\nobreak}\unhbox\z@). Supported-LaTeX
  artefacts regenerated.

What was run:
- cargo test --lib: test result: ok. 349 passed; 0 failed
- cargo test --no-fail-fast (whole crate): every target ok after
  render_supported_latex.sh (supported_latex: ok. 8 passed; includeonly: ok. 10 passed)
- pdflatex probes with the render pipeline (scratch export): include 3/3 pages,
  include-para, include-two 4, include-last 2, includeonly-excluded 2: all match.

Next step: render-pipeline draft consumes the bare penalty (flushbottom) and
\nobreakdash's hyphenation; vendor re-pin past #568 and this PR.

Implementation-Agent: claude-opus-5 subagent of daniel-parent
Commit-Executor: daniel-parent subagent
Claude-Session: https://claude.ai/code/session_012c9XLkHjePPGBuarrmE2mz

* compiler: leave \include's page breaks to #578 (#64)

What changed:
- Reverted the \include \clearpage emission in expansion.rs and the
  includeonly test changes from the previous commit: #578 (render pipeline,
  agent/daniel-parent/include-float-numbering) already clears the page before
  and after an \include'd file, and the coordinator moved that item there.
  The vertical \pagebreak penalty and \nobreakdash stay.

What was run:
- cargo test --lib: test result: ok. 349 passed; 0 failed
- cargo test --test includeonly: test result: ok. 9 passed; 0 failed
- cargo test --test supported_latex: test result: ok. 8 passed; 0 failed

Next step: render-pipeline draft for \pagebreak under \flushbottom,
\nobreakdash hyphenation, \enlargethispage and the \clearpage float flush.

Implementation-Agent: claude-opus-5 subagent of daniel-parent
Commit-Executor: daniel-parent subagent
Claude-Session: https://claude.ai/code/session_012c9XLkHjePPGBuarrmE2mz

* Post-merge fixups: dedupe squashed test, VSpace pattern gains rubber fields

The #568 squash and this branch both carried
pagebreak_inside_a_paragraph_ends_the_page_after_its_line_not_the_paragraph
(byte-identical); kept one. kernel_untested_b.rs's Block::VSpace pattern now
ignores #606's stretch_pt/shrink_pt (it asserts only pt) - note main's tip has
the same flat pattern and needs the same fix.

Implementation-Agent: fable-rebase-c
Commit-Executor: fable-rebase-c (direct; Cursor usage limit)

---------

Co-authored-by: GoKubar <kabirgoyal@icloud.com>
@GoKubar
GoKubar deleted the agent/daniel-muse-lead/vskip-glue branch September 16, 2026 04:16
d-q222 added a commit that referenced this pull request Sep 16, 2026
…KIP-GLUE-STRETCH slice 2)

Adapter only: accumulate CBlock::VSpace stretch_pt/shrink_pt through
pending_vspace into Unit/Block::Paragraph vspace_flex, alongside the
existing natural sum; the gap re-read now parses plus/minus glue into
the existing style::Skip. Stops at the flat Block shapes (Rule,
Heading, Picture, LongTable) and their rigid typeset consumption.

Draft: needs vendor/compiler re-pin past #606 for the new fields.

Implementation-Agent: muse-spark-1.3-contributor
d-q222 pushed a commit that referenced this pull request Sep 16, 2026
The merge with main dropped \addvspace from the outer dispatch list
that routes bigskip/medskip/vspace/etc. into vertical_command (main
had reorganized this list independently), so \addvspace fell through
to the generic unsupported() catch-all and tripped its own
debug_assert(!BUILT_INS.contains(name)) sanity check. Add it back
alongside vspace. Also update Block::VSpace construction/pattern
sites for the stretch_pt/shrink_pt fields GH-VSKIP-GLUE-STRETCH (#606)
added to main during the wind-down.

Implementation-Agent: muse-spark-1.3-contributor
d-q222 added a commit that referenced this pull request Sep 17, 2026
…KIP-GLUE-STRETCH slice 2)

Adapter only: accumulate CBlock::VSpace stretch_pt/shrink_pt through
pending_vspace into Unit/Block::Paragraph vspace_flex, alongside the
existing natural sum; the gap re-read now parses plus/minus glue into
the existing style::Skip. Stops at the flat Block shapes (Rule,
Heading, Picture, LongTable) and their rigid typeset consumption.

Draft: needs vendor/compiler re-pin past #606 for the new fields.

Implementation-Agent: muse-spark-1.3-contributor
ItsAkilesh pushed a commit to ItsAkilesh/flashtex that referenced this pull request Sep 18, 2026
What changed:
- `crates/render-pipeline/Cargo.toml` declares a new off-by-default feature
  `compiler-node-surface`. It carries no behaviour of its own: every arm it
  adds is the inert answer the pipeline already gave for a compiler node the
  current pin (`c95977d6`) cannot produce.
- The pipeline's exhaustive matches and node constructors now cover main's
  compiler surface behind that feature: `parser::Block::Penalty`/`Tabbing`,
  `parser::Inline::ThePage`/`PageNumbering`/`TabStop`/`TabJump`/`Marginpar`/
  `Penalty`/`PagePenalty`/`Discretionary`, `VSpace`/`HSpace` glue components,
  `math::Nucleus::TextRun`/`SideSet`/`Lap` and `math::Accent::Mathring`
  (compiler flash-tex#549, flash-tex#551, flash-tex#555, flash-tex#568, flash-tex#581, flash-tex#583, flash-tex#587, flash-tex#606, flash-tex#616).
  `adapter::vspace_block` is a new cfg'd constructor beside the existing
  `line_break_inline`; the one open-coded `Inline::LineBreak { .. }` left in
  the `\opening` lowering now goes through `line_break_inline` too.
- `tabbing` is lowered to flush-left paragraphs with one `unsupported_block`
  limitation, the way `LetterBlock` is, so no row is dropped by the re-pin.
- `docs/integration/repin-runbook.md`: the exact re-pin commands, the three
  vendor directories that must move (`compiler`, `tex-expansion`, and a new
  `bibliography`), the lockfile and `#[ignore]` edits `--locked` CI needs, the
  measured test deltas and the PRs the pin unblocks.

No file under `vendor/` is touched: the vendor swap used to measure all of
this was scratch-only and reverted. `git diff --stat origin/main...HEAD`
contains zero `vendor/` paths.

What was run:
Whole `crates/render-pipeline` suite, CARGO_BUILD_JOBS=4, --no-fail-fast:
  origin/main, pinned vendor, feature off:   469 passed, 13 failed
  this branch, pinned vendor, feature off:   469 passed, 13 failed (same 13)
  this branch, vendor re-pinned, feature on: 485 passed, 0 failed
The 13 red-on-main tests (letter_class_geometry x5, frame_env, underline_sout
x4, uline x2, xcolor_oracle) all pass after the re-pin.
Two re-pin-gated #[ignore]s also pass against the re-pinned vendor:
  test frame_draws_a_rule_border_around_its_content ... ok
  test coloneqq_decomposes_like_mathtools ... ok
crates/flashtex-cli against the same re-pinned vendor:
  test result: ok. 58 passed; 0 failed
cargo check --all-targets on this branch at the current pin: 0 errors.

Next step:
The integration lane applies docs/integration/repin-runbook.md section 3 --
swap the three vendor trees, move `compiler-node-surface` (and
`linebreak-skip`) into `default`, refresh both Cargo.locks, drop the two
`#[ignore]`s, update vendor/VENDORING.md.

Implementation-Agent: claude-opus-5 subagent of daniel-parent
Commit-Executor: daniel-parent subagent
Claude-Session: https://claude.ai/code/session_012c9XLkHjePPGBuarrmE2mz
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants