Skip to main content

max / makenotwork

Delete the QUASI_SCREENS flag: the description is the only rendering All seven converted screens serve from the description layer on both boxes, so the switch has nothing left to switch. A flag that outlives its conversion is where the second rendering path lives, which is the third root cause named in the frontend-unification note: a path nobody runs is not maintained, and the hand-written path beside it keeps growing. Gone: QuasiScreens itself, the config field, the startup warning, the .env.example block, quasi::described, six conditional route registrations, the project_content write guard, seven Askama handlers, build_ssh_keys, seven template structs and their .html, and the six parse tests in parity_harness. quasi::mounts is a vec! literal now: a screen missing from it is an address nothing answers. Two predicates read `screen.is_some_and(|n| screens.enabled(n))` and simplify in opposite directions. In settings_tabs::shown_at it kills a path -- a described section can never be selected, which is what made the "ssh-keys" match arm unreachable and build_ssh_keys dead. In user_tabs::html it keeps one: not every tab is described, so only the second half of the test retires. ProjectContentTabTemplate stops deriving Template. Both callers of build_content take items, deleted_items and posts off it and hand them to the described renderer; nothing rendered project_content.html any more. Its blog table went with it, which is what 6077d0d9 was waiting for -- quasi's project_content renders that table itself. Two seals move, in opposite directions. handwritten_confirm 47 -> 46: library_contacts.html took its hx-confirm with it, as Shape 8 predicted. The other two dual-serve templates stay, because they are not tab renderings but the fragments routes::api::ssh_keys and the git-token routes answer with. Dead vocabulary 44 -> 45, and this one loosens: .form-label lost its last spelling in this repo's markup, while makeover-webview still writes it on the screen that replaced that template. The strip tests narrow rather than go. A described tab now never carries hx-target, where under the old default every tab was Askama and every tab was retargeted, so each test keeps the Askama tabs and asserts the described ones get a frame but no target.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-26 17:54 UTC
Signed with PGP, not checked
Commit: 25573e1793165cfea3685b3eb316a3a30ccd3c49
Parent: 5394a7c
44 files changed, +309 insertions, -1651 deletions
@@ -50,10 +50,3 @@
50 50 # script reads the same value as CAPTURE_BUYER_PASSWORD. See src/seed/buyer.rs.
51 51 # TESTNOT_BUYER_PASSWORD=
52 52
53 - # Optional: the wave-2 conversion switch. A comma-separated list of screens that
54 - # serve from the quasi description layer instead of Askama; `*` converts
55 - # everything, which is a local-work setting. Unset means every screen serves
56 - # Askama, which is where every deployment stays until a screen's parity test is
57 - # green and Max flips it. A name that matches nothing is inert, so a typo
58 - # disables a screen rather than enabling the wrong one. See wiki look-wave-2.
59 - # QUASI_SCREENS=
M server/build.rs +15 -1
@@ -494,7 +494,21 @@
494 494 /// template in this repo. Nothing about this server changed; what changed is
495 495 /// that the check can now see the half of the vocabulary it was blind to.
496 496 /// It tightens as screens convert, exactly as the lines above did.
497 - const DEAD_VOCABULARY_HIGH_WATER: usize = 44;
497 + /// 44 to 45, 2026-08-26, and this one LOOSENS -- the first line here that does.
498 + /// `64b33b26` deleted the seven Askama renderings the description replaced, and
499 + /// `.form-label` lost its last two spellings with them (both in
500 + /// `partials/tabs/user_ssh_keys_tab.html`). The class is not gone and is not
501 + /// unused: makeover-webview's field emitter still writes it, on the described
502 + /// screen that replaced that template. It is dead only in the sense this check
503 + /// can measure, which is "no markup in this repo spells it", and the markup
504 + /// that spells it is now Rust in a dependency.
505 + ///
506 + /// So a rising number here is not automatically a regression. Read it against
507 + /// what moved: markup deleted in favour of a description will raise it, and a
508 + /// class that genuinely lost its writer will too. The list the failure prints
509 + /// is what tells them apart -- if a name on it is one this server still means
510 + /// to render, that is the bug.
511 + const DEAD_VOCABULARY_HIGH_WATER: usize = 45;
498 512
499 513 /// The scripts this build script generates into `static/`.
500 514 ///
@@ -1053,7 +1053,6 @@
1053 1053 access_gate: crate::config::AccessGate::Open,
1054 1054 sso: None,
1055 1055 rate_limits: crate::constants::RateLimits::production(),
1056 - quasi_screens: crate::config::QuasiScreens::default(),
1057 1056 build: BuildConfig {
1058 1057 trigger_token: None,
1059 1058 host_linux: None,
@@ -1140,7 +1139,6 @@
1140 1139 access_gate: crate::config::AccessGate::Open,
1141 1140 sso: None,
1142 1141 rate_limits: crate::constants::RateLimits::production(),
1143 - quasi_screens: crate::config::QuasiScreens::default(),
1144 1142 build: BuildConfig {
1145 1143 trigger_token: None,
1146 1144 host_linux: None,
@@ -84,68 +84,6 @@
84 84 /// Rate-limit profile the router is built with. Production everywhere that
85 85 /// is not a test; see [`crate::constants::RateLimits`].
86 86 pub rate_limits: crate::constants::RateLimits,
87 - /// Which screens serve from the quasi description layer instead of Askama
88 - /// (`QUASI_SCREENS`). See [`QuasiScreens`].
89 - pub quasi_screens: QuasiScreens,
90 - }
91 -
92 - /// The wave-2 conversion switch, one screen at a time.
93 - ///
94 - /// Per screen and not global: a global flag means the first screen converted
95 - /// cannot ship until the last one is, which turns a hundred-screen conversion
96 - /// into one release. Per screen, each conversion ships the moment its parity
97 - /// test is green and reverts by editing an env var rather than by a deploy.
98 - ///
99 - /// Read from `QUASI_SCREENS` as a comma-separated list of screen names. Unset
100 - /// means empty means every screen still serves Askama, which is the state this
101 - /// is meant to be in everywhere until Max flips one:
102 - ///
103 - /// ```text
104 - /// QUASI_SCREENS=user_account,item_pricing
105 - /// QUASI_SCREENS=* # everything, for local work
106 - /// ```
107 - ///
108 - /// The names are the conversion's own, matching the screen inventory in wiki
109 - /// `look-wave-2`. Nothing validates them against a registry: a typo disables a
110 - /// screen rather than enabling the wrong one, which is the safe direction, and
111 - /// a registry would have to be kept in step with a list that is still moving.
112 - #[derive(Clone, Debug, Default, PartialEq, Eq)]
113 - pub struct QuasiScreens {
114 - all: bool,
115 - names: std::collections::HashSet<String>,
116 - }
117 -
118 - impl QuasiScreens {
119 - /// Parse the comma-separated form. Blanks and stray whitespace are ignored.
120 - #[must_use]
121 - pub fn parse(raw: &str) -> Self {
122 - let mut all = false;
123 - let mut names = std::collections::HashSet::new();
124 - for part in raw.split(',') {
125 - match part.trim() {
126 - "" => {}
127 - "*" => all = true,
128 - name => {
129 - names.insert(name.to_owned());
130 - }
131 - }
132 - }
133 - Self { all, names }
134 - }
135 -
136 - /// Whether this screen serves from the description layer.
137 - #[must_use]
138 - pub fn enabled(&self, screen: &str) -> bool {
139 - self.all || self.names.contains(screen)
140 - }
141 -
142 - /// Whether any screen is converted. For the startup log line: a server
143 - /// serving one screen differently from every other deployment is worth
144 - /// saying out loud rather than discovering.
145 - #[must_use]
146 - pub fn any(&self) -> bool {
147 - self.all || !self.names.is_empty()
148 - }
149 87 }
150 88
151 89 /// Native build pipeline configuration (`BUILD_*`, `GIT_*`).
@@ -597,7 +535,6 @@
597 535 access_gate,
598 536 sso,
599 537 rate_limits: crate::constants::RateLimits::production(),
600 - quasi_screens: QuasiScreens::parse(&std::env::var("QUASI_SCREENS").unwrap_or_default()),
601 538 build: BuildConfig {
602 539 trigger_token: build_trigger_token,
603 540 host_linux: build_host_linux,
@@ -1167,7 +1104,6 @@
1167 1104 access_gate: AccessGate::Open,
1168 1105 sso: None,
1169 1106 rate_limits: crate::constants::RateLimits::production(),
1170 - quasi_screens: QuasiScreens::default(),
1171 1107 build: BuildConfig {
1172 1108 trigger_token: None,
1173 1109 host_linux: None,
@@ -596,10 +596,7 @@
596 596 });
597 597 let csrf_routes = csrf_routes.finalize();
598 598 let app = Router::new()
599 - .merge(page_routes(
600 - state.config.rate_limits,
601 - &state.config.quasi_screens,
602 - ))
599 + .merge(page_routes(state.config.rate_limits))
603 600 .merge(sso_routes())
604 601 .merge(csrf_routes)
605 602 .merge(git_routes())
@@ -142,17 +142,6 @@
142 142 let config = Config::from_env().expect("Failed to load configuration");
143 143 tracing::info!("Configuration loaded");
144 144
145 - // A box serving some screens from the description layer and the rest from
146 - // Askama is worth saying out loud. The failure this guards against is a
147 - // QUASI_SCREENS left set on a host nobody meant to convert, which otherwise
148 - // looks exactly like the site behaving oddly for one page.
149 - if config.quasi_screens.any() {
150 - tracing::warn!(
151 - screens = %std::env::var("QUASI_SCREENS").unwrap_or_default(),
152 - "QUASI_SCREENS is set: these screens serve from the description layer, not Askama"
153 - );
154 - }
155 -
156 145 // Create database connection pool with health checks and lifecycle limits.
157 146 // - test_before_acquire: validates connections before use (catches stale/broken conns)
158 147 // - max_lifetime: rotates connections to prevent long-lived session issues
@@ -37,12 +37,14 @@
37 37 /// 50 across 33 files on 2026-08-20, the measurement the task was written
38 38 /// against and unchanged since.
39 39 ///
40 - /// Three of the fifty are not this program's to remove and will be the last to
41 - /// go: `partials/ssh_keys_list.html`, `partials/git_tokens_list.html` and
42 - /// `partials/tabs/library_contacts.html` back screens that are already
43 - /// described, and are still live Askama structs because the conversions are
44 - /// dual-serve while `QUASI_SCREENS` serves nobody. They leave with the templates
45 - /// when the switch ships, which is task `64b33b26`.
40 + /// Three of the fifty were called out as not this program's to remove:
41 + /// `partials/ssh_keys_list.html`, `partials/git_tokens_list.html` and
42 + /// `partials/tabs/library_contacts.html`, all backing screens that were already
43 + /// described and dual-serving while the switch served nobody. `64b33b26` shipped
44 + /// the switch's deletion and took `library_contacts.html` with it, which is the
45 + /// 47 to 46 below. The other two stay: they are not tab renderings but the
46 + /// fragments `routes::api::ssh_keys` and the git-token routes answer with, and
47 + /// the described screens still call those.
46 48 ///
47 49 /// 48 on 2026-08-22, and the first two that left without their screens. The
48 50 /// identical "Delete this blog post?" button in `tabs/project_content.html` and
@@ -64,7 +66,7 @@
64 66 /// progress: the seal counts template source, so deduplicating two templates
65 67 /// lowers it without describing anything. The surviving site is still blocked
66 68 /// on the `closest .link-row` target above.
67 - const HIGH_WATER: usize = 47;
69 + const HIGH_WATER: usize = 46;
68 70
69 71 /// Every template, recursively. Walked rather than listed for the reason the
70 72 /// frontend-globals seal walks `frontend/src`: a fence that has to be told about
@@ -1,4 +1,4 @@
1 - //! Tests for the parity harness, and for the per-screen conversion switch.
1 + //! Tests for the parity harness.
2 2 //!
3 3 //! The harness is what every phase-3 conversion trusts, so it is tested on both
4 4 //! sides: that it ignores what it claims to ignore, and that it still fails on
@@ -12,7 +12,6 @@
12 12 #[path = "harness/parity.rs"]
13 13 mod parity;
14 14
15 - use makenotwork::config::QuasiScreens;
16 15 use parity::Parity;
17 16
18 17 // --- what it forgives -------------------------------------------------------
@@ -172,49 +171,14 @@
172 171 }
173 172
174 173 // --- the per-screen switch --------------------------------------------------
175 -
176 - #[test]
177 - fn no_screen_is_converted_by_default() {
178 - // The state every deployment is in until Max flips one.
179 - let screens = QuasiScreens::default();
180 - assert!(!screens.enabled("item_pricing"));
181 - assert!(!screens.any());
182 - }
183 -
184 - #[test]
185 - fn an_unset_variable_converts_nothing() {
186 - let screens = QuasiScreens::parse("");
187 - assert!(!screens.enabled("item_pricing"));
188 - assert!(!screens.any());
189 - }
190 -
191 - #[test]
192 - fn screens_are_named_one_at_a_time() {
193 - let screens = QuasiScreens::parse("user_account,item_pricing");
194 - assert!(screens.enabled("user_account"));
195 - assert!(screens.enabled("item_pricing"));
196 - assert!(!screens.enabled("project_content"));
197 - assert!(screens.any());
198 - }
199 -
200 - #[test]
201 - fn whitespace_and_blanks_in_the_list_are_ignored() {
202 - let screens = QuasiScreens::parse(" user_account , , item_pricing ,");
203 - assert!(screens.enabled("user_account"));
204 - assert!(screens.enabled("item_pricing"));
205 - assert!(!screens.enabled(""));
206 - }
207 -
208 - #[test]
209 - fn a_star_converts_everything_for_local_work() {
210 - let screens = QuasiScreens::parse("*");
211 - assert!(screens.enabled("anything_at_all"));
212 - assert!(screens.any());
213 - }
214 -
215 - #[test]
216 - fn a_typo_disables_a_screen_rather_than_enabling_another() {
217 - // The safe direction, and the reason nothing validates against a registry.
218 - let screens = QuasiScreens::parse("item_pricng");
219 - assert!(!screens.enabled("item_pricing"));
220 - }
174 + //
175 + // Six tests lived here until 2026-08-26, covering `QuasiScreens::parse`: the
176 + // default converting nothing, an unset variable, naming screens one at a time,
177 + // whitespace and blanks, `*` for local work, and a typo disabling a screen
178 + // rather than enabling another. `64b33b26` deleted the switch, so they have no
179 + // subject.
180 + //
181 + // The normalizer above is untouched and is the half worth keeping: a phase-3
182 + // conversion still wants to compare its described rendering against the Askama
183 + // one it replaces. What it cannot do any more is serve both from one binary and
184 + // diff them over a request, because there is no flag to serve the old one.
@@ -43,7 +43,8 @@
43 43 use super::Viewer;
44 44 use crate::db;
45 45
46 - /// The conversion switch's name for this screen. `QUASI_SCREENS=buyer_contacts`.
46 + /// This screen's name. Was the `QUASI_SCREENS` switch name until `64b33b26`
47 + /// deleted the flag; it survives as the marker the tab strips read.
47 48 pub const SCREEN: &str = "buyer_contacts";
48 49
49 50 /// The address this screen answers, and the one the Askama route gives up.