Repository navigation
Conversation
101aeff to
ca672a5
Compare
ca672a5 to
e879814
Compare
e879814 to
5dfd20d
Compare
600d3cb to
49dc7eb
Compare
> _Posted by an AI agent on kve's behalf._
## Summary
Add typed horizontal and vertical size classes to Broadway. UIKit roots
observe changes live; SwiftUI roots map their environment into the same
traits. Scoped overrides let component styles resolve the container's
layout policy.
This is foundation only. It preserves the current main toolchain and
screen behavior.
## Primary APIs
`BHorizontalSizeClass` and `BVerticalSizeClass` expose only compact and
regular values. Both default to compact. UIKit unspecified/unknown
values and SwiftUI missing/unknown values normalize to compact at the
bridge, so stylesheet switches need only two cases. `BTraits.system`
registers both, and `bHorizontalSizeClass` / `bVerticalSizeClass`
provide scoped SwiftUI overrides.
```swift
content
.bHorizontalSizeClass(.regular)
.bVerticalSizeClass(.regular)
```
Stylesheets read `context.traits.horizontalSizeClass` and
`verticalSizeClass` during slicing. Measured geometry remains a view
input. The fallback is an explicit styling policy; known system traits
and scoped overrides are preserved without inferring size classes from
device identity or bounds.
Independent review found one downstream test matrix using the removed
enum case. PR #378 now tests all nine raw UIKit size-class combinations
through the Broadway bridge, preserving single-pane fallback coverage.
## Stack
1 of 5, based on `main`. The snapshot foundation follows this PR;
reusable navigation and geometry come next. [The final app
PR](#372) describes the complete
experience and remaining native release checks.
## Testing
- At current stack tip `2fd6f699853ac4fa592a90d3928f83e836bca635`,
`./test --all` passed on Xcode 27.2: 2,975 iOS unit tests, 28 host macro
tests, and 31 architecture tests. SwiftFormat passed. The root PR also
passed 141 Broadway tests from an isolated build; an earlier
shared-cache build hit stale LifecycleKit deployment-target metadata.
- The earlier full integration at
`e9236bb54771a1e144ffbc35ea9076e8f2c4569f` passed both CI gates,
including all image suites. The current change normalizes unavailable
Broadway size classes to compact and updates the downstream UIKit-input
regression matrix; reference PNGs and renderer settings are unchanged.
New full gates are running on the current tip: [GitHub
Actions](https://github.com/kyleve/Stuff/actions/runs/43064578603) and
[CircleCI pipeline
2166](https://app.circleci.com/pipelines/circleci/HfkN3cJ2hk23YfG42g3oS1/E7hn5FALiSX67sknpk9SZu/2166).
- Visual review covers every changed reference, including full-height
content, accessibility annotations, large text, and theme panels.
Reference PNG metadata and comparison tolerances are preserved.
- Independent review covered all five stack slices and the final
capture, navigation, and inset changes. Focused mutation tests
demonstrate that stale-inset delivery and off-screen accessibility
regressions fail without their fixes.
- Two tall Year accessibility images retain a pre-existing marker offset
and incomplete native-toolbar legends. The capture follow-up is
documented below; it is tracked in
[STU-325](https://linear.app/kve/issue/STU-325); these images do not
prove live VoiceOver behavior.
- Native Duo 27.2 geometry re-measurement and interactive device checks
remain pending. Synthetic regular-simulator coverage does not establish
native system-bar geometry or spoken VoiceOver behavior.
## Backlog reconciliation
The 13 preserved Duo records are tracked in Linear.
[STU-318](https://linear.app/kve/issue/STU-318) owns adoption and its
six implementation sub-issues. This slice relates to
[STU-318](https://linear.app/kve/issue/STU-318). Unmerged implementation
remains In Review.
Remaining Backlog work: native Duo release validation
([STU-316](https://linear.app/kve/issue/STU-316)), intermittent
Locations settling diagnostics
([STU-317](https://linear.app/kve/issue/STU-317)), and tall Year
accessibility annotations
([STU-325](https://linear.app/kve/issue/STU-325)). Existing
[STU-114](https://linear.app/kve/issue/STU-114) and
[STU-252](https://linear.app/kve/issue/STU-252) now distinguish the
partial fixes from their remaining requirements; both retain their
priorities, labels, and open state.
3afa6ca to
0c7e8de
Compare
0c7e8de to
bb29adb
Compare
bb29adb to
223fd29
Compare
> _Posted by an AI agent on kve's behalf._ ## Summary Add explicit frame layout traits and recorded Duo profiles to the Xcode 27.2 baseline from main. Apply requested content clearance after UIKit finalizes containment and native geometry. This layer retains the existing Where navigation. Its image references establish the new capture baseline before the adaptive app changes. Calendar month sections, day rows, and Timeline rows measure eagerly so full-content captures include the final rows; the selection and tabletop changes remain in the app PR. Eager Timeline measurement removes blank tails caused by lazy height estimates in a bottom-anchored scroll view. Settings waits for native search chrome to settle before measuring its full height. Existing scrolling onboarding and Devices fixtures use full-content frames. Theme choices also fall back to a vertical layout when narrow, and large-text Logged Days rows retain their dates, notes, and labels. ## Screenshots Developer Overlay, light iPhone full-content capture. Retaining the scene restores uniform native glass without changing the menu's styling, dimensions, or content. | Before | After | |---|---| | <img alt="Detached-scene menu with bright bands and a hard material cutoff" width="260" src="https://media.githubusercontent.com/media/kyleve/Stuff/9e759fc8b0ac8db6569bfb03d49cdafd54c7ad2c/Where/WhereUI/SnapshotTests/__Snapshots__/DeveloperOverlaySnapshotTests/developerOverlay.MenuTopLeading_iPhone.png"> | <img alt="Scene-backed menu with uniform glass and complete content" width="260" src="https://media.githubusercontent.com/media/kyleve/Stuff/f05ca62400c415631e21c5e649ce655700d9f18a/Where/WhereUI/SnapshotTests/__Snapshots__/DeveloperOverlaySnapshotTests/developerOverlay.MenuTopLeading_iPhone.png"> | Before: `9e759fc8`. After: `f05ca6240`; all six overlay captures reproduced byte for byte. ## Primary APIs - `SnapshotConfiguration.Frame.LayoutTraits` owns horizontal and vertical size classes and interface idiom. Configuration-level layout traits remain supported and take precedence over frame defaults. Phone and iPad presets carry truthful traits without changing their filenames. - `Frame.scenePolicy` controls capture scene retention without renaming references. Both configured assertions and hosted PNG export honor it. - `Frame.viewport` captures bounded shell composition. It must be paired with full-content captures of scrolling panes. - The four Duo profiles use measured native geometry. The module README retains the measurement date, runtime/build, collection method, and validation limits; the unused raw JSON dump is removed. `.narrowWindow` covers a synthetic multitasking container. ```swift let configuration = SnapshotConfiguration(device: .duoInnerPortrait) configuration.applyTraits(to: host) ``` Previews and UIKit capture use the same mapping. Conversion from configuration traits to frame traits uses exhaustive switches for both size classes and idiom, so new enum cases require an explicit mapping. Custom frames can supply `layoutTraits`; component frames inherit the host's traits. ## Capture and tooling boundaries All capture entry points acquire one lock before host discovery, validation, and preparation. Fixed, regular-width phone captures retain their scene so native bar geometry stays stable. Other synthetic captures detach the marked window by default, preserving compact title space and anchoring full-content search to expanded content. Capture and measurement hosts reconcile their effective insets after containment and layout, with another reconciliation after settling. The predicate uses content-controller traits, not pixel width or simulator identity. Frames can explicitly retain the scene when native chrome requires it. Periscope and Developer Overlay use this option without changing their configured traits, insets, or sizing. Developer Overlay's native glass otherwise develops bright bands and a hard material cutoff. Retention can expose physical reserved regions, so general presets keep the automatic policy. Both paths restore scene and presentation state on success or failure. A nil inset override retains native geometry. Only the captured root overrides its safe-area getter, during final pixel rendering. Native getters remain active during containment, measurement, and settling so inset changes propagate to children. Root pinning protects translated tiles. Overriding ancestors doubled asymmetric insets after measurement rehosting. Annotation padding has zero safe-area insets to avoid moving centered content. Tall tiled Year annotations retain the pre-existing limitation listed below. Regressions cover these boundaries, already-mounted inputs, compact and regular title readability, native bar stability, tiling, and failure cleanup. Full-content captures reset restored scroll offsets after readiness; viewport captures preserve them. Accessibility subjects stay mounted during readiness and settling. Ordinary captures retain their controller parent during parsing; only upstream tiling temporarily detaches it. Annotation wrappers grow only after the final accessibility parse. Synthetic viewports recover native navigation-bar metadata synchronously, restore window geometry before parsing, and restore the original getters on every exit. Pixel settling retains main’s normalized pixel comparison and retry policy. Final reference-comparison tolerances remain unchanged. Hosted resize, restoration, full-content, PNG export, and cancellation checks cover the shared pipeline. Snapshot shard discovery accepts literal multiline source arrays with shared support files. Unsupported declarations fail without borrowing a following target's sources. The existing shard assignments stay unchanged. ## Compatibility and review focus - The stack requires iOS 27.1. Development and CI use Xcode and simulator 27.2. The native macOS deployment target is unchanged. - Review the capture isolation and frame-trait API changes before the references. The fix addresses stale inset compensation: requested top/bottom values of 5/9 previously reached native children as 0/0. - The app integration in #372 fixes a separate stale developer-overlay inset delivery. Native accessibility capture corrections belong to this foundation layer; later app layers own their navigation and search behavior. - The Duo profiles retain their recorded 27.1 measurements. Re-measurement on the native 27.2 Duo runtime remains an explicit release-validation item. - Theme descriptions retain three lines of minimum space and grow for large text. The shared picker no longer truncates the Flat description at AX5. ## Testing - At `42ab5b40e`, `./test --review --only SnapshotKitTests --only WhereUISnapshotTests/DeveloperOverlaySnapshotTests` passed all 56 SnapshotKit tests and the Developer Overlay image suite (all six captures matched byte for byte). Architecture and SwiftFormat passed. Review fixes preserve the existing mappings and presets; no references changed. - Full gates on the current head `42ab5b40e`: [GitHub Actions](https://github.com/kyleve/Stuff/actions/runs/43081928022) and [CircleCI pipeline 2195](https://app.circleci.com/pipelines/circleci/HfkN3cJ2hk23YfG42g3oS1/E7hn5FALiSX67sknpk9SZu/2195). - At `f05ca6240`, the full run passed 2,922 iOS unit tests and 28 host macro tests. All 71 snapshot tests are covered by the full run plus focused assertions after review; 679 affected WhereUI tests also passed after the eager Timeline change. - `./test --no-generate --review --timings --only WhereUITests` with the seven affected snapshot suites verified the refreshed references. A final `./test --no-generate --no-build --review --only WhereUISnapshotTests/DeveloperOverlaySnapshotTests` repeated all six overlay captures byte for byte. Architecture checks and SwiftFormat passed. - Full gates for the capture-repair baseline (before the exhaustive-conversion refactor and documentation cleanup): [GitHub Actions](https://github.com/kyleve/Stuff/actions/runs/43079785790) and [CircleCI pipeline 2188](https://app.circleci.com/pipelines/circleci/HfkN3cJ2hk23YfG42g3oS1/E7hn5FALiSX67sknpk9SZu/2188). The capture fixes and reference migration are verified at this PR's own layer. A green stack tip cannot establish that an earlier PR's renderer and references agree. Layer-specific Timeline, Settings, and Year references retain the behavior present here rather than borrowing later adaptive UI semantics. - Independent source review covered capture containment, final annotation sizing, native-bar getter restoration, Settings measurement, and eager Timeline layout. Visual review covered the refreshed references and preserved comparison-sheet metadata; comparison tolerances are unchanged. - Two tall Year accessibility images retain a pre-existing marker offset and incomplete native-toolbar legends ([STU-325](https://linear.app/kve/issue/STU-325)). - Native Duo 27.2 geometry re-measurement and interactive device checks remain pending. Synthetic regular-simulator coverage does not establish native system-bar geometry or spoken VoiceOver behavior. ## Stack First active layer, based on main after [#376](#376) merged. This supplies the capture foundation for #378 and #372. Capture corrections and their references land here; adaptive corrections and references land with the app integration. ## Backlog reconciliation The 13 preserved Duo records are tracked in Linear. [STU-318](https://linear.app/kve/issue/STU-318) owns adoption and its six implementation sub-issues. This slice relates to [STU-319](https://linear.app/kve/issue/STU-319), [STU-320](https://linear.app/kve/issue/STU-320), [STU-327](https://linear.app/kve/issue/STU-327). Unmerged implementation remains In Review. Remaining Backlog work: native Duo release validation ([STU-316](https://linear.app/kve/issue/STU-316)), intermittent Locations settling diagnostics ([STU-317](https://linear.app/kve/issue/STU-317)), and tall Year accessibility annotations ([STU-325](https://linear.app/kve/issue/STU-325)). Existing [STU-114](https://linear.app/kve/issue/STU-114) and [STU-252](https://linear.app/kve/issue/STU-252) now distinguish the partial fixes from their remaining requirements; both retain their priorities, labels, and open state.
083ef93 to
bcbb35b
Compare
There was a problem hiding this comment.
Posted by an AI agent on kve's behalf.
Duo Layout Lab — shared pose fixtures and labels
The lab keeps the same synthetic geometry and pose labels, now supplied by SnapshotConfiguration.DuoPose. The closed pose retains the forecast's initial bottom alignment.
Reference verified against ca09946122b6a23743f78fad51b3ca75d4bea87e with recording disabled on the pinned iOS 27.2 renderer. Existing outerPortrait_iPad fixture, production demo content. This establishes synthetic composition; native Duo geometry and physical folding remain pending.
bcbb35b to
c50e59f
Compare
There was a problem hiding this comment.
Posted by an AI agent on kve's behalf.
Locations — selection follows the visible pane layout
Returning to the phone card list retains California as the selected region, without the blue outline or selected accessibility trait. The tablet-style layout keeps the outline while the cards and calendar are visible together.
| Phone after returning from the calendar | Open display with companion calendar |
|---|---|
![]() |
![]() |
References verified with recording disabled at: ca09946122b6a23743f78fad51b3ca75d4bea87e, pinned iOS 27.2 renderer. The phone is a full-content capture; the open display is a synthetic Duo viewport. The mounted regression checks selection across compact, columns, tabletop, and compact again. Native Duo geometry remains pending.
There was a problem hiding this comment.
Posted by an AI agent on kve's behalf.
Your Year — the standard bottom selector at every size
Calendar and Timeline use one navigation stack on phones, open displays, and tabletop. The bottom selector stays available, and the selected mode survives resizing. Timeline owns its row identities and scrolling independently. Recorded rows have no selection action; planned rows still open their editors.
| Calendar | Timeline |
|---|---|
![]() |
![]() |
References verified with recording disabled at: ca09946122b6a23743f78fad51b3ca75d4bea87e, production demo data in the synthetic duoInnerPortrait viewport on the pinned iOS 27.2 renderer. The mounted selector test passes across all seven synthetic poses and return. Final Locations, Year, and tab-shell snapshot comparisons pass with recording disabled. Native Duo geometry remains pending.
The five Timeline accessibility-reference updates only remove recorded-row “Button” labels from the annotation legends; their screen pixels are unchanged. Planned-stay actions remain buttons.
Move the native Settings search placement, fold regression, and 101 reviewed integration references out of the follow-up PR. Refresh four scene-backed developer overlay references for the adaptive geometry and Duo Lab row. Validation: full iOS unit suite passed with 2,975 executed tests and no unexpected failures; host macros, architecture, and formatting passed. Adaptive lab, MainTabs, and Settings snapshots passed. All six adaptive developer-overlay captures repeat byte-for-byte after review.
3002c17 to
ca09946
Compare
There was a problem hiding this comment.
Posted by an AI agent on kve's behalf.
Settings — native list/detail navigation
Settings uses its stable native split navigation and the stylesheet's compact-layout policy directly. It no longer measures Locations' fold geometry. The mounted search test preserves the entered query through compact, open, tabletop, book, and compact again.
Reference verified against ca09946122b6a23743f78fad51b3ca75d4bea87e with recording disabled. Production demo data, synthetic duoInnerPortrait viewport, pinned iOS 27.2 renderer. Native Duo geometry validation remains pending.






Summary
Where keeps navigation, selection, search, sheets, and presentation state in stable views while the window changes size. Locations uses native browse/detail navigation and a custom tabletop composition. Your Year uses its standard bottom calendar/timeline selector at every size. Settings uses native split navigation and the stylesheet's compact-layout policy.
Locations marks the selected region only while browsing and calendar panes are visible together. Returning to the phone card list retains the region without a blue outline or selected accessibility trait. Active Locations drill-ins keep their native stack while resizing; tabletop waits until the user returns.
Behavior
Ownership
LocationsViewowns an optionalCalendarMonthRevealvalue. Calendar consumes it synchronously after readiness, retaining its identity/month for tabletop display. There is no per-pane consumption registry, interval coordinator, or calendar-to-timeline resolver.CalendarContentViewretains native detail scroll position through BroadwayUI. Overview and tabletop use separate view-local positions..monthand.estimateremain distinct destinations. Initial forecast alignment stays at the bottom.CalendarModelinterprets data and accesses existing preferences. View-owned helpers handle zoom, gestures, focus, rejection feedback, and transition geometry.PresenceTimelineListowns typed recorded/flight/planned row IDs. Its full timeline and embedded excerpt share rendering. The unused linked presentation and its dedicated BrowseColumn snapshot are removed.SettingsViewowns its stable navigation and search state without measuring Locations' fold geometry. The welcome and developer overlays independently use the shared geometry adapter to find clear space.DuoPoselabels and fixtures.Review focus
Start with CalendarMonthReveal, then CalendarContentView and its mounted tests. The request identity is distinct from the destination identity, and consumption does not create another scroll store.
PresenceTimelineList retains restoration and planned-stay editing without linked selection. Its mounted test browses a row, replaces the view, and verifies the same target remains visible.
Mounted tests caught a plain-binding observation gap: post-mount requests were not delivered until the calendar registered
@Binding. The corrected flow passes repeated, delayed, year-change, and consumed-request restoration guards. Independent review checked the correction and found no remaining actionable issue. Hosted fold guards cover Settings search, pushed navigation, presented editors, unsaved drafts, and load continuity. Native folding remains a separate validation requirement.Stack
#378 supplies shared restoration, localized pose definitions, and layout policy. This PR installs the app integration, DEBUG lab, and adaptive references. #376 and #377 are merged; #466 remains superseded. Both active PRs remain open for review.
Screenshots
Your Year — standard selector on the open display
Representative references verified against
ca09946122b6a23743f78fad51b3ca75d4bea87ewith recording disabled, using production demo data and synthetic Duo viewports. These establish composition, not native floating-bar placement.Testing
./test BroadwayUITests SnapshotKitTests WhereUITests: 798 tests ran; 793 initially passed. Four calendar tests exposed an unregistered binding, and the new timeline test waited for a transient.edgecommand instead of its rendered bottom offset. The corrected, rebuilt CalendarContentView, PresenceTimelineList, LocationsDuo, MainTabsDuo, and YearView suites passed all 19 tests. The broad run's remaining tests were not repeated because their inputs did not change../test --no-generatewith the seven affected snapshot-suite filters and--record never --reviewran nine tests. Eight passed; Timeline identified five annotation legends with obsolete recorded-row Button traits. All five were visually reviewed and copied unchanged from actual PNGs. Pixel checks confirm their entire screen regions are identical; only the annotation legends change. The unusedBrowseColumn_browseColumntimeline reference is removed.--record never --reviewcomparisons passed MainTabs, SettingsView, and PresenceTimelineList. The Settings root preserves the former container background without restoring geometry machinery. Its outer-display search surface still reports a low-contrast delta (maximum channel difference 16) within the existing comparison tolerance; that reference remains unchanged. No other references were recorded during this review follow-up.Release validation
Native geometry measurements remain from iOS 27.1. Native Duo 27.2 re-measurement remains pending. This refactor establishes synthetic layout and state continuity, not native folding fidelity. Interactive system bars, camera regions, keyboard, VoiceOver focus, and physical folding remain separate release checks.
Backlog reconciliation
The 13 preserved Duo records are tracked in Linear. STU-318 owns adoption and its six implementation sub-issues. This slice also owns the search work in STU-326. It relates to STU-318, STU-321, STU-322, STU-323, STU-324, STU-328. Unmerged implementation remains In Review.
Remaining Backlog work: native Duo release validation (STU-316), intermittent Locations settling diagnostics (STU-317), and tall Year accessibility annotations (STU-325). Existing STU-114 and STU-252 now distinguish the partial fixes from their remaining requirements; both retain their priorities, labels, and open state.