Skip to main content

max / quasi

Say a badge and a chip, and report what is counted and not work e2030032 answered (b): a standalone tag gets a member spelling. `token` is a setting on Row and on Cell so it can never be a member, and Tag's two constructors are what a screen actually reaches for, so the members are named for those instead. Measured over 33 sites in the three trees. badge "Focus" { tone Info; } chip window.value to get PATH carrying "range" window.value { latched ..; } Both accrete onto a Tag under Container::Tag and the emitter wraps Node::token. `chip` is not in NODE_MEMBERS because it carries an action, which is spelled `to <verb>` rather than as an argument, so it has a parse arm of its own. The rule those two settle is now on the NODE_MEMBERS doc: where a variant holds a builder type, the member is named for the constructor rather than for the variant. 95017e31 answered (a): the predicate does not change and the denominator stays the ratified 514, because the number's value is that it is comparable across waves and reproducible from the tree. progress.py grows a `counted but not work` line and a --parked listing, and --next drops them from the queue so a session cannot stall on them. Two of the three categories are a hand-maintained table with a reason per entry. The third is derived: a shape whose return type is not one declare! can emit. That found 39 nobody had counted, including five Run suppliers in audiofiles' toolbar and three Action methods in goingson's task_list.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session
https://claude.ai/code/session_01MptwXZ8k65v19rFmdGAyki
Author: Max Johnson <me@maxj.phd> · 2026-09-04 16:15 UTC
Signed with PGP, not checked
Commit: 78dcaa66de40387d549ed37b1e522f9627245b83
Parent: 2353c9e
4 files changed, +181 insertions, -8 deletions
@@ -48,6 +48,63 @@
48 48 # reproduced by population.py.
49 49 BASELINE = {"mnw": 173, "goingson": 184, "audiofiles": 157}
50 50
51 + # COUNTED, AND NOT WORK.
52 + #
53 + # `population.py`'s predicate counts a function returning a description type as
54 + # a shape to convert. Three kinds of thing match it and never will be converted,
55 + # so they sit at the head of `--next` forever and a session not told to skip
56 + # them converts nothing and reports a stall. Settled 2026-09-04 (GoingsOn
57 + # `95017e31`, option (a)): the predicate does not change and the denominator
58 + # stays the ratified 514, because the number's whole value is that it is
59 + # comparable across waves and reproducible from the tree. They are reported
60 + # instead.
61 + #
62 + # Two of the three categories cannot be detected mechanically and are listed
63 + # here by hand, with the reason. The third -- a shape `declare!` cannot emit at
64 + # all -- is detected in `unemittable()` below.
65 + NOT_WORK = {
66 + "MNW/server/src/quasi/tip.rs": {
67 + "checkout": "`Action::with` is refused as a production; `doing` is the remedy",
68 + },
69 + "MNW/server/src/quasi/auth_pages.rs": {
70 + "reset_action": "`Action::with` is refused as a production",
71 + },
72 + "MNW/server/src/quasi/git_commit.rs": {
73 + "note_delete": "`Action::with` is refused as a production",
74 + },
75 + "MNW/server/src/quasi/pricing.rs": {
76 + "crossover_meter": "`meter` is a setting on `Row`, so it cannot also be a member",
77 + },
78 + "MNW/server/src/quasi/item_sales.rs": {"badge": "a supplier a conversion wrote"},
79 + "MNW/server/src/quasi/media_picker.rs": {
80 + "folder_choices": "a supplier a conversion wrote",
81 + },
82 + "MNW/server/src/quasi/payout_summary.rs": {
83 + "figures": "a supplier a conversion wrote",
84 + },
85 + "MNW/server/src/quasi/widgets/carousel.rs": {
86 + "region": "refused on the hard limit: a closure holding a `let mut` and an `if let`",
87 + },
88 + }
89 +
90 + # The shaped types `declare!` can return. A shape function whose return type is
91 + # not one of these cannot be emitted at all, whatever the form grows.
92 + SHAPED = {"Node", "Screen", "Slot", "Row", "Cells", "Field", "Act"}
93 +
94 +
95 + def unemittable(shape):
96 + """Whether `declare!` could never emit this shape, and why.
97 +
98 + Two independent reasons, and `feeds.rs`'s `Surface::address` has both. A
99 + return type outside `SHAPED` has no R2 case and cannot get one, because the
100 + macro emits a free function returning a vocabulary type. A receiver is the
101 + other: a declaration is a `fn`, never an `impl` item.
102 + """
103 + head = pop.head_type(shape["returns"]) or ""
104 + if head not in SHAPED:
105 + return f"`declare!` returns one of {'/'.join(sorted(SHAPED))}, not `{head}`"
106 + return None
107 +
51 108
52 109 def scan():
53 110 per_file = {}
@@ -62,6 +119,7 @@
62 119 hand = pop.shapes_in(f)
63 120 per_file[key] = {
64 121 "tree": TREES[rel],
122 + "shapes": hand,
65 123 "hand": len(hand),
66 124 "declared": len(DECLARED.findall(blanked)),
67 125 "lines": sum(h.get("lines", 0) for h in hand),
@@ -69,10 +127,28 @@
69 127 return per_file
70 128
71 129
130 + def counted_but_not_work(per_file):
131 + """Every counted shape that no conversion will ever remove, with its reason.
132 +
133 + `NOT_WORK` holds the two categories that need a human to say so; the third
134 + is derived, so a new method returning an `Action` is reported the day it is
135 + written rather than the day somebody notices.
136 + """
137 + out = []
138 + for path, v in sorted(per_file.items()):
139 + for shape in v["shapes"]:
140 + why = NOT_WORK.get(path, {}).get(shape["fn"]) or unemittable(shape)
141 + if why:
142 + out.append((path, shape["fn"], why))
143 + return out
144 +
145 +
72 146 def main() -> int:
73 147 ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
74 148 ap.add_argument("--files", action="store_true", help="per file, fully converted files hidden")
75 149 ap.add_argument("--next", action="store_true", help="the smallest unconverted files first")
150 + ap.add_argument("--parked", action="store_true",
151 + help="the shapes the predicate counts that are not work, and why")
76 152 args = ap.parse_args()
77 153
78 154 per_file = scan()
@@ -87,12 +163,27 @@
87 163 print(f" {tree:11} declared {d:4}, remaining {h:4} of {base}")
88 164 print(f"\ndeclared {declared}, remaining {remaining} of {total_base} ({pct:.1f}%)")
89 165
166 + parked = counted_but_not_work(per_file)
167 + if parked:
168 + print(f"of which counted but not work: {len(parked)}")
169 +
170 + if args.parked:
171 + print("\nCounted, and not work. Never take one of these off the queue.\n")
172 + for path, name, why in parked:
173 + print(f" {path}:{name}\n {why}")
174 +
90 175 if args.next:
91 - todo = [(k, v) for k, v in per_file.items() if v["hand"]]
92 - todo.sort(key=lambda kv: (kv[1]["lines"], kv[1]["hand"]))
93 - print("\nSmallest unconverted files first. A whole file is the unit worth taking.\n")
94 - for k, v in todo[:20]:
95 - print(f" {v['hand']:3} shapes {v['lines']:5}L {k}")
176 + skip = {(path, name) for path, name, _ in parked}
177 + todo = []
178 + for k, v in per_file.items():
179 + left = [s for s in v["shapes"] if (k, s["fn"]) not in skip]
180 + if left:
181 + todo.append((k, len(left), sum(s.get("lines", 0) for s in left)))
182 + todo.sort(key=lambda row: (row[2], row[1]))
183 + print("\nSmallest unconverted files first. A whole file is the unit worth taking.")
184 + print("The counted-but-not-work shapes are already out; `--parked` lists them.\n")
185 + for path, hand, lines in todo[:20]:
186 + print(f" {hand:3} shapes {lines:5}L {path}")
96 187
97 188 if args.files:
98 189 print()
@@ -161,6 +161,15 @@
161 161 args: Vec<Arg>,
162 162 body: Vec<Item>,
163 163 },
164 + /// `chip <value> to <action> { .. }`
165 + ///
166 + /// Its own emission rather than a `Simple` member because `Tag::chip` takes
167 + /// an `Action`, and an action is spelled `to <verb>` rather than as an arg.
168 + Chip {
169 + value: Arg,
170 + action: Action,
171 + body: Vec<Item>,
172 + },
164 173 /// `screen <arrangement> <arg> { .. }`
165 174 Screen {
166 175 arrangement: Ident,
@@ -50,6 +50,8 @@
50 50 Image,
51 51 /// One canvas: its body sets on the `Canvas` and draws inside its scope.
52 52 Canvas,
53 + /// One tag: its body says what it is like, and it emits nothing.
54 + Tag,
53 55 }
54 56
55 57 pub fn declaration(declaration: &Declaration) -> Result<TokenStream> {
@@ -605,6 +607,10 @@
605 607 // canvas can hold anything: the markup is opaque, so nothing is
606 608 // injected into the middle of it.
607 609 (Container::Canvas, other) => Ok((node(other)?, quote!(.with(#held)))),
610 + (Container::Tag, other) => Err(syn::Error::new(
611 + emission_span(other),
612 + "a tag holds nothing: its body says what it is like",
613 + )),
608 614 (Container::Run, Emission::Beside { priority, inner }) => Ok((
609 615 node(inner)?,
610 616 quote!(.beside(#held, ::quasi_router::layout::Priority::#priority)),
@@ -775,6 +781,37 @@
775 781 )?;
776 782 Ok(quote!(::quasi_router::Node::Image(#picture)))
777 783 }
784 + Emission::Simple { member, args, body } if member == "badge" => {
785 + // The third member whose body does not set on a `Node`, and the
786 + // first of two over `Tag`. `Node::Token` holds a `Tag`, and `token`
787 + // is a setting on `Row` and on `Cell` so it cannot be a member at
788 + // all, so the members are named for `Tag`'s constructors instead.
789 + // quasicoherent `e2030032` decided it over 33 sites.
790 + let args = args.iter().map(self::arg).collect::<Result<Vec<_>>>()?;
791 + let tag = accrete(
792 + body,
793 + Container::Tag,
794 + &quote!(::quasi_router::screen::Tag::badge(#(#args),*)),
795 + )?;
796 + Ok(quote!(::quasi_router::Node::token(#tag)))
797 + }
798 + Emission::Chip {
799 + value,
800 + action,
801 + body,
802 + } => {
803 + // The other half of `badge`. A chip goes somewhere, so it carries an
804 + // action, which is why it is spelled `chip <value> to <action>`
805 + // rather than as a member with two arguments.
806 + let value = arg(value)?;
807 + let called = self::action(action)?;
808 + let tag = accrete(
809 + body,
810 + Container::Tag,
811 + &quote!(::quasi_router::screen::Tag::chip(#value, #called)),
812 + )?;
813 + Ok(quote!(::quasi_router::Node::token(#tag)))
814 + }
778 815 Emission::Simple { member, args, body } if member == "canvas" => {
779 816 // The second member whose body does not set on a `Node`, and for
780 817 // `picture`'s reason: `Node::Canvas` holds a `Canvas`, and
@@ -1396,7 +1433,7 @@
1396 1433 Emission::Simple { member, .. } => member.span(),
1397 1434 Emission::Screen { arrangement, .. } => arrangement.span(),
1398 1435 Emission::Row { .. } | Emission::List(_) => Span::call_site(),
1399 - Emission::Form { action, .. } => action.verb.span(),
1436 + Emission::Form { action, .. } | Emission::Chip { action, .. } => action.verb.span(),
1400 1437 Emission::Field { kind, .. } => kind.span(),
1401 1438 Emission::Act { action, .. } => action.verb.span(),
1402 1439 Emission::Guarded { guard, .. } => guard.span,
@@ -47,8 +47,8 @@
47 47 /// without a production is a parse error naming it, which is the failure worth
48 48 /// having.
49 49 const MEMBERS: &[&str] = &[
50 - "act", "across", "activate", "beside", "cell", "cells", "column", "field", "form", "given",
51 - "include", "link", "offering", "region", "row", "screen", "table",
50 + "act", "across", "activate", "beside", "cell", "cells", "chip", "column", "field", "form",
51 + "given", "include", "link", "offering", "region", "row", "screen", "table",
52 52 ];
53 53
54 54 /// The members that are one of `Node`'s own constructors, called by its name.
@@ -68,12 +68,24 @@
68 68 /// supplier, which is the remedy the deferred table already names, and
69 69 /// `project_analytics`'s `chip` is that supplier.
70 70 ///
71 + /// **Where a variant holds a builder type, the member is named for the
72 + /// constructor rather than for the variant.** That is the rule the exceptions
73 + /// below share, and it is what `badge` and `chip` settled: `Node::Token` holds a
74 + /// `Tag`, `token` is a setting on `Row` and on `Cell` so it cannot be a member
75 + /// at all, and `Tag`'s two constructors are what a screen actually reaches for.
76 + /// So there is no `token` member and there never will be. quasicoherent
77 + /// `e2030032` is the decision, measured over 33 sites in the three trees.
78 + ///
71 79 /// `canvas` is the second exception and is the last entry for that reason:
72 80 /// `Canvas` is a builder type of its own, the way `Image` is, so the member's
73 81 /// body accretes onto the canvas and the emitter wraps the variant afterwards.
74 82 /// `custom_page` is the site -- a creator's opaque markup under the scope its
75 83 /// stylesheet was rewritten for, with the platform's own blocks drawn inside
76 84 /// it.
85 + ///
86 + /// `badge` is the third and `chip` the fourth, and `chip` is not on this list
87 + /// because it carries an action: it has a parse arm of its own. Both accrete
88 + /// onto a `Tag` under `Container::Tag` and the emitter wraps `Node::token`.
77 89 const NODE_MEMBERS: &[&str] = &[
78 90 "text",
79 91 "toned",
@@ -91,6 +103,7 @@
91 103 "code",
92 104 "picture",
93 105 "canvas",
106 + "badge",
94 107 ];
95 108
96 109 /// The arrangements a screen may be laid out in.
@@ -677,6 +690,29 @@
677 690 },
678 691 ))
679 692 }
693 + // A chip is a tag that goes somewhere, so it takes an action, and
694 + // an action is spelled `to <verb>` rather than as an argument. That
695 + // is why it is not in NODE_MEMBERS with `badge`.
696 + "chip" => {
697 + let value: Arg = input.parse()?;
698 + preposition(input, "to")?;
699 + let action: Action = input.parse()?;
700 + let guard = guard(input)?;
701 + let body = if input.peek(token::Brace) {
702 + block(input)?
703 + } else {
704 + input.parse::<Token![;]>()?;
705 + Vec::new()
706 + };
707 + Ok(guarded(
708 + guard,
709 + Self::Chip {
710 + value,
711 + action,
712 + body,
713 + },
714 + ))
715 + }
680 716 "field" => {
681 717 let kind: Ident = input.parse()?;
682 718 let name: Arg = input.parse()?;