Lab Architect / Ellsworth
Afternoon Brief
Saturday, October 3, 2026 — Twenty-fifth consecutive night with no nightly-branch build on any app. There is no feature/nightly-20261003 or feature/nightly2-20261003 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. A morning brief was published today, but none of its three ideas survived verification. Two of them fix offline-queue code that nothing feeds: in both Closr+ and Buildr+, SyncManagerService.queueOperation has zero callers, and neither app shows sync status on screen. The third (DailyReportr+ jump to the first invalid field) shipped Aug 21 in c5bc882. This is the second time a morning brief has re-proposed it (first on Sept 26).
Last Night’s Builds
No nightly-branch build on any app, twenty-fifth 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 sixth day. morning-reports/2026-10-03.md shows Hermes UP and the nightly-review artifacts MISSING (last log line Sept 6). It says nothing about 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 1,648 changed paths, nearly all 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 25 days.
DailyReportr+ silent 19 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 today: the offline write queue has no producers. SyncManagerService.queueOperation (lib/services/sync/sync_manager_service.dart:70) and LocalDatabase.queueOperation are never called, so syncNow() always replays an empty queue. OfflineBanner, the only consumer of syncStatusProvider, is never mounted (the one hit is its own doc comment). These files are imported, so the unimported-file metric doesn't catch them. Still open: 10 unguarded onDismissed deletes and the 6 owner-retired pages. |
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 today: the same producer-less queue. queueOperation has zero callers; project_service.dart and punch_item_service.dart only use hasConnectivity() and the cache helpers. syncStatusProvider, pendingSyncCountProvider, and isOfflineProvider have no watchers. None of the four AppHeader( call sites passes syncStatus:, so the "All changes saved" chip (app_header.dart:162) never renders. Still open: the isExpiringSoon boundary gap, the silent portfolio catch (_), tracked node_modules/, and the Connected Sources retire/restore decision. |
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!" This is the only app with a mounted sync indicator: SyncOutboxBanner on projects_hierarchy_page.dart:165. Still open: the tapped-photo bug (2 entry points), debug/auth leftovers among the unimported files, and 29 raw Colors.green. |
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!" Confirmed today: on Save, the manual report form already focuses and scrolls to the first empty activity name (_revealFirstInvalidActivityName, manual_daily_report_page.dart:528, from c5bc882 on Aug 21). Activity name is the form's only required: true field, so nothing is left uncovered. 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 fresh git archive main snapshots (after flutter pub get --offline) in /private/tmp/afternoon-brief-20261003/. Unimported-file counts (57 total) are carried from Oct 2. No commits landed on any main, so they can't have changed. Today's finding shows a gap in that metric: a file can be imported and still have whole APIs (queue writers, status providers, banners) that nothing calls or mounts.
Recurring Themes from Morning Briefs
Sources: the Oct 3, Oct 1, and Sept 30 morning briefs (briefs/). There was no Oct 2 morning brief.
- Sync and queue honesty: this theme came up again today with Closr+ "Tell the Truth About Queued Changes" and Buildr+ "Reject Unknown Queued Write Types", following the Sept 29 Closr+
_markSynceditem. Correction: both of today's targets are unreachable, the same problem as Connected Sources on Oct 2. No code in either app enqueues anything, and neither app renders sync status. The Closr+ "All changes saved" chip that the brief warns about never appears, and the Buildr+ replay switch never receives an operation. The right fix is to remove the false promise, not harden it (Recommendation #1). - Field navigation should respect where the user was: Oct 1 raised the Inspectr+ tapped photo and DailyReportr+ return-to-Today, and Oct 3 raised the invalid-field jump. The Inspectr+ fix is still first in the queue. The invalid-field jump already exists (Aug 21,
c5bc882); this is the second time it has been proposed (also Sept 26). The morning brief generator should run the samegit log -Sdedup this pipeline does. - Stay within scope against competitors: each morning brief compares against Fieldwire/Bluebeam offline sync and warns against matching their scale. Recommendation #2 follows that advice. It's a speed improvement inside the existing Inspectr+ add-item dialog, not a new module.
- Automation stall: 25 nights. The morning sources keep reporting the retired review producer as MISSING, but none of them check the builder launch jobs.
Feature Ideas + UI/Code Health Recommendations
There are 2 recommendations: 1 UI/code health item and 1 feature. All three morning ideas were rejected after checking against main: two target code nothing calls, and one shipped in c5bc882. Both items below were checked with git grep on main and git log --all. No commit removes or wires the queue, and Inspectr+ has no carry-forward or "add another" path (grep for carry.forward|lastUsed|Save and add|addAnother returns 0 hits). The held items from Sept 28 to Oct 2 still rank ahead of these.
1. Retire the Offline Queue That Nothing Feeds Closr+ + Buildr+ — UI/Code Health (dead API + false promise)
Both apps still include the full offline write-queue scaffolding: a SQLite sync_queue table, LocalDatabase.queueOperation, SyncManagerService.queueOperation/syncNow, a SyncStatus enum, and Riverpod status/pending-count providers. In Closr+, the manager's own doc comment says the legacy push path "is closed" and that the Cloudflare drain "is not yet implemented". However, nothing in either app enqueues a write, and nothing displays the status. The Closr+ AppHeader sync chip never gets a syncStatus, and the Buildr+ OfflineBanner is never mounted. The code still says _setStatus(SyncStatus.synced) on connectivity alone, so it's one wiring change away from telling a field user "All changes saved" when nothing was sent. That is the bug today's morning brief describes. It also cost a builder-night of attention: today's morning brief proposed hardening both apps.
Why now: two of today's three morning ideas target this code. It is also the second "dead but imported" case in two days, after Connected Sources. Removing it leaves both codebases cleaner and stops future briefs from re-proposing the fix.
Sketch: Closr+: delete SyncManagerService.queueOperation/syncNow/getPendingCount, the three unwatched providers in sync_provider.dart, the syncStatus parameter and _buildSyncIndicator in app_header.dart, and LocalDatabase.queueOperation/markSynced/getPendingCount. Keep hasConnectivity() and the cache helpers, which project_service and punch_item_service use. Leave the SQLite table in place, but don't write to it (no schema migration tonight). Buildr+: do the same for queueOperation, the replay loop in syncNow, offline_banner.dart, and syncStatusProvider. Keep cacheProjects/cacheDocuments/preCacheAttachments. Guard: add a test that fails if any Text in lib/ contains "All changes saved" or "Synced" unless a server acknowledgement exists in the same file. When a real Cloudflare drain is built, it should bring back an indicator modeled on Inspectr+'s mounted SyncOutboxBanner. Run dart analyze after each deletion to keep both apps at 0.
2. Save & Add Next (Carry Location and Contractors Forward) Inspectr+ — Feature
Logging a run of deficiencies in one room takes a full round trip for every item. AddInspectionItemDialog (project_detail_page.dart:8145, reachable from 4 call sites) creates the item, uploads photos, and then Navigator.pop()s. To log the next item, the inspector reopens the dialog and retypes the location, re-picks the contractors, and resets the status. Walk Mode already records each capture's locationLabel (WalkModeService.recordCapture), but nothing feeds it back as a default.
Why now: Autodesk Forma Build's September release added photos-first issues where "consecutive issues carry forward previous values to reduce repeated entry" (intel below). This is the honest, small-scope version for Inspectr+'s highest-frequency action, and it reuses the Walk Mode data that already exists.
Sketch: Add a secondary Save & Add Next button next to Save. After createInspectionItem and the photo uploads both succeed, clear the title, description, asset tag, and captured images. Keep location, _assignedContractors, and status. Scroll to the top, focus the title, and show a short "Item 3 saved · Kitchen" confirmation instead of popping. If the dialog opens while Walk Mode is active, prefill the location from the session's last locationLabel. On any failure, keep every field and show the error. Never clear on a partial save. Tests: two consecutive saves keep location and contractors; a failed photo upload keeps the form; the plain Save button still pops.
UI Inconsistencies
- Sync and offline status differs in all four apps: Inspectr+ mounts
SyncOutboxBanner(outbox count plus "Offline"). Closr+ has a header chip that's never fed. Buildr+ has anOfflineBannerthat's never mounted. DailyReportr+ has no indicator. A user moving between apps gets four different answers to "did my work save?" Recommendation #1 removes the two false promises. A shared indicator should only come back once a real drain exists. - Inspectr+ add-item feedback: success reads "Inspection item created successfully", but failure shows
'Error creating inspection item: ${e.toString()}', a raw exception string. Fix this while Recommendation #2 is in the same_savepath. It's part of the wider raw-$epattern noted Oct 2 (Buildr+ 71, Closr+ 61, Inspectr+ 18, DailyReportr+ 50). - Carried over, unchanged (no commits): Buildr+ uses a custom
Icons.arrow_back_iosback button on 9 reachable pages; elsewhere it uses the platform default. The Inspectr+ gallery opens on photo 1 regardless of which thumbnail was tapped. The DailyReportr+ "Today" pill looks tappable but isn't. DailyReportr+ has the fake "1 activity" badge in two duplicated cards. Buildr+ swipe backgrounds use rawColors.redon 10 pages. RawColors.green: DailyReportr+ 40, Inspectr+ 29, Buildr+ 0, Closr+ 0.
Competitive Intel
- Autodesk Forma Build (September releases): photos-first issues with carry-forward. Users can start issues from photos on sheets, and consecutive issues carry forward the previous values. The same post adds Submittal review templates at the account level, renameable Form instances, and mobile sync of a chosen subset of Forms. These are relevant to Inspectr+ (Recommendation #2) and Buildr+ submittals. Sept 2026 (the "Forma" branding and a Sept 2026 third-party review date it), new to this brief [source] [review]
- Procore iOS 2026.0923 (released Sept 29) and September iOS releases: offline support for Workflows (create items, respond to steps, and capture photos offline, with automatic sync on reconnect), plus document markup authoring on iOS. This is the benchmark a real Closr+/Buildr+ queue drain would have to meet. Until one exists, our apps shouldn't imply it (Recommendation #1). dated Sept 29, new to this brief [source]
- Procore Daily Log (Android): "Fix Errors" jumps to the empty required field, with Next/Previous Field navigation (cited in the morning brief). DailyReportr+ already does this for activity names (
c5bc882, Aug 21), so it's at parity, not a gap. current capability, not dated [source] - Already reported: Procore Workflows Step Override and My Open Items (Oct 13) were reported Oct 2. Daily Log negative quantities were reported Oct 1–2. The Project Map color-coded pins were reported Sept 28, and Specifications Connected Items many times in September. No dated, in-window Fieldwire or PlanGrid ship was found.
Tomorrow’s Build Suggestion
This is the twenty-fifth night without builders. The assignments stay held (sixth day). Queue change: today's morning ideas are not added. Both Closr+ and Buildr+ queue-hardening items are replaced by Recommendation #1 (retire), and the DailyReportr+ invalid-field item has already shipped. 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 make 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, do the Buildr+ half of today's Recommendation #1 (delete the producer-less queue writer and the unmounted OfflineBanner), which is pure deletion. 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 that users can actually hit.
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 (19 days on main), and all three fixes target one reachable file. Queued next for whichever builder frees up first: the Inspectr+ tapped-photo fix, then Inspectr+ Save & Add Next (Recommendation #2), then Buildr+ Submittal Status History (Oct 2).