Lab Architect / Ellsworth
Afternoon Brief
Friday, October 2, 2026 — Twenty-fourth consecutive night with no nightly-branch build on any app. There is no feature/nightly-20261002 or feature/nightly2-20261002 branch, and git log --all --since="30 hours ago" is empty on all four app repos. Codebase health: 0 analyzer issues on all four apps. No morning brief was published today (briefs/ stops at Oct 1; only the Fountainhead report exists), so today's recommendations come from a direct code sweep. That sweep turned up something the analyzer can't see: 57 Dart files across the four apps that nothing imports. Among them is Closr+ Connected Sources, which has had no entry point since Apr 25, yet three briefs in the past week recommended hardening it. That item is pulled from the build queue below.
Last Night’s Builds
No nightly-branch build on any app, twenty-fourth night running missed
Ran git fetch origin on all four repos. No new nightly branches exist; the newest on any remote are still feature/nightly-20260908 and feature/nightly2-20260909. The held assignments (Dominique → Buildr+ Deletes That Wait for the Server; Katey → DailyReportr+ reports_page.dart rework) went unclaimed for a fifth day. morning-reports/2026-10-02.md shows Hermes UP and the retired nightly-review artifacts MISSING. Neither morning source mentions the 00:15 and 01:15 builder jobs. ~/memory/last-nightly-build.md (the builder coordination file) was last updated Aug 5.
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 · tracked node_modules
Local main head 0925b0b (Sept 21) is 6 ahead / 0 behind origin/main (7a3ca21). git status still lists the deleted-but-tracked node_modules/ files. Unchanged.
Inspectr+ 7 commits unpushed
Local main head 8145093 (Sept 21) is 7 ahead / 0 behind origin/main (4140149, Sept 8). origin/main has had no new commits for 24 days.
DailyReportr+ silent 18 days · working copy off main
main = origin/main = 0433f44 (Sept 14, 3.8.1 TestFlight prep). The working copy is still on the Aug 11 fix/owner-report-media-web branch with modified tracked files.
Codebase Health
| App | Analyzer Issues | Unimported files | Breakdown | Last 3 Commits (local main) |
|---|---|---|---|---|
| Buildr+ | 0 | 16 | "No issues found!" New: six pages the owner approved for retirement on 2026-08-08 (docs/ux/buildrplus-feature-effectiveness-audit.md) lost their routes in 85364d3, but their files stayed in lib/: 4,527 lines. ActivityLogTimeline and LinkedDocumentsSection are also never mounted, and nothing calls ActivityLogService.log. Still open: the 10 unguarded onDismissed deletes and ProjectCard semantics. |
a7a5a03 merge harden-ios-release-gate • a2873c3 merge project-card spacing fix • fac04bd source protected secrets file (unpushed) |
| Closr+ | 0 | 12 | "No issues found!" New: connected_sources_page.dart (1,592 lines) has had no importer since 492ce70 (Apr 25, "remove redundant … Connected Sources cards"). Its provider and service (539 lines) are reachable only through that page. Also unimported: punch_list_page, punch_item_form_page, client_portal_page, import_from_procore_page, dashboard_page, and closeout_readiness_card. Still open: the isExpiringSoon boundary gap, the silent portfolio catch (_), and tracked node_modules/. |
0925b0b merge harden-ios-release-gate • d4c8952 gate TestFlight IPA on client IDs • ca33394 bump TestFlight 2.32.75 (unpushed) |
| Inspectr+ | 0 | 18 | "No issues found!" Unimported files include auth_page_fixed.dart, paywall_timer_debug_widget.dart, debug_platform_widget.dart, glass_container/glass_dialog, and sync_history_page.dart. The last one was deliberately unlinked in f447ac2 (Jun 16), so it should be deleted, not revived. Still open: the tapped-photo bug (2 entry points). Raw Colors.green: 29. |
8145093 merge Google sign-in client-ID fix • 5e0849b merge harden-ios-release-gate • 744cc12 add iOS artifact gate (unpushed) |
| DailyReportr+ | 0 | 11 | "No issues found!" Unimported files: whole equipment, tasks, materials, checklists, gallery, and notes pages, plus daily_report_edit_view.dart. Still open: the admin reports retry loop, the duplicated _buildReportCard with its fake "1 activity" badge, the eager Reports list, and 40 raw Colors.green. |
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, from dart analyze lib on git archive main snapshots (after flutter pub get --offline). Unimported files is a new, conservative metric: a lib/ file whose basename appears in no import/export in lib/ or test/ (excluding main.dart and *.g.dart). The total is 57. It undercounts dead code, because files used only by a dead file (such as the Closr+ link provider and service) aren't included. The analyzer doesn't report unused public classes, which is why "0 issues" has hidden this.
Recurring Themes from Morning Briefs
Sources: the Oct 1, Sept 30, and Sept 29 morning briefs (briefs/). There is no Oct 2 morning brief, only morning-reports/2026-10-02.md.
- Failure must look like failure: this is still the dominant theme, with 10+ honesty bugs raised since Sept 27 and 0 built. Today's sweep adds two more silent collapses in Buildr+:
ActivityLogTimelineandLinkedDocumentsSectioncatch load errors withcatch (_) {}and renderSizedBox.shrink(). They're unmounted for now, but Recommendation #3 would put one on screen, so it must fix this first. - Closr+ Connected Sources: correction. The Sept 27, Sept 29, and Oct 1 briefs (and the Oct 1 afternoon queue) all targeted
connected_sources_page.dart/project_link_service.dart. Users can't reach that page. Its only entry card was removed in492ce70on Apr 25. The bugs are real in the code but not live for users. Removed from the build queue pending an owner decision (Recommendation #1). - Field navigation should respect where the user was: the Inspectr+ tapped photo, the "Photo N of M" label, and DailyReportr+ return-to-Today are all still unbuilt. The Inspectr+ fix stays first in the queue.
- Stay honest about scope against competitors: the morning briefs warn against chasing Procore On the Clock. Today's intel adds Procore's shipped Workflows Step Override (with attribution history). Recommendation #3 answers it with the smallest honest version: a recorded status history.
- Automation stall: 24 nights. No source reports on the builder launch jobs.
Feature Ideas + UI/Code Health Recommendations
There are 3 recommendations: 2 UI/code health items and 1 feature. With no morning brief today, all three come from a code sweep of main snapshots. Each was checked with grep and git log -S/--all: no commit has wired the activity log, and no orphan guard exists in any repo. The held Sept 28 items (Buildr+ server-confirmed deletes, DailyReportr+ admin failure state) still outrank these.
1. Decide Connected Sources Before Anyone Hardens It Closr+ — UI/Code Health (dead feature / correction)
ConnectedSourcesPage (lib/pages/projects/connected_sources_page.dart, 1,592 lines) has zero references anywhere in lib/ or test/. On Apr 25, 492ce70 ("remove redundant Import Data and Connected Sources cards from Overview tab") deleted _buildConnectedSourcesCard, the only MaterialPageRoute to it, from project_detail_page.dart. project_link_provider.dart and project_link_service.dart (539 lines) are imported only by that page. import_from_procore_page.dart (719 lines), the other half of that card pair, is also unimported. So the _markSynced-on-failure bug (Sept 29), the unlink race, and the missing try/catch (Oct 1) can't affect users today. Yesterday's afternoon brief queued all of them for a builder anyway.
Why now: it stops a builder from spending a night hardening code no one can open. It also removes about 2,850 lines of unreachable Closr+ code if retired. The pattern repeats on the Buildr+ side (Recommendation #2).
Sketch: Owner decision (one line): retire or restore. Retire (default, matching the Apr 25 "redundant" message): delete the page, provider, service, and import_from_procore_page.dart in one commit, and keep the D1 tables and Worker routes until a separate backend cleanup. Restore: re-add one entry point in Project Detail and land the Sept 29 + Oct 1 fixes together with the first service and widget tests. Either way, the change should leave the unimported-file count for Closr+ lower.
2. Finish the Approved Retirements, Then Guard Against New Orphans Buildr+ (pilot) → all apps — UI/Code Health (dead code + test)
The Aug 8 simplification (85364d3, "simplify Buildr project workspaces") removed routes to six pages: RFI Impact Tracker, RFI Field Verification, RFI Action Checklist, RFI Location Assist, Submittal Commitment Tracker, and Submittal Review Radar. The owner approved all six for retirement on 2026-08-08 in docs/ux/buildrplus-feature-effectiveness-audit.md, which calls Commitment Tracker "fabricated" and Field Verification/Action Checklist "in-memory only". Their page files (4,527 lines) are still in lib/, along with providers and services only they use. Submittal Review Radar got a nightly polish on Aug 5, three days before it was retired. The same thing is happening across all four apps: 16/12/18/11 files that nothing imports. Some are obviously stale, like Inspectr+ auth_page_fixed.dart and paywall_timer_debug_widget.dart. Because the analyzer stays at 0, none of this shows up in health checks, and builders and briefs keep finding "bugs" in code that never runs.
Why now: under the "leave it cleaner" standard, this is the largest code-health gain available, and it's mostly deletion that was already approved. Buildr+ already has test/simplification_route_inventory_test.dart, so a reachability test fits right next to it.
Sketch: (a) In Buildr+, delete the six retired pages plus their now-unused providers and services. Re-run dart analyze until it reports 0 again, and keep the inventory test green. (b) Add test/no_orphan_files_test.dart: walk the import/export graph from lib/main.dart, then fail with a list of unreachable lib/**.dart files, minus a small commented allowlist. (c) Port the test to the other three apps once each one has been triaged; start with the Inspectr+ debug and auth leftovers. Only delete what has an owner retirement or is clearly a debug/duplicate file. List anything ambiguous, such as the DailyReportr+ equipment/tasks/materials pages, for the owner instead.
3. Submittal Status History (Who Changed It, From What, When) Buildr+ — Feature
Buildr+ already has a complete activity log stack, but it's never been connected. ActivityLogService.log(documentId, documentType, action, oldValue, newValue, performedBy) writes to the activity_logs support record. ActivityAction.statusChanged exists. ActivityLogTimeline renders a collapsible timeline. However, nothing in lib/ calls log() and nothing mounts the timeline. Today, saving a submittal in submittal_detail_page.dart:251 (updateSubmittal(copyWith(status: _status, …))) overwrites the status with no trace, and so does the Bulk Edit sheet. When an architect asks "who marked this Approved?", the app can't answer.
Why now: Procore shipped Workflows Step Override on Sept 29, which lets users advance a stalled approval with required documentation and attribution history (intel below). An honest status trail is the small, in-scope version of that for Buildr+ submittals. It also turns three dead files into used code instead of adding new ones.
Sketch: In _save(), when editing and widget.submittal!.status != _status, call ActivityLogService().log(action: statusChanged, oldValue: old.name, newValue: _status.name, documentType: 'submittal') only after updateSubmittal succeeds. Do the same per item in the bulk path. Mount ActivityLogTimeline(documentId: submittal.id) on the existing-submittal detail view. Before mounting, fix the timeline's catch (_) {} so a failed load shows "Couldn't load history · Retry" instead of disappearing, and give getLogsForDocument a projectId so it stops listing every activity_logs row client-side. Tests: a status change writes one entry, an unchanged save writes none, a failed update writes none, and a timeline load error shows the retry state.
UI Inconsistencies
- Buildr+ back affordance: 9 reachable pages use a custom
Icons.arrow_back_iosleading button:security_page,profile_page,rfi_aging_page, the submittal aging, auto-deadline, watchlist, exception-digest, and escalation-rules pages, andwizard_shell. The rest of the app uses the platform defaultAppBarback button, so Android users get iOS chevrons on some screens and Material arrows on others. Five more instances sit in the retired pages and would go away with Recommendation #2. - Buildr+ silent empty vs. real empty:
LinkedDocumentsSectionshows "No linked documents" when the list is empty, but shows nothing at all (SizedBox.shrink) when loading fails or is still in progress.ActivityLogTimelinerenders nothing in all three cases. "Failed", "loading", and "none" all look the same. This must be fixed before Recommendation #3 puts the timeline on screen. - Inspectr+ raw error copy: the (unreachable)
SyncHistoryPageshows'Error loading sync history: $e', which is a raw exception string. A grep forText('Error…: $e')/Text('Failed…: $e')finds 71 in Buildr+, 61 in Closr+, 18 in Inspectr+, and 50 in DailyReportr+ (all files, including unreachable ones). That's worth a sharedErrorStatewidget, adopted page by page as each one is touched. Low priority today. - Carried over, unchanged (no commits): the Inspectr+ gallery opens on photo 1 regardless of which thumbnail was tapped. The DailyReportr+ "Today" pill looks tappable but isn't. Buildr+ project-card mini-chips are identical on every card. DailyReportr+ has the fake "1 activity" badge in two duplicated cards. Buildr+ swipe backgrounds use raw
Colors.redon 10 pages.Icons.arrow_back_iosis in 8 Closr+ files. RawColors.green: DailyReportr+ 40, Inspectr+ 29, Buildr+ 0, Closr+ 0. The Closr+ Connected Sources items are no longer listed here because that page is unreachable (Recommendation #1).
Competitive Intel
- Procore Workflows: Step Override (shipped Sept 29). Authorized users can advance a stalled approval step by supplying documentation, and the override is kept in attribution history. This applies directly to Buildr+ submittal and RFI approvals. It's the basis for Recommendation #3, scoped down to a recorded status trail and not a workflow engine. dated Sept 29, available now, new to this brief [source]
- Procore My Open Items: grouping, saved views, and new filters (announced Sept 29, available Oct 13). Users can group a personal cross-project to-do list by project, due date, or item type and save the view. It's a benchmark for "what needs me today" lists like Buildr+ Needs Attention and the Closr+ portfolio view. Announced, not shipped. announced, ships Oct 13, new to this brief [source] [releasebot]
- Autodesk Build mobile: sync a chosen subset of Forms for offline use, from Autodesk's "September product releases" summary. This is relevant to Inspectr+ and DailyReportr+ offline capture. date unverified, current capability (Autodesk's September posts mix years, and the blog returns 403 to fetch.) [source]
- Last ~7 days, otherwise: Procore On the Clock timesheets (Oct 13) and Daily Log negative quantities were already reported Oct 1. Procore also announced a Permissions redesign (open beta, Oct 13) and Project Date Variance Hub cards (Oct 13), but neither fits our app surface. The Bluebeam result was Revu 21.6 "Markups on Capture", which is not new. No dated, in-window Fieldwire or PlanGrid ship was found.
Tomorrow’s Build Suggestion
This is the twenty-fourth night without builders. The assignments stay held (fifth day). Queue change: the Closr+ Connected Sources hardening pass is removed until the owner decides to retire or restore it (Recommendation #1). Owner actions before either build: check the 00:15 and 01:15 builder launch jobs, push the unpushed main commits (Buildr+ 4, Closr+ 6, Inspectr+ 7), and give the one-line Connected Sources decision. For Closr+, stage explicit paths rather than using git add -A.
Dominique → Buildr+
Task: Deletes That Wait for the Server (Sept 28 Recommendation #1). If time remains, delete the six owner-retired pages (Recommendation #2a), which is pure deletion with the inventory test as a safety net. Rationale: Buildr+ hasn't had a nightly feature since Aug 5. A delete that can hide a live project is still the top honesty bug, and the retirement cleanup removes about 4.5k lines no one can reach.
Katey → DailyReportr+
Task: a single reports_page.dart rework: Admin Reports That Admit Failure, then the shared ReportSummaryCard without the fake "1 activity" badge, then a lazy SliverList. Rationale: it's the stalest app (18 days on main), and all three fixes target the same file, which is reachable (unlike the 11 unimported DailyReportr+ files). Queued next for whichever builder frees up first: the Inspectr+ tapped-photo fix, then Buildr+ Submittal Status History (Recommendation #3).