Notechondria

Version: 0.1.23 Build Date: 2026-04-15T03:00

What's Changed

Frontend — splash byproducts as structural formulas

  • The four cycle byproducts (CO2, NADH, FADH2, GTP) previously drawn as English-name text (_drawText) are now rendered as minimal skeletal structural formulas by a new _KrebsCyclePainter._drawByproductFormula.
    • CO2: O=C=O with two visible double bonds.
    • NADH: pyridine-like hexagon with ring N and the nicotinamide -C(=O)NH2 substituent + reduced-ring H.
    • FADH2: two fused hexagons (isoalloxazine stub) with N and =O side substituents and the two reduced-ring Hs.
    • GTP: purine (fused hexagon + pentagon) with three P circles (alpha, beta, gamma) linked by phosphate-bridge lines. These drawings are schematic (not IUPAC-complete) but they satisfy the "no English text" intent.
  • Byproduct flight distance / peak travel bumped slightly so the larger formula drawings fit clear of the active-metabolite glyph.

Frontend — debug log window (shared package)

  • New shared module notechondria_shared/lib/src/components/debug_log.dart owns the debug log contract:
    • DebugLogLevel enum: error | warning | info | debug.
    • DebugLogEntry: timestamped, level-tagged, source-tagged message with an optional durationMs (for timed backend calls). Persisted form is [iso] [L] source \u2014 message (Xms); legacy unprefixed strings are round-tripped as Debug-level entries.
    • DebugLogController: ChangeNotifier holding up to 200 entries plus a Map<String, Object?> cache provider callback.
    • DebugLogCard: rendered-log list with per-level color chips, a level-filter chip row (defaults to Debug = show everything), and an embedded mini-terminal supporting ls, cd <key>, cd .., pwd, clear, and help. The terminal navigates the in-memory cache snapshot the host app binds to its controller (maps -> list keys, lists -> numeric indices, leaves print a one-line summary).
  • flutter/services (Clipboard) is imported by the new module so the built-in Copy logs button falls back to clipboard when the host does not supply an onCopyLogs handler.
  • Exported from notechondria_shared.dart barrel.

Frontend — per-app wiring

  • editor_app, planner_app, portal_app each declare a DebugLogController _logController field, dispose it, and bind its cache provider to a new _snapshotLocalStore() method that mirrors the six _LocalAppStore buckets (settings, drafts, courses, stats, cache, logs) plus a redacted session entry (token_present + the profile, never the raw token).
  • Each app's _appendUiLog(String) is preserved as a thin Info-level wrapper and now also appends a DebugLogEntry to _logController. A richer _log({level, source, message, durationMs}) method is added on the same class so new code can emit structured entries.
  • Editor adds a _timed<T>(String source, Future<T> Function()) helper that wraps a backend call, logs duration at Debug level on success and at Error level on failure, and rethrows. Used to wrap the four high-signal bootstrap calls inside Editor._loadInitialData (getFrontPage, getCourses, getCourseNotes, listNotes). The bootstrap completion line now reads Initial Editor._loadInitialData data loaded (N categories, M notes). — replacing the former Initial data loaded. line per the TODO's "use Initial <what class>, <what function> data loaded" ask.
  • Planner and portal use the lighter-touch wiring only (controller + cache provider + settings widget swap). No per-request timing instrumentation this round.

Frontend — settings surface

  • Each app's _SettingsPage gained an optional debugLogController: DebugLogController? parameter. When supplied the "Debug log" card renders the shared DebugLogCard; otherwise the previous string-list view is preserved so the widget stays drop-in compatible.
  • Each app_shell._SettingsPage(...) call site now passes debugLogController: _logController.

Files Changed

New

  • frontend/notechondria_shared/lib/src/components/debug_log.dart
  • docs/versions/0.1.23.md (this file)

Modified

  • frontend/notechondria_shared/lib/notechondria_shared.dart — exports DebugLogCard, DebugLogController, DebugLogEntry, DebugLogLevel.
  • frontend/notechondria_shared/lib/src/components/splash_screen.dart — replaces byproduct text labels with _drawByproductFormula.
  • frontend/editor_app/lib/app_shell.dart — new _logController + _log + _timed + _snapshotLocalStore; _appendUiLog rewritten as a wrapper; _loadInitialData wraps 4 client calls with _timed; the "Initial data loaded" line now names class + method; settings call site passes debugLogController.
  • frontend/editor_app/lib/modules/settings.dart — new debugLogController param; _buildDebugSection short-circuits to DebugLogCard when available.
  • frontend/planner_app/lib/app_shell.dart — same controller wiring.
  • frontend/planner_app/lib/modules/settings.dart — same settings swap.
  • frontend/portal_app/lib/app_shell.dart — same controller wiring.
  • frontend/portal_app/lib/modules/settings.dart — same settings swap.
  • VERSION — 0.1.22 -> 0.1.23.
  • docs/TODO.md — completed debug-log items removed; splash byproduct item removed.

Verification

  • notechondria_shared: flutter analyze — no new errors (2 pre-existing surfaceVariant deprecations unchanged).
  • Each of editor_app / planner_app / portal_app:
    • flutter analyze — issue count unchanged vs 0.1.22 (all infos / pre-existing warnings; no new errors).
    • flutter test test/smoke_test.dart -r compact — passes.

Notes / follow-ups

  • Planner / portal still emit mostly Info-level _appendUiLog strings; per-request timing instrumentation is editor-only this round. Adding _timed wrappers in planner/portal bootstrap is a straightforward follow-up when those apps' bootstrap surface stabilizes.
  • The terminal's ls/cd navigates the in-memory _LocalAppStore buckets only (not the browser filesystem). Log entries from Debug-level timed calls use short ClassName._method source strings; individual call sites can adopt that convention incrementally.
  • Note-view local-category delete semantics remain pending in docs/TODO.md (next round).
  • Planner / portal app_shell.dart still needs the 0.1.20 editor_app invalid-token session-clear and bind-without-token short-circuit replicated (pre-existing bug from docs/TODO.md).