Lab Architect / Ellsworth

Afternoon Brief

Sunday, September 27, 2026 — Nineteenth consecutive night with no nightly-branch build on any app. There is no feature/nightly-20260927 or feature/nightly2-20260927 branch, and git log --all --since="42 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. Today's morning brief raised two honesty bugs, and both are confirmed in code. DailyReportr+ sync receipts always say "Sync Complete", and unknown statuses load as accepted (Recommendation #1). The Closr+ portfolio subcontractor view silently drops projects that fail to load (Recommendation #2). Correction to the morning brief: it again reports "latest commit" for Buildr+ (b983e74) and DailyReportr+ (af49e33, Aug 11) from off-main working copies. The real main heads are a7a5a03 and 0433f44. Source note: /Volumes/Media itself is now absent, not just App Dev/. This run used ~/Documents/Applications/<App>, which is readable again today.

Last Night’s Builds

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

Ran git fetch origin on all four repos. There is no *nightly*2026092[5-7] branch on any remote, and no branch has a commit in 42 hours. Yesterday's assignments (Dominique → Buildr+ Honest Filtered Project Empty State, Katey → DailyReportr+ green tokens) were not picked up. Today's morning brief says the recurring review producer "was retired" and that Hermes is up. That explains the missing review, but not the missing builds. The 00:15 and 01:15 builder launch jobs still need to be checked directly.

Buildr+ 4 commits unpushed · working copy off main

Local main head a7a5a03 (Sept 21) is 4 ahead / 0 behind origin/main (33c825f). 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 status still shows 1,648 entries, almost all of them the deleted-but-tracked node_modules/ tree. 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 19 days.

DailyReportr+ silent 13 days · working copy off 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 4 modified tracked files.

Codebase Health

App Analyzer Issues Breakdown Last 3 Commits (local main)
Buildr+ 0 dart analyze lib on git archive main: "No issues found!" The filtered "No projects yet" empty-state bug (yesterday's Recommendation #1) is still open. a7a5a03 merge harden-ios-release-gate • a2873c3 merge project-card spacing fix • fac04bd source protected secrets file (unpushed)
Closr+ 0 "No issues found!" Silent error swallowing: cross_project_subcontractor_provider.dart:90 uses catch (_) {} per project, and line 70 maps a project-load error to []. There are 5 bare catch (_) blocks in lib/providers. The tracked node_modules/ and in-app Procore secret are still open. 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 (no commits, so 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 (re-counted today). Test gap: there are no tests for SyncReceipt or SyncReceiptStatus.fromString (ls test | grep receipt is empty). 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. The analyzer is clean, but today's two confirmed bugs are the kind it can't catch: default-to-success enums and swallowed exceptions. Both fixes below come with tests.

Recurring Themes from Morning Briefs

Sources: the Sept 27, 26, and 21 morning briefs (briefs/).

Feature Ideas + UI/Code Health Recommendations

There are 2 new recommendations: 1 UI/code health item and 1 feature. Both came from today's morning brief and were verified against main snapshots with grep and git log --all. The only prior receipt work is 80ca0b4 "Offline Sync Receipt (v2.18.0)", which created the sheet. The only prior portfolio work is 4e4b2b1, the "All Subcontractors" quick action. Neither handles failure honestly. Deferred: the morning brief's Closr+ "Project Scope on Portfolio Subcontractors" filter. It's valid (the page has only risk chips and text search, and search already matches project name), but it should wait until #2 lands. Yesterday's four recommendations are still open and still valid: Closr+ node_modules, DailyReportr+ green tokens, Buildr+ filtered empty state, and Closr+ version search.

1. Sync Receipts That Tell the Truth DailyReportr+ — UI/Code Health

There are two defects in the receipt path. (a) lib/pages/sync/sync_receipt_sheet.dart:81 hard-codes the header "Sync Complete" with CupertinoIcons.checkmark_circle_fill (line 69). When a receipt contains failed or needs-review items, the header only turns the checkmark orange, so a superintendent still reads "complete" above a red "Failed" chip. (b) SyncReceiptStatus.fromString (lib/models/sync_receipt.dart:47) has default: return SyncReceiptStatus.accepted. Any null, misspelled, or future status stored by SyncReceiptItem.fromMap (line 120) is counted as delivered. There are no receipt tests.

Why now: it's today's morning-brief idea #1, confirmed line by line. It's the cheapest instance of the recurring "UI claims success" theme. Procore's Daily Log iOS flow (offline entries plus "Fix Errors") shows the competitive bar, which is to separate "saved locally" from "accepted by server".

Sketch: Change the fromString default to failed and log the raw value. Add a SyncReceipt.headline getter: "Sync Complete" only when !hasIssues, "Synced with N issues" when there's review work only, and "N items didn't sync" when failedCount > 0. Reuse the icon logic already in sync_history_page.dart:132 (exclamationmark_triangle_fill when hasIssues) so the sheet and history agree. While in the file, replace the 18 isDark ternaries with the existing AdaptiveColors extension (app_colors.dart:73). Add test/sync_receipt_test.dart covering unknown and null status → failed, the mixed-receipt headline, and the all-accepted headline. Add a widget test asserting that "Sync Complete" is absent when failedCount > 0. Don't touch SyncManagerService reconciliation.

2. Honest Partial Portfolio Compliance Closr+ — Feature

There are three ways allProjectSubcontractorsProvider (lib/providers/cross_project_subcontractor_provider.dart:63) hides missing data. (1) A load error on allProjectsProvider maps to <Project>[] (line 70). (2) Its loading state also maps to [] (line 69), so the page briefly computes an empty portfolio. (3) Each project's getSubcontractors failure is swallowed with catch (_) { // Skip projects } (line 90). portfolioComplianceSummaryProvider then computes the compliance % banner from whatever survived. A PM with one project offline sees a clean percentage for an incomplete portfolio, with no indication that anything is missing.

Why now: it's today's morning-brief idea #2, and closeout compliance is Closr+'s core promise. It removes a silent catch (_) instead of adding one. Fieldwire's selective-sync docs make the same point: an incomplete offline set must never read as complete.

Sketch: Return a PortfolioSubsResult { items, failedProjects: List<Project> }, and use await ref.watch(allProjectsProvider.future) so errors propagate instead of becoming []. In cross_project_subcontractors_page.dart, show an amber "Some projects couldn't load (N) — Retry" banner above _PortfolioSummaryBanner, and replace the $pct% (line 336) with "Incomplete" while failedProjects is non-empty. Keep the risk-ranked list for projects that loaded. Tests: one failing project (banner shown, % suppressed), all projects failing (error state, not "no subcontractors"), and all succeeding (unchanged).

UI Inconsistencies

Competitive Intel

Tomorrow’s Build Suggestion

This is the nineteenth night without builders, so check the 00:15 and 01:15 builder launch jobs directly, because Hermes being UP hasn't been enough. Both picks are one-night, test-backed honesty fixes that start from main. Owner action before either build: push the unpushed main commits (Buildr+ 4, Closr+ 6, Inspectr+ 7). For Closr+, stage explicit paths rather than using git add -A.

Dominique → Buildr+

Task: Honest Filtered Project Empty State, with a shared empty-state widget and widget test (carried over from yesterday, still unbuilt). Rationale: Buildr+ hasn't had a nightly feature since Aug 5. It's a confirmed misleading-UI bug in one file.

Katey → DailyReportr+

Task: Sync Receipts That Tell the Truth (Recommendation #1), with the new sync_receipt_test.dart. The green-token cleanup moves behind it. Rationale: this is the stalest app (13 days). Misreporting field evidence as delivered is a bigger risk than a color mismatch, and the fix adds the app's first receipt tests.