Lab Architect / Ellsworth

Afternoon Brief

Saturday, September 26, 2026 — Eighteenth consecutive night with no nightly-branch build on any app. There is no feature/nightly-20260926 or feature/nightly2-20260926 branch, and git log --all --since="36 hours ago" is empty on all four app repos. Codebase health: 0 analyzer issues on all four apps (git archive main snapshots). Buildr+/Closr+/Inspectr+ still hold 4/6/7 unpushed commits. A new morning brief landed today, the first since Sept 21. Two corrections to it: (1) its DailyReportr+ "Jump to the First Missing Field" idea already exists as _revealFirstInvalidActivityName(), and (2) its "latest commit" for Buildr+ and DailyReportr+ reads the parked off-main working copies, not main. The Buildr+ filtered-empty-state bug it raised is real and confirmed in code (Recommendation #1). Source note: /Volumes/Media/App Dev/ is still missing. This run used ~/Documents/Applications/<App>.

Last Night’s Builds

No nightly-branch build on any app, eighteenth night running missed

Ran a fresh git fetch origin --prune on all four repos. There is no *nightly*2026092[56] branch on any remote, and nothing has been committed on any branch in 36 hours. Yesterday's assignments (Dominique → Buildr+ Submittal Attachment Bundle, Katey → DailyReportr+ green tokens) were not picked up. Today's Fountainhead morning report again shows the nightly build-review producer MISSING (log tail still ends Sept 6). Hermes now reports UP with no gateway-restart warning, but the builders still didn't run. That weakens yesterday's theory that the stale gateway was the whole cause. The builder launch jobs themselves need checking.

Buildr+ 4 commits unpushed · working copy off main

Local main head a7a5a03 (Sept 21) is 4 ahead / 0 behind origin/main (33c825f, Sept 18). The working copy is still on fix/project-card-contract-value-spacing. Unchanged.

Closr+ 6 commits unpushed · 1,645 tracked vendored files

Local main head 0925b0b (Sept 21) is 6 ahead / 0 behind origin/main (7a3ca21). git ls-files node_modules still lists 1,645 files, all deleted on disk. The only other working-tree entries are untracked .worktrees/, worktrees/, and .env.bak-20260913-signin. Unchanged.

Inspectr+ 7 commits unpushed

Local main head 8145093 (Sept 21) is 7 ahead / 0 behind origin/main (4140149, Sept 8). origin/main has been silent for 18 days.

DailyReportr+ silent 12 days · working copy 105 behind main

main = origin/main = 0433f44 (Sept 14, 3.8.1 TestFlight prep). The working copy is still parked on the Aug 11 fix/owner-report-media-web branch with uncommitted WIP. That is why the morning brief reports af49e33 (Aug 11) as the "latest commit".

Codebase Health

App Analyzer Issues Breakdown Last 3 Commits (local main)
Buildr+ 0 dart analyze lib on git archive main: "No issues found!" Raw Colors.green: 0. Behavior bug: the projects list shows the first-run "No projects yet" empty state for any zero-match search or filter (Recommendation #1). a7a5a03 merge harden-ios-release-gate • a2873c3 merge project-card spacing fix • fac04bd source protected secrets file (unpushed)
Closr+ 0 "No issues found!" Raw Colors.green: 0. Repo hygiene: the 1,645 vendored node_modules/ files are still tracked (yesterday's Recommendation #1, open). The Procore client secret is still in-app. 0925b0b merge harden-ios-release-gate • d4c8952 gate TestFlight IPA on client IDs • ca33394 bump TestFlight 2.32.75 (unpushed)
Inspectr+ 0 "No issues found!" Raw Colors.green: 29 across 13 files (unchanged). 8145093 merge Google sign-in client-ID fix • 5e0849b merge harden-ios-release-gate • 744cc12 add iOS artifact gate (unpushed)
DailyReportr+ 0 "No issues found!" Raw Colors.green: 40 across 8 files (unchanged, yesterday's Recommendation #2). 0433f44 prepare 3.8.1 TestFlight • 2495d04 merge keyboard-recovery fix • 7253e65 stop keyboard recovery stranding text field (pushed)

Analyzer counts: Buildr+ 0 · Closr+ 0 · Inspectr+ 0 · DailyReportr+ 0. There were no commits, so nothing got worse. The open risks haven't changed: 17 unpushed commits across three apps, two working copies parked off main, and Closr+'s vendored JS tree.

Recurring Themes from Morning Briefs

Sources: the Sept 26, 21, and 20 morning briefs (briefs/2026-09-26.html is new today, after a five-day gap) and today's Fountainhead morning report.

Feature Ideas + UI/Code Health Recommendations

2 new recommendations: 1 UI health and 1 feature. Both were dedup-checked today with grep over lib/ on main snapshots and with git log --all. Rejected on dedup: the morning brief's DailyReportr+ "Jump to the First Missing Field" already ships. manual_daily_report_page.dart:472 calls _revealFirstInvalidActivityName() (line 528), which focuses the first empty activity name and runs Scrollable.ensureVisible. Yesterday's three recommendations (Closr+ node_modules, DailyReportr+ green tokens, Buildr+ attachment bundle) are still open and still valid. They aren't repeated here.

1. Honest Filtered Project Empty State Buildr+ — UI Health

In lib/pages/projects/projects_list_page.dart, filtered (line 165) applies both the search text and the ProjectStatus chip. The if (filtered.isEmpty) branch at line 181 then always renders "No projects yet", "Create your first project to get started", and a Create Your First Project button. A superintendent with 30 projects who types a typo, or taps the "Closed" chip with no closed jobs, is told they have no projects and is invited to create one. That is misleading and invites duplicate projects. No "No matching projects" copy exists anywhere in lib/. The only related history is 1d811be (v3.1.1, which added the empty-state button), with no filtered-state handling.

Why now: the Sept 26 morning brief raised it, and the code confirms it. It's a one-file fix plus a test that leaves the codebase measurably cleaner, which fits the "fix the misleading UI before adding features" standard.

Sketch: Branch on projects.isEmpty versus filtered.isEmpty. For the filtered case, show Icons.search_off, "No matching projects", a subtitle that echoes the active query and status, and a Clear filters TextButton that resets _search, the search controller, and _filter. Extract a shared ProjectsEmptyState widget so the doc_control_list_page.dart:98 copy uses the same icon size and adaptive color (see UI Inconsistencies). Add test/projects_list_filtered_empty_test.dart with 3 project fixtures: search "zzz" shows "No matching projects" and not "Create Your First Project", Clear filters restores all 3, and an empty source list still shows the first-run CTA.

2. Search Earlier Document Versions Closr+ — Feature

Closr+ already versions documents: DocumentService has getVersionHistory() (line 291), createNewVersion() (311), and restoreVersion() (346). But documents_page.dart's _applySearch (line 347) only matches current documents. A closeout manager hunting for "the Rev 2 O&M manual the owner signed off on" has to guess which current document it lives under and then open its history. grep -rn "Earlier versions\|searchVersions\|versions/search" lib and git log --all | grep -iE "version (search|history)|archived version" are both empty.

Why now: it comes from the Sept 26 morning brief and builds on existing version plumbing, so no new storage is needed. Revision identity at handover is the recurring intel theme: Fieldwire's version comparison and as-built exports, and Procore's pins that survive revisions.

Sketch: Add an owner-scoped Worker route GET /api/documents/versions/search?q= that queries D1 for superseded versions by filename or version number and returns {versionId, versionNumber, parentDocumentId, parentTitle, createdAt}. When _searchQuery is non-empty, render a collapsible "Earlier versions" section below the current results. Tapping a result opens the existing version-history sheet scrolled to that version. Restore stays behind its existing confirmation, with no one-tap restore from search. Offline, show "Earlier versions need a connection" instead of an empty list. Tests: duplicate filenames across parents, version-number queries ("v2", "rev 3"), and the offline message.

UI Inconsistencies

Competitive Intel

Tomorrow’s Build Suggestion

The builders haven't run in 18 nights, and Hermes now reports UP, so check the builder launch jobs directly (the 00:15 and 01:15 schedules). The picks stay on the two stalest apps, but Dominique's task is now smaller so a restarted builder can finish it in one night. Owner action before either build: push the unpushed main commits (Buildr+ 4, Closr+ 6, Inspectr+ 7). For Closr+, use explicit paths rather than git add -A.

Dominique → Buildr+

Task: Honest Filtered Project Empty State plus a shared empty-state widget and widget test (Recommendation #1), starting from main. If time remains, start the Submittal Attachment Bundle. Rationale: Buildr+ hasn't had a nightly feature since Aug 5. This is a confirmed user-facing bug that takes one night to fix and leaves a new test behind.

Katey → DailyReportr+

Task: Tokenize the 40 raw greens to AppColors.primaryGreen and add the no_raw_material_green_test.dart guard (carried over from yesterday), starting from main. Rationale: this is the stalest app (12 days), the change is mechanical and low-risk, and the test locks in 40 → 0.