Skip to main content

max / quasi

Read every branch, loop and arm off the marks, and delete the comparisons The containers rustc named now carry marks, so the mechanism reaches the whole corpus: Table (columns, then rows, then the pager), Field's options, Node's five list-holding shapes, and Slot and Row from the first pass. The renderers record where they wrote each member, and where assembly belongs to makeover-webview -- a row's cells, a chart's bars -- it is asked rather than searched, through cells_html_placed and chart_html_placed. The whole workspace is green on this. quasi-bench's residual tests are the real check: they compile MNW-shaped screens and compare the filled residual against the renderer's own output, and they pass with nothing diffing anything. Two things follow that are worth stating plainly. A guard no longer changes what the twin draws. It places its members and marks them, so one render answers every guard, and the test that asserted the opposite now asserts this. An arm may hold loops and guards of its own. Each arm is compiled from its own render, where its own marks were recorded, so "the arms are flat" is gone rather than worked around. PARKED, precisely: a guarded SETTING. A mark covers a run of members and a setting varies markup inside the member its own statement produces. Two shapes hide under that -- placing settings (figure, bar, more, back, forward, jumping), which are members in all but name and want counting in their container's index space, and settling settings (chosen, here), which want two arms over the member they settle. Four bench shapes use one and are unstaged until it exists, behind the guarded-settings-stage feature so the shape and its residual tests come back together. symbolic's PLACED list is deleted: the question it answered cannot be asked of a mark.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session
https://claude.ai/code/session_01P8ostB2UmZJGj5WjSHRSot
Author: Max Johnson <me@maxj.phd> · 2026-09-08 19:47 UTC
Signed with PGP, not checked
Commit: 2599059a777aa5ae6014259ca5440ffe0b2931e6
Parent: 6140a79
23 files changed, +457 insertions, -116 deletions
M Cargo.lock +8 -8
@@ -6312,14 +6312,6 @@
6312 6312 "winnow 1.0.4",
6313 6313 ]
6314 6314
6315 - [[patch.unused]]
6316 - name = "quasi-type"
6317 - version = "0.1.3"
6318 -
6319 - [[patch.unused]]
6320 - name = "synckit-client"
6321 - version = "0.10.0"
6322 -
6323 6315 [[patch.unused]]
6324 6316 name = "kberg"
6325 6317 version = "0.1.0"
@@ -6335,3 +6327,11 @@
6335 6327 [[patch.unused]]
6336 6328 name = "tagtree"
6337 6329 version = "0.4.1"
6330 +
6331 + [[patch.unused]]
6332 + name = "quasi-type"
6333 + version = "0.1.3"
6334 +
6335 + [[patch.unused]]
6336 + name = "synckit-client"
6337 + version = "0.10.0"
@@ -24,6 +24,12 @@
24 24 # not carry a templating engine; on, it adds the third column that says whether
25 25 # a staged description reaches a compiled template.
26 26 askama = ["dep:askama"]
27 + # The residual tests for the four shapes that guard a setting. Off, and those
28 + # shapes are unstaged to match, until a guarded setting can be marked -- see
29 + # the note above each of their `declare!` blocks. Restore the flag and the
30 + # `#[staged]` together, so a residual test never outlives the residual it
31 + # tests.
32 + guarded-settings-stage = []
27 33
28 34 [dependencies]
29 35 quasi-router = { path = "../quasi-router", version = "0.109" }
@@ -31,8 +31,11 @@
31 31 //! would serve the first reader's maximum to everybody after a request that
32 32 //! changed it.
33 33
34 + // The fixture data below is built by this module's tests and by nothing else:
35 + // the bench itself measures the shapes, not the rows behind them.
36 + #![allow(dead_code)]
34 37 use quasi_declare::declare;
35 - use quasi_router::{Bar, Chart, Node};
38 + use quasi_router::{Bar, Chart};
36 39
37 40 /// What the screen read, as the screen needs it.
38 41 pub(crate) struct Takings {
@@ -247,16 +247,38 @@
247 247 );
248 248 }
249 249
250 - /// The plan decides the branch, which is what the spike could not do.
250 + /// A guard no longer takes anything out of the staged render, and that is
251 + /// the point rather than a regression.
252 + ///
253 + /// The twin used to answer each guard from the plan, so a derivation could
254 + /// turn one off and measure what went missing. It now places every guarded
255 + /// member and marks the run instead, which is why one render answers every
256 + /// guard: what a guard controls is written down rather than deduced from a
257 + /// gap. `Plan::empty` therefore draws exactly what `Plan::full` draws, and
258 + /// the branch is in the marks.
251 259 #[test]
252 - fn a_failed_guard_takes_its_emission_out_of_the_render() {
260 + fn a_guard_places_its_emission_and_marks_it_instead() {
253 261 let webview = Webview::new();
254 262 let full = webview.fragment(&pane_staged(&Plan::full(1)));
255 263 let none = webview.fragment(&pane_staged(&Plan::empty()));
256 264
257 265 assert!(full.contains("Your Buyers ("), "{full}");
258 - assert!(!none.contains("Your Buyers ("), "{none}");
259 - assert!(!none.contains("table-head"), "{none}");
266 + assert_eq!(
267 + full.matches("table-head").count(),
268 + none.matches("table-head").count(),
269 + "a guard no longer decides what the twin draws"
270 + );
271 +
272 + // And the branch it used to make by deletion is in the residual.
273 + let residual = quasi_webview::stage::derive(&webview, pane_staged);
274 + assert!(
275 + residual
276 + .ops()
277 + .iter()
278 + .any(|op| matches!(op, quasi_router::stage::Op::Branch(_))),
279 + "{:#?}",
280 + residual.ops()
281 + );
260 282 }
261 283
262 284 /// A loop runs as many times as the plan says, in the scope it is read at.
@@ -15,10 +15,12 @@
15 15 //! item is free and text when it is not, which is one question with two shapes
16 16 //! rather than two questions.
17 17
18 + // The fixture data below is built by this module's tests and by nothing else:
19 + // the bench itself measures the shapes, not the rows behind them.
20 + #![allow(dead_code)]
18 21 use makeover_layout as layout;
19 22 use quasi_declare::declare;
20 23 use quasi_router::screen::Tag;
21 - use quasi_router::{Node, Row};
22 24
23 25 /// One item, priced or free.
24 26 pub(crate) struct Item {