Skip to main content

max / goingson

Drop decorative bullets, vacuous doc comments, and a timezone dependency Three mechanical findings from the GoingsOn problems queue. A pinned saved view carried its state as a U+2022 appended to the button label. It is a data-pinned attribute now, styled from the stylesheet, so the state is in the markup rather than in a glyph. The reader-mode fallback in utils.js writes "- " for a list item, matching what pter::convert emits on the backend, so the two paths read the same. Sixteen doc comments that only respelled the field they sat on are gone. Kept anything stating a unit, an invariant, or a why. go-mcp's relative-event test wrote its instants with a fixed -06:00 offset and passed only on a UTC-6 host. It builds them from the system zone now and picks a destination zone whose wall clock actually differs, so the moved assertion cannot go green for the wrong reason.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-20 20:36 UTC
Signed with PGP, not checked
Commit: c238caaa9dc224dd32473df5c9cef1e2b6acd468
Parent: a15c474
14 files changed, +40 insertions, -28 deletions
@@ -4,10 +4,8 @@
4 4
5 5 // Time Constants
6 6
7 - /// Hours in a day.
8 7 pub const HOURS_PER_DAY: f64 = 24.0;
9 8
10 - /// Days in a week.
11 9 pub const DAYS_PER_WEEK: i64 = 7;
12 10
13 11 /// Approximate days in a month (for relative date calculations).
@@ -38,7 +38,6 @@
38 38 #[error("Internal error: {0}")]
39 39 Internal(String),
40 40
41 - /// Authentication error.
42 41 #[error("Authentication error: {0}")]
43 42 Auth(String),
44 43
@@ -1382,14 +1382,28 @@
1382 1382 let ctx = Arc::new(Ctx::new(pool));
1383 1383 let reg = tools::registry(ctx.clone());
1384 1384
1385 - // 06:00 as a routine, not as an instant.
1385 + // 06:00 as a routine, not as an instant. A relative event's civil time is
1386 + // rendered in whatever zone the machine reports, so the instant is built
1387 + // from that zone rather than written as a fixed -06:00 offset: hard-coding
1388 + // one made the assertion below pass only on Mountain-time hosts.
1389 + use chrono::TimeZone as _;
1390 + let home = goingson_core::tz::system_tz();
1391 + let start_at = home
1392 + .with_ymd_and_hms(2026, 8, 3, 6, 0, 0)
1393 + .earliest()
1394 + .expect("06:00 on this date exists in every zone");
1395 + let end_at = home
1396 + .with_ymd_and_hms(2026, 8, 3, 6, 30, 0)
1397 + .earliest()
1398 + .expect("06:30 on this date exists in every zone");
1399 +
1386 1400 let created = call(
1387 1401 &reg,
1388 1402 "create_event",
1389 1403 json!({
1390 1404 "title": "Wake, feed cats",
1391 - "start": "2026-08-03T06:00:00-06:00",
1392 - "end": "2026-08-03T06:30:00-06:00",
1405 + "start": start_at.to_rfc3339(),
1406 + "end": end_at.to_rfc3339(),
1393 1407 "tz_kind": "relative",
1394 1408 "recurrence": { "pattern": "Weekly", "interval": 1, "weekdays": [0, 1, 2, 3, 4] },
1395 1409 }),
@@ -1401,20 +1415,32 @@
1401 1415 assert_eq!(got["tz_kind"], "relative");
1402 1416 assert_eq!(got["start_local"], "2026-08-03 06:00:00");
1403 1417
1404 - // Now the machine moves to Lisbon. The civil time is the truth, so the
1405 - // recompute must move the UTC instant to keep the wall clock at 06:00.
1406 - let lisbon: chrono_tz::Tz = "Europe/Lisbon".parse().unwrap();
1407 - let moved = goingson_core::tz::rematerialize_civil_events(&ctx.events(), ctx.user_id, lisbon)
1418 + // Now the machine moves somewhere the wall clock genuinely differs. Lisbon
1419 + // is the usual destination, but it shares its August offset with a band of
1420 + // European hosts, and on one of those nothing would move for the wrong
1421 + // reason; Tokyo covers that case.
1422 + let away = ["Europe/Lisbon", "Asia/Tokyo"]
1423 + .into_iter()
1424 + .map(|name| name.parse::<chrono_tz::Tz>().unwrap())
1425 + .find(|zone| {
1426 + start_at.with_timezone(zone).naive_local()
1427 + != start_at.with_timezone(&home).naive_local()
1428 + })
1429 + .expect("one of the two reads differently from the host zone");
1430 +
1431 + // The civil time is the truth, so the recompute must move the UTC instant
1432 + // to keep the wall clock at 06:00.
1433 + let moved = goingson_core::tz::rematerialize_civil_events(&ctx.events(), ctx.user_id, away)
1408 1434 .expect("recompute");
1409 1435 assert_eq!(moved, 1, "the relative event should have been remapped");
1410 1436
1411 1437 let after = call(&reg, "get_event", json!({ "id": id })).await;
1412 1438 // Civil truth untouched...
1413 1439 assert_eq!(after["start_local"], "2026-08-03 06:00:00");
1414 - // ...and the instant now reads 06:00 in Lisbon rather than in Denver.
1440 + // ...and the instant now reads 06:00 there rather than at home.
1415 1441 let start: chrono::DateTime<chrono::Utc> = after["start"].as_str().unwrap().parse().unwrap();
1416 1442 assert_eq!(
1417 - start.with_timezone(&lisbon).format("%H:%M").to_string(),
1443 + start.with_timezone(&away).format("%H:%M").to_string(),
1418 1444 "06:00"
1419 1445 );
1420 1446 }
@@ -9118,6 +9118,7 @@
9118 9118 .saved-views-save .field { flex: 1 1 auto; min-width: 160px; }
9119 9119 .saved-views-row { display: flex; gap: var(--gap-peer); align-items: center; }
9120 9120 .saved-views-row .saved-views-apply { flex: 1 1 auto; text-align: left; }
9121 + .saved-views-row .saved-views-apply[data-pinned] { font-weight: 700; color: var(--action); }
9121 9122 .saved-views-empty { color: var(--content-muted); }
9122 9123
9123 9124 /* command palette / search
@@ -67,7 +67,7 @@
67 67 const pinLabel = v.isPinned ? 'Unpin' : 'Pin';
68 68 html += `
69 69 <div class="saved-views-row">
70 - <button type="button" class="button button--sm saved-views-apply" data-act="savedViews._apply" data-a1="${escAttr(v.id)}">${esc(v.name)}${v.isPinned ? ' •' : ''}</button>
70 + <button type="button" class="button button--sm saved-views-apply"${v.isPinned ? ' data-pinned="true"' : ''} data-act="savedViews._apply" data-a1="${escAttr(v.id)}">${esc(v.name)}</button>
71 71 <button type="button" class="button button--sm" data-act="savedViews._togglePin" data-a1="${escAttr(v.id)}">${pinLabel}</button>
72 72 <button type="button" class="button button--sm button--danger" data-act="savedViews._delete" data-a1="${escAttr(v.id)}">Delete</button>
73 73 </div>`;