Name the first door instead of an empty paragraph, and stop calling the night a fault - #82
Merged
Conversation
…he night a fault
At 11:40pm on a Monday the whole app was one card reading "Nearest buildings"
over an empty paragraph, above a button reading "Show nearest buildings", inside
an orange border. Three ways of saying nothing, and the orange said something was
broken when the only thing that had happened was the time of day.
The gate now says the minute in its heading and one line under it.
before after
Nearest buildings Monday, 11:40pm
(empty) Classes are done for the day. On Tuesday PAES
opens at 5:00am and Vacant ranks rooms again at
8:00am.
border --warn border --line
nextOpening scans forward up to a week for the first door that has not already
opened, and it is location-free on purpose: three buildings open together at
7:00am on both weekend days, and nothing in state.js knows where the reader is
standing, so it names the first the index reaches and the count carries the other
two. The buildings screen uses the same function, so at 3am it reads "Everything
is closed. Hitchcock Hall and 2 more open at 7:00am." rather than stopping at
"Everything is closed right now." while holding all 46 opening times.
A door opening and a ranked list coming back are different promises. On a
Saturday they are 49 hours apart: the first door is 7:00am that morning, the
first ranked room is 8:00am on Monday, because only 5 of the 46 buildings publish
Saturday hours and busyDay.weekdays[6] is false. So the Saturday sentence names
Monday and never promises rooms at 8am.
Writing the sweep test found a second one. The last weekday door opens at 7:00am,
so between 7:00 and 7:59 the next door is TOMORROW'S, and a bare "and Vacant
ranks rooms again at 8:00am" sitting behind "On Saturday" reads as Saturday when
it means 59 minutes away. 300 minutes of the week, one hour every weekday,
immediately before class. The clause carries "today" in exactly that case now.
Orange means a refusal. paintGate adds .refusal for the six states refusedState
dresses and leaves it off for the clock, which the gate wears for 6,405 of the
10,080 minutes in a week. Labor Day at 2:00pm comes out rgb(255, 176, 46),
Monday at 11:40pm comes out rgb(29, 35, 44), read off the computed border.
The closed group gets opensAt as a last-resort tiebreak under the walk, measured
rather than assumed: over a 12x12 grid on the campus box at every quarter hour of
every day, 4,066 of 96,768 closed lists (4.20%) come out in a different order and
no row moves more than two places. Cockins Hall and Agricultural Engineering are
both 1,003 m from the south of campus, one opening 12:30pm on a Sunday and the
other shut all day, and the shut one used to sort first.
A heading is not a control. focusHeading moves focus to an h2 so the reader lands
on the new screen, and a script focus is scored with the modality of the last real
input, so a heading reached from the keyboard matched :focus-visible and wore the
3px ring meant for buttons. Driven headless on main: the buildings heading reached
by mouse comes out outline none, the same heading reached by Tab comes out outline
solid 3px. focus({ focusVisible: false }) is none on both routes, and the
h2[tabindex="-1"] rule is the same answer for an engine that drops the option.
Nine tests appended, none edited. 606 tests, 602 pass, 4 skip.
…s to it Review found the night gate saying five things the app cannot back, all of them new, and no test on any of the seven screen changes. The gate promised the ranked list back off busyDay.weekdays alone, a weekly Mon-Fri mask counted off block totals with no calendar in it, so it named days resolveState already refuses on: 3,780 of the 94,665 gate minutes of Autumn 2026, 3.99%, pointing at Labor Day, Veterans Day, Thanksgiving or the day after the last class of term. 3,105 of those were one weekend, every gate minute from Friday 20:15 to Sunday midnight offering rooms on Labor Day. nextScheduled now steps real dates through scheduleCoversDate, which is the day half of inScheduledHours lifted out of it, and drops the clause when it cannot see a day it will rank on. The sweep is held against resolveState, a different function reading a different thing, so it is not the sentence marking its own homework. It also named the first door with campus already open behind it, on 3,885 of the 6,405 gate minutes of a week, including 7:30am on a Tuesday with all 46 buildings unlocked under a button leading straight to a list of them. The buildings screen guards the same sentence on groups.open.length; openDoorCount gives the gate the same fact without needing an origin. data/buildings-hours.json is weekly and hoursFor indexes it by weekday, so nothing in it knows about a holiday. On Thanksgiving the buildings screen printed "PAES opens at 5:00am" directly under its own heading saying campus is locked, and on the Sunday before Labor Day it said the same about the Monday. firstDoor drops the door when the day it lands on is one the university closes, and both screens go back to "Everything is closed right now." The registrar publishes three no-classes weekdays that the mask says yes to and resolveState already flags. The gate said the opposite on both sides of the day: "Classes have not started yet" at 3am on Autumn Break, "Classes are done for the day" at 11pm. It now says the same words the ranked screen uses on the date. The heading is a live minute and nothing repainted it. Booted at 11:40pm on a Monday and brought back at 10:00am on the Tuesday, the card was byte identical, still naming Monday night on a minute the app ranks. visibilitychange now covers the question screen too. Two numbers did not reproduce and were heading into an append-only record. The byDoor sweep is 2,984 of 96,768 (3.08%) with a maximum row move of 1, not 4,066 / 4.20% / two places, and the Cockins Hall and Agricultural Engineering example never happens: those two never tie anywhere on the grid. The key is now the NEXT door rather than opensAt, which for a row already shut for the day is the minute it opened this morning, and fixed four cases of a building shut until tomorrow sorting above one still to open. The nextOpening header said a Saturday night names 46 doors opening Monday; the answer is three opening 7:00am Sunday, and Monday is unreachable from any Saturday minute. On tests, all nine of the previous ones exercised pure functions, and every one of the seven js/app.js and index.html changes reverted with the suite green, including the bug in the branch title. Eighteen mutations now go red, covering each screen change and each correctness fix; the source-text assertions follow the idiom dev.test.mjs and the container-query test already use. Also here: the buildings screen picks the nearest of three tied doors rather than the first the index reaches, Independence Hall at 120 m over Hitchcock Hall at 460 m; WEEKDAYS renamed to DAY_NAMES, the name js/dev.js already uses, because it sat one line above busyDay.weekdays meaning something else; comment density on the added lines cut from 92 to 77 per 100 in js/state.js and 79 to 56 in js/app.js; and sw.js re-stamped, shell 77,138 bytes and the cache name moved off the one main carries. Driven headless in the real app at every instant named above, from the pinned Thompson Library origin, with a clock that can be moved after boot. This branch's nine tests became twenty, four of them rewritten for the signatures that moved; nothing that exists on main is edited or deleted, git diff main on the test file still removes no line. 617 tests, 604 pass, 4 skip; the 9 alert.test.mjs failures on this box are a bash artefact that fails identically on main. node scripts/shoot.mjs --check is clean on both trees, interleaved, and writes nothing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What it looks like
At 11:40pm on a Monday the whole app is one card: heading
Nearest buildings,an empty paragraph, a button reading
Show nearest buildings, all inside anorange border. Every holiday gets a paragraph explaining itself; the ordinary
night, which is most of the year, gets nothing and an alarm colour.
Mechanism
On
main,paintGatestarts at js/app.js:1766 and borrowsUNSCHEDULEDat:1778-1779. That pair belongs to the buildings screen and its
bodyis''bydesign, so the heading repeated its own button over an empty paragraph.
#gatecarried
--warnin its base rule at index.html:195-196, so the clock wore thecolour a missing fact wears everywhere else, for 6,405 of the 10,080 minutes in a
week.
Three new pure functions in js/state.js:
nextOpeningwalks forward a week forthe first door that has not already opened,
openDoorCountsays how many areunlocked right now, and
unscheduledGatewrites the line. All three arelocation-free, because whether campus is shut is not a fact about where the
reader is standing; js/app.js swaps in the nearest of any tied doors on the
screen that does know.
Honesty, which is where the work went
Five ways this screen could state something the app cannot back, all of them new
because
mainprinted an empty paragraph here. Every figure is a sweep of theshipped
data/rooms-1268.jsonanddata/current.json.The day the list comes back was read off
busyDay.weekdays, a weekly Mon-Frimask counted from block totals with no calendar in it, so it named days
resolveStatealready refuses on: 3,780 of the 94,665 gate minutes of Autumn2026, 3.99%. 3,105 were one weekend, every gate minute from Friday 20:15 to
Sunday midnight promising rooms on Labor Day; the rest Veterans Day, Thanksgiving
and 2026-12-10.
nextSchedulednow steps real dates throughscheduleCoversDate, the day half ofinScheduledHours(js/state.js:480 onmain) lifted out of it, and drops the clause when it cannot see a day it willrank on. The test walks the sentence's named day back to a date and asks
resolveState, a different function reading a different thing.The door clause fired with campus already open behind it, on 3,885 of a
week's 6,405 gate minutes, including 7:30am on a Tuesday with all 46 buildings
unlocked, under a button leading straight to a list of them. The buildings screen
guards the same sentence on
groups.open.length; the gate now has the same fact.data/buildings-hours.jsonis weekly andhoursForindexes it by weekday, sonothing in it knows about a holiday. On Thanksgiving the buildings screen printed
PAES opens at 5:00amunder its own heading saying campus is locked, and on theSunday before Labor Day it said the same about the Monday.
firstDoordrops thedoor when the day it lands on is one the university closes.
Three registrar no-classes weekdays are days the mask says yes to and
resolveStatealready flags. The gate said the opposite on both sides of them,Classes have not started yetat 3am on Autumn Break andClasses are done for the dayat 11pm. It now says what the ranked screen says on the same date.The heading is a live minute and nothing repainted it.
visibilitychange(js/app.js:2019 on
main) covered the list and buildings screens only, and thegate lives inside
#ask.Evidence
The real app, off a local server, pinned to the Thompson Library steps, with a
clock that can be moved after boot.
#gateand#nearread back from the DOM:The stale heading, same page, clock walked forward with
visibilitychangefiredat each step. Before the one-word fix the card was byte identical at all four:
Two numbers did not reproduce and were heading into an append-only
docs/DECISIONS.md. ThebyDoorsweep is 2,984 of 96,768 (3.08%), maximum rowmove 1, not 4,066 / 4.20% / two places, and the Cockins Hall and Agricultural
Engineering example never happens: the pair never ties on walk and metres at any
of the 144 grid points the sweep uses, and over a 201x201 grid of the same box
there is no origin where both come out 1,003 m. Where they do tie, both read
2,775 m. The key is now the next door rather than
opensAt, which for a rowalready shut for the day is the minute it opened this morning; that fixed four
cases of a building shut until tomorrow sorting above one still to open. Both
figures are asserted in the test now, so they fail rather than rot. The
nextOpeningheader said a Saturday night names 46 doors opening Monday;measured, Saturday publishes 5 doors and Sunday 11, the answer is three opening
7:00am Sunday, and Monday is unreachable from any Saturday minute.
The focus-ring measurement stands as written: on
maina heading reached bymouse comes out
outline: noneand the same heading reached by Tab comes outsolid 3px; with the option it isnoneon both routes, and.opt,.chip,.row,.b-rowand.bar-btnall keep their ring.Tests
Nine tests became twenty under
// ---- the night gate; nothing that exists onmainis edited or deleted andgit diff main -- scripts/test/screens.test.mjsstill removes no line. The first nine were all on pure functions, so every one of
the seven js/app.js and index.html changes reverted with the suite green,
including the bug in the title. Eighteen mutations now go red, one for every
screen change and every correctness fix, including all seven that used to pass:
UNSCHEDULEDback inpaintGate,var(--warn)back in the#gatebase rule,either
refusalclass call deleted,focusVisible: falseor theh2[tabindex="-1"]rule dropped, the buildings sentence reverted, and thesame-day join short-circuited. The source-text assertions use the idiom
scripts/test/dev.test.mjs:50and the container-query test already have.617 tests, 604 pass, 4 skip. The 9
alert.test.mjsfailures on this box area bash artefact and fail identically on
main.node scripts/shoot.mjs --checkis clean on both trees, interleaved, and writes nothing.
Uncertainty
nextOpeningnames whichever tied building the index reaches first, so a rebuildthat reorders
roomscould swap the name in a sentence that stays true; thebuildings screen overrides it with the nearest tie, the gate cannot, having no
origin.
firstDoor's calendar guard and the nearest-door pick live in js/app.jsand are held by source-text assertions plus the driven runs above, not by a unit
test, because js/app.js needs a DOM the offline suite has not got. The
todayday word is unreachable on the shipped table now, so the test drives it from a
door handed in; it stays because a term whose earliest door moved past 8:00am
would need it.
scheduleCoversDateadds an exam-window checkinScheduledHoursdid not have, which changes nothing on the shipped calendar because exam week is
already out of term and already dark.
SHELL_CACHEis stamped from this branch'sparent and has to be re-run on the merge commit.