Skip to content

Latest commit

 

History

History
843 lines (717 loc) · 50 KB

File metadata and controls

843 lines (717 loc) · 50 KB

MHUI Main-App Rollout

Updated September 26, 2026.

This record covers the main-app step. The subsequent companion rollout evaluates Watch, Widgets, and CookleLibrary independently; the exclusions below describe this earlier step.

Scope

ADR 0009 records the accepted expanded Recipe Detail direction and broader main-app adoption. The root and Recipe Detail implementation is committed as 5f247dfa; the original comparison and first adoption evidence are committed as 9d09bf76. This record follows the subsequent screen-by-screen implementation.

Existing content, routes, fields, actions, and persistence stay in the app. Reading and action order are app-owned presentation decisions. New features and diary-list information architecture are separate work. CookleLibrary, Watch, Widgets, App Intent implementations, and the MHUI package remain outside this change.

MHUI 2.3 Adoption

The remote requirement advances to 2.3.0..<3.0.0, resolved to MHUI 2.3.0 at 844fec442c78a0777e4b2786bcc9ea3233b12c2f. The project-link and resolved-pin guardrails reject the 2.2 baseline. The root standard theme, the orange accent, and the startup configureNativeAppearance() call are unchanged.

mhScreen no longer limits the entire screen to 640 points. Recipe Detail, Cooking, the Diary landing, and the photo collection fill their available column or screen within MHUI's responsive margins, and text shares the same width as media. These composed screens had no app width compensation to remove and gain no new app width limit. Recipe photos keep their app-owned 240-point height, aspect-fit scaling, order, and horizontal scrolling; a wider column shows more of the row at once. Native split-view column allocation is unchanged, and Cookle sets no column width. Full-screen empty states do not use mhScreen and keep their existing centered layout and readable-width limit.

Default content buttons return from primary text to the accent. The actions that 2.2 listed as changing to primary text, including See All, Add Diary, Another Suggestion, the add-multiple-ingredients accessory, the backup rows, and the search first-use actions, take the accent again. Delete All keeps the destructive role, and explicit mhPrimary, mhQuiet, and mhDestructive actions keep their treatments.

The two detached recipe text editors already use mhInputChrome, which now applies primary input text and hides the editor's scroll background. They drop their own scrollContentBackground(.hidden) call. Native Form fields receive no added input decoration.

MHUI 2.3 Verification

The formatter and retained repository rules pass. Negative guardrail probes reject a 2.2 project minimum and resolved pin. The Xcode-native Cookle build succeeds with Xcode 27.1 (27A9269) and the iOS 27.1 Simulator SDK. Its full log includes a Watch App Intents metadata-extraction warning because that target has no AppIntents framework dependency. No library logic changed, so library tests were not rerun.

The isolated Japanese fixture on a 13-inch iPad with iOS 27.0 confirms the landscape detail content width grows from 640 to 976 points, preserving the 40-point margins inside its 1056-point native detail column. Both sample photos fit fully in the initial viewport without changing their 240-point height. Portrait retains horizontal scrolling when the photo row exceeds the available width. The body uses the same wider column; the native navigation title retains its own alignment.

Additional iPad checks cover opening and closing the full-screen photo and landscape at the largest accessibility text size. The detail photos and actions remain within the column. The narrow native sidebar wraps recipe names heavily and truncates secondary labels at that size; this is not evidence of full accessibility coverage.

On iPhone 18 Pro with iOS 27.0, the compact recipe detail, existing materials TextEditor in light and dark, and empty Recipe and Search screens were checked. The editor retains its themed text and background without the duplicate app modifier. Changing appearance dismissed the nested editor sheet; reopening it allowed the dark capture. That transition was not compared against 2.2, so its regression status is undetermined. The separate recipe-inference editor was not opened; its identical modifier cleanup has build and source evidence only. Search first-use actions render in the accent again, and the empty state remains centered in its available viewport with the keyboard shown. Cancel and return paths were used without saving changes to user data.

The app-owned orange accent still has limited contrast against light surfaces. Unselected tab colors and native Form/search input coverage are not claimed as fixed by this update. Diary selection and the complete empty-state accessibility matrix were not rerun for 2.3; their earlier checks remain historical evidence. No real-device, VoiceOver, Increase Contrast, purchase, notification, or sync validation was performed. Appearance, text size, orientation, Xcode selection, and the iPad's initial shut-down state were restored, and owned runs and interaction sessions ended. Captures and the before/after gallery are retained under .build/ci/mhui-2.3-adoption/.

MHUI 2.2 Adoption

This section records the 2.2 step. Its default-button colors and screen width are superseded by the MHUI 2.3 section above.

The remote requirement advances to 2.2.0..<3.0.0, resolved to MHUI 2.2.0 at 24c15fd86eef7207ae56092983305b478d1c9de6. The project-link and resolved-pin guardrails reject the 2.1 baseline. The root standard theme and the orange accent are unchanged. The app initializer and the shared preview assembly replace configureNavigationTitleAppearance() with configureNativeAppearance(), which keeps the title setup and adds the UIKit text-input and unselected-tab requests.

MHUI 2.2 widens section spacing to 40 points and keeps a composed section's heading, content, and footer 8 points apart. Recipe Detail, Cooking, Diary, and the recipe actions already compose through mhSection and theme.spacing.section, so they receive the new rhythm without app changes. The photo collection was the one composed section that placed a standalone MHSectionHeader above its grid with theme.spacing.content; it now uses mhSection, as the package reading and section-rhythm examples do. Cookle adds no metric, padding, border, divider, or palette override. Grouped rows keep their own 16-point padding, so visible heading-to-text distances in those groups exceed the 8-point structural gap, as the package guide notes.

The root theme now supplies the orange accent as native control tint. Toolbar items such as sort, add, and the recipe import control take the accent; the confirmation-placed Edit button was already accent-filled. No toolbar item has a neutral role that requires a primaryText exception, so none is added. Default content buttons follow MHUI's primary text or destructive role: See All in recipe diary history, Add Diary, Another Suggestion, the add-multiple-ingredients header accessory, the backup rows, and the search first-use actions change from accent to primary text, and Delete All uses MHUI's destructive color for its icon and label. Explicit mhPrimary, mhQuiet, and mhDestructive actions keep their treatments. The empty-state Add Recipe control is a Menu, which the default button style does not reach, so it keeps the accent.

MHUI 2.2 Verification

The Swift formatter and retained repository rules pass, and the guardrails reject the 2.1 project baseline and resolved versions below 2.2.0. The Xcode-native Cookle build succeeds with no errors or warnings on Xcode 27.1 (27A9269) and the iOS 27.1 Simulator SDK, and Xcode's package state resolves MHUI 2.2.0 at the pinned revision. No shared library logic changed, so no library tests ran.

Runtime evidence uses the isolated capture fixture in Japanese on iPhone 18 Pro and a 13-inch iPad, both iOS 27.0, installed and launched through the native Xcode integration with an explicit capture environment. On iPhone, Recipe Detail measures 40 points between sections and 8 points from each heading to its content; the photo collection measures the same. The recipe form accepted typed name text, and Cancel and Discard returned to the unchanged detail. Settings was checked in light, dark, and dark at AX3; recipe actions in dark and at AX3 in light; and the recipe list, tabs, and toolbar in light and dark. The diary selector opened with the saved breakfast recipe checked once its push transition settled, the first tap changed the count from one to zero, and returning and cancelling kept the original diary. With the empty isolated store, the Recipe, Photos, and Search first-use states remain centered, and at AX5 the Photos action remains reachable by scrolling. The iPad run covers the recipe split view with a detail, selecting another recipe at AX3 in light, and dark Settings.

The observed limits are separated by owner:

  • SwiftUI text fields and the searchable field render input text in the system label color (#000000 in light) in both the 2.1 and 2.2 captures, while navigation titles use MHUI's primary text (#444444). The UIKit text-input default does not reach these SwiftUI-owned inputs on this runtime; this is a native and package boundary, and Cookle adds no per-field override.
  • Unselected tab items stay system black, as the MHUI 2.2 guide records for the Liquid Glass tab renderer. On iPad, the system sidebar toggle stays neutral beside the accent-tinted sort and add items.
  • The orange toolbar glyphs sample about 2.2:1 against the light glass. The accent's light-appearance contrast predates 2.2 and remains an app accent decision, consistent with the 2.1 measurements below.
  • Default content buttons in primary text are less distinct from adjacent text than the previous accent treatment, most visibly in the search first-use actions. This follows the package's default-button decision and is recorded for MHUI review rather than overridden in Cookle.
  • The switch ON state was not exercised. The only switch visible in capture mode controls real daily notifications, so turning it on would change a notification setting; the OFF state and MHUI's native-control Preview are the available evidence.

The fixture run on iPhone logs two SwiftUI glassEffect() multiple-update faults plus UIKit, keyboard, and accessibility-automation messages. The empty-store and iPad runs log no such fault. No crash, fatal error, or SwiftData or Core Data error appears.

Appearance and text size used official simulator settings because the native integration has no such control; both devices were restored and confirmed. No user records were saved or deleted, and no purchase, sync, account, or notification setting changed. Interaction sessions ended, runs stopped, the iPad returned to its shut-down state, and the original Cookle scheme and iPhone 18 Pro destination were restored. VoiceOver, Increase Contrast, physical devices, and unvisited routes remain unverified for 2.2. Local captures, logs, and a review gallery are retained under .build/ci/mhui-2.2-adoption/.

Empty-State Alignment Review

This review ran against MHUI 2.1. Its spacing values and runtime evidence are historical; the MHUI 2.2 section above records the current rhythm.

The September 26 follow-up centers full-screen empty states in the available content viewport. Recipe and Search previously placed their placeholders in mhScreen, whose scrolling stack does not expand to the viewport height; Photos used an unwrapped native placeholder. The app now shares a scrollable empty-state layout for Recipe, Photos, Search, and tag discovery. Diary uses it only when both diaries and recipes are empty, retaining recipe inspiration when recipes exist. Native navigation and tab bars define the available area. The layout uses MHUI's empty-state padding, readable width, text appearance, and semantic background without copying palette values or screen offsets.

The border audit found no app-owned stroked frames or border overrides. Recipe ingredients, categories, and diary history use MHGroupedRows, which intentionally draws separators between rows. Content List separators and native settings/form boundaries remain structural. The four explicit app Divider calls separate the website address field from web content or separate content in App Intent snippets. They are retained for those roles. MHUI 2.1's visual principles explicitly preserve grouped-row separators and input boundaries while rejecting ornamental frames.

Recipe Detail, Cooking, Diary, and Photos already use theme.spacing.section between major blocks. Section headings and their content use mhSection or theme.spacing.content, matching the MHUI reading Example and section Preview. In the standard theme those values are 32 and 24 points; grouped rows add their own 16-point vertical padding. This can make the apparent gaps around a heading similar. Cookle does not override these values, so this review retains the package rhythm rather than adding app-specific offsets. Native List/Form heading geometry also remains under MHUI and system control.

The follow-up app build and repository rules pass. Japanese iPhone Simulator checks cover all four empty tab states, empty category discovery, no search results, and opening/cancelling diary and recipe creation. At the largest accessibility text size, the photo description and final action remain reachable by scrolling. An iPad capture confirms centering within each split column. Populated Recipe and Diary detail captures preserve the existing section and row treatments. This is representative Simulator evidence, not physical-device or VoiceOver coverage. Verification runs ended and the original Cookle/iPhone destination and simulator settings were restored.

MHUI 2.1 Adoption

This section and its verification are historical MHUI 2.1.0 evidence.

The remote requirement advances to 2.1.0..<3.0.0, resolved to MHUI 2.1.0 at 68a00be5348dadb5a16e84e18d52017f105d5a6d. The project-link and resolved-pin guardrails reject the 2.0 baseline. The root standard theme, the startup navigation-title configuration, and the orange accent are unchanged. Cookle adds no metric, padding, or color override to reproduce its 2.0 appearance.

MHUI 2.1 applies its canvas and text colors to .native containers. Each app-owned native List wraps its complete rows once in MHContainerContent: Settings, the Debug sidebar and model list, and the diary-object, photo-object, and ingredient-object inspectors. The adapter adds the themed row surface without recomposing sections or removing swipe deletion, and no row adds mhRow(). Two inspectors name their sections as properties to keep the wrapped list within the lint limit. The Shortcuts link row keeps its own empty row background inside the adapter.

The subscription host and the Debug Previews list only host MHPlatform-owned StoreKit, advertisement, and Shortcuts sections, so they keep the native row background. A wrapped trial framed the StoreKit view's own white surface inside the muted row, which the package guidance asks adopters to avoid. Native control labels and selection, disabled, and destructive states keep their system semantics.

The recipe list keeps content presentation at compact and expanded widths. Recipe actions keep the vertical quiet and destructive group without fixed icon widths or compensating padding. The diary row's day number previously forced the system label color; it now uses the theme's primary text role, so it follows the softer 2.1 hierarchy beside the rest of the diary text. The remaining fixed app metrics size product content: photo heights, thumbnail grids, the 44-point target for custom suggestion chips, and the placeholder inset matching the native text editor. They are unchanged. Diary recipe selection keeps its PersistentIdentifier binding and row tags.

MHUI 2.1 Verification

The Swift formatter and retained repository rules pass, and the guardrail rejects the previous project baseline. The Xcode-native Cookle build succeeds with no errors or warnings on Xcode 27.0 and the iOS 27.1 Simulator SDK. Xcode's package state resolves MHUI 2.1.0 at the pinned revision. No shared library logic changed, so no library tests ran.

Runtime evidence uses the isolated capture fixture in Japanese on iPhone 18 Pro and a 13-inch iPad, both iOS 27.0. The iPhone run covers the startup recipe list, detail and Back, the detail's primary and lower actions, Settings including its lower Shortcuts row, the subscription host, and the Diary landing. The recipe form entered edit mode, reordered and deleted a step, and discarded the draft; the detail kept its original six steps.

The diary selector opened with the saved breakfast recipe checked. The first tap changed the count from one to zero. Selecting a different recipe, Done, and reopening kept the draft selection; Cancel and Discard returned to the diary with its original breakfast.

Recipe actions were checked in light and dark, with Increase Contrast in both, and at accessibility text size AX3 in both. Settings was checked in light, dark, light with Increase Contrast, and AX3. At AX3 the primary pair stacks and the longer label wraps without clipping. Quiet and destructive icons begin at the same leading edge at the standard size and within one point at AX3. Duplicate is about five points taller than Delete at AX3 because the symbols differ.

These contrast estimates sample 1x screenshots against the adjacent background. They are approximate and are not an accessibility certification.

Label Light Light + Increase Contrast Dark Dark + Increase Contrast
Quiet orange action text 2.2:1 4.2–4.4:1 10.3–10.6:1 11.4–11.8:1
Start Cooking label on orange 2.0:1 Not sampled 10.0:1 Not sampled
MHUI destructive Delete 5.2:1 7.7:1 6.3:1 12.9:1
Native Delete All in Settings 3.3:1 3.6:1 5.5:1 Not sampled
Secondary Add to Today 9.5:1 Not sampled 11.8:1 Not sampled

In light without Increase Contrast, orange text and the white label on the orange primary action fall well below 4.5:1. Cookle's accent is the system orange, so this predates 2.1 and remains an app accent decision. Settings rows use MHUI's muted surface: a subtle #FAFAFA on the white canvas, strengthened to #E9E9E9 with Increase Contrast.

The iPad run covers both recipe columns before and after selection, sidebar collapse and expansion through the system toggle, portrait and landscape, light and dark recipe detail, and dark Settings. No divider is drawn between the recipe list and detail columns in either appearance, confirmed at native resolution. Whitespace and alignment carry the boundary. Cookle adds no separator; the condition is recorded for MHUI review. The same missing divider also appears in the isolated 2.0 baseline. Recipe rows use app-owned selection routing, so the list shows no persistent selected row, as in the 2.0 capture. Choosing a recipe in the app shows an inline detail title, while launching directly into it shows the large title. The inline title and the large title on direct launch both reproduce on the same iPad with the 2.0 baseline at 94983428, resolving MHUI 2.0.0; this route-dependent difference is not introduced by this update. In Settings, the unselected detail placeholder uses the system background beside the themed sidebar canvas.

Runtime logs contain four SwiftUI glassEffect() multiple-update faults on iPhone and one on iPad, plus Core Animation, UI automation, and CoreTelephony messages. No crash, fatal error, or SwiftData or Core Data error appears.

The workspace interaction session disappeared right after the native install and launch, and the native launch session later expired and terminated the app. Verification then relaunched the natively installed build through official simulator tooling with the explicit capture environment, using a native standalone interaction session. Appearance, text size, and contrast used official simulator settings and were restored. No user records were saved or deleted, and no purchase, sync, account, or notification setting changed. Capture mode hides the Debug screens; a Debug sidebar Preview shows the themed rows but is not runtime evidence. Capture mode also skips runtime startup, so the subscription store stays in its loading state. VoiceOver, physical devices, and unvisited routes remain unverified. Local captures, logs, and a review gallery are retained under .build/ci/mhui-2.1-adoption/.

MHUI 2.0 Adoption

The remote requirement advances to 2.0.0..<3.0.0, resolved to MHUI 2.0.0 at 8bd30c7c9b6149d7034fe76ab9675ef3822c4d42. The project-link and resolved-pin guardrails reject the 1.x baseline.

The app root applies the neutral standard theme, and the app initializer configures the same theme's navigation title appearance before any scene is created. Previews apply the same theme and title configuration through the shared preview assembly. Cookle keeps its orange accent and adds no palette or base-color overrides.

MHUI 2.0 changes no-argument mhListChrome() and mhFormChrome() from native rows on the MHUI canvas to content presentation, so every container now states its route; the table below lists the choices. The recipe form keeps its specialized native sections (reordering, deletion, edit mode, section-level dialogs and import modifiers) and opts each row into mhRow() explicitly instead of recomposing sections through MHContainerContent. The graphical date picker opts into automatic labeled-content styling to avoid inheriting the compact key-value column intended for ordinary metadata. The isolated sample factories save their in-memory contexts before navigation or selection retains model identifiers. This prevents temporary identifiers from changing after the sample UI has captured them; live stores are unaffected.

Recipe Detail and Cooking move the recipe name from a custom content heading into the native navigation title. Sections and grouped rows follow the 2.0 open canvas, so ingredient, category, and diary groups no longer draw surfaces. Empty, loading, and search states drop their surface frames, redundant secondary button styles inside action groups are removed, and footer-only sections use mhSectionWithFooter. Detached editors no longer paint a grouped background behind their input chrome. Watch, Widgets, and CookleLibrary still do not link MHUI, so the 2.0 metrics do not affect them.

MHUI 2.0 Verification

The Swift formatter and retained repository rules pass. The Xcode-native Cookle build succeeds with no errors or warnings on Xcode 27.0 and the iOS 27.1 Simulator SDK; it compiles the MHUI 2.0.0 checkout and the embedded Watch and Widgets targets. No shared-library logic changed, so no library tests ran.

Runtime evidence uses the existing isolated capture fixture on iPhone 18 Pro (iOS 27.0). It covers the recipe list, sort menu, Recipe Detail with its collapsed title and lower actions, diary history, Cooking with step selection and a dismissed End Session confirmation, the recipe form in view and edit modes followed by Cancel, the Diary landing and detail, Search prompt, no-result and result states, Settings, the photo grid, and photo detail. Dark appearance with accessibility text covers Recipe Detail and the recipe list, and the iPad review simulator covers the recipe split view. No user records were saved or deleted, and no purchases or cloud synchronization were performed. Local captures and the filtered runtime log are retained under .build/ci/mhui-2.0-adoption/.

Independent follow-up verifies the corrected full-width graphical date picker and tag edit cancellation without changing its name. The initial diary selection defect predates this migration: exact Cookle commit 78eb27ad with MHUI 1.20.0 reproduces an empty selection circle at a selected count of one. The first tap also fails to deselect that row; earlier checks only exercised selection after adding another recipe, so they missed this initial-state defect.

Removing MHUI's container and chrome while retaining the current saved sample fixture reproduces the same behavior. Cookle previously bound native selection to Set<Recipe> while ForEach identifies rows by PersistentIdentifier. The app now projects its draft selection into those same persistent identifiers and tags rows accordingly. With MHUI 2.0 content presentation retained, initial selection is correctly checked and the first tap changes the count from one to zero. Selecting a different recipe, confirming it into the draft, reopening the selector, and cancelling/discarding the draft also pass; the original diary retains its recipe. No MHUI package change or model/schema change is needed. The comparison artifacts are under the local runtime directory's review/selection-investigation.

Workspace interaction sessions were lost during verification. After reproducing the tool gap, an explicit isolated-fixture launch through official simulator tooling with native UI interaction completed the follow-up checks. Verification runs and sessions were stopped, simulator overrides were restored, and the original Cookle scheme and iPhone 18 Pro destination were confirmed.

The native large title truncates long recipe names on iPhone, most visibly at accessibility sizes; the captured collapsed inline title shows the full sample name. VoiceOver behavior remains unverified. MHUI's compact key-value value column is 120 points, so detail dates use the stacked key-value layout. Earlier captures omitted Cooking's ingredient list while the in-memory fixture still held temporary identifiers; the sample factories now save before creating navigation and cooking state. Cooking was not recaptured after this fixture correction. Runtime logs retain three SwiftUI glassEffect() multiple-update faults and simulator system messages, with no Cookle crash or SwiftData exception. VoiceOver, Increase Contrast, physical devices, and every iPad route remain unverified.

MHUI 1.19 Refresh

Commit a239626b advances the remote minimum and resolved dependency to MHUI 1.19.0 at 81f48d1784ad85aadf4fccdf1e4e85606ac5c142. The built Xcode checkout and workspace resolution match that published tag. The project and resolved-pin guardrails reject the previous 1.18 baseline.

The standard theme and components supply the revised low-chroma palette, softer text and surface treatment, motion timing, and removal of heading rules. Cookle uses none of the removed heading-cue APIs. The initial compatibility pass required no app Swift changes or theme overrides. The subsequent composition pass below applies the design intent to app-owned layouts.

The Cookle Simulator build and retained repository checks pass, with no build warnings or errors. Verification uses Xcode 27.0 (27A266a) and iOS 27.0 Simulator; it does not establish shipping-Xcode or device evidence. Shared models, Operations, persistence, and companion linkage are unchanged, so this update does not add a separate shared-library test result.

Native runtime verification on iPhone 18 Pro covers the existing recipe list, detail sections through the lower actions, and opening and cancelling the edit form. The app remained running throughout, with no new visible layout or navigation regression in those routes. The run did not edit or save fields, delete records, or operate the existing cooking session. An initial device-session timeout recovered after session reinitialization. Runtime logs contain Simulator, networking, and Watch-pairing diagnostics, but no app fatal error or CoreData/SwiftData exception in this flow. The verification run and interaction sessions were stopped, and the original Xcode scheme and destination were restored and confirmed.

Three direct native Preview captures cover the first viewport of the new-recipe form and active cooking screen in Light, plus cooking in Dark with AX 5 text. The visible content remains readable; lower actions are not covered by those captures. Recipe Detail's updated direct Preview failed with a swift_task_dealloc/SwiftUI abort during injection. The 1.18 baseline returned a screenshot but also logged a later CoreData/SwiftData abort. These failures remain Preview/runtime diagnostics, not an isolated MHUI regression or proof of stable Preview execution. The separate iPad cooking Preview timed out and supplies no iPad evidence. These are two failed 1.19 Preview attempts; the edit-form Preview was not attempted because its existing production route was selected for interaction.

Current-run images, logs, and coverage are retained locally under .build/ci/mhui-1.19/. The historical rollout evidence below remains scoped to MHUI 1.18. Its destructive-action contrast review remains open; this dependency update does not establish VoiceOver or release acceptance.

Recipe Composition

Commit 91ddaba5 applies the recipe composition refinement.

The pinned SDK's visual principles distinguish a quiet content plane, important controls, and selective emphasis for photos and summaries. Cookle applies those roles to Recipe Detail through compact facts, unframed prose, and selective use of grouped surfaces.

  • The photo leads into serving size and cooking time, followed by the primary cooking entry and the action to add the recipe to today's diary.
  • Recipe facts share one compact row and stack at accessibility text sizes.
  • Ingredients, categories, and diary history retain grouped surfaces. Steps and notes use shared typography and headers on an unframed reading plane.
  • Creation and update dates form a compact metadata footer. Share and Duplicate use quiet actions; deletion retains its destructive style and confirmation. Edit remains available in the native toolbar.

The standard theme, SDK metrics, recipe data, action handlers, and native list/form routes are unchanged. Native search and Intent snippet reuse keeps its existing section presentation.

Cooking Composition

Cooking applies the same hierarchy to a focused task. Progress appears once, the current instruction uses unframed reading space, and Previous/Next sit before the grouped timer controls. The separate Step Navigation surface and repeated step number are removed. Existing timer actions, lifecycle behavior, and the End Session confirmation remain.

Standard text sizes retain native horizontal paging with a scaled reading height. At accessibility sizes, the current instruction takes its natural height in the screen's scroll view. Changing steps returns the viewport to the progress and instruction so reading can restart from the beginning.

Composition Verification

The recipe composition passed a Cookle Simulator build and retained rules. Native interaction covered the iPhone overview, ingredients, unframed steps and note, diary history, dates, and secondary actions. Edit/Cancel, the Add-to-Today confirmation and dismissal, Resume/Close, and the deletion confirmation and dismissal preserved the existing record and cooking session. Dark appearance with AX 5 text showed stacked facts, wrapping primary actions, and readable instructions in the captured viewports.

The final combined app installed and ran through Xcode's native integration; its build log reported success with no warnings. In the existing iPhone cooking session, Next/Previous and horizontal paging each advanced and returned successfully. At Dark AX 5, scrolling past the progress indicator and selecting Next returned the next instruction and progress to the top. The End Session confirmation was cancelled, and no timer was started. The sample returned to step 1 with no timer and its original Light/Large settings. The final runtime log filter found no fatal, SwiftData/CoreData exception, abort, or crash messages in the exercised flow. The retrieved error/fault log tail includes a glassEffect() multiple-update diagnostic also observed in the earlier 1.19 dependency and recipe runs. The observed controls and screenshots remained usable; these observations do not isolate its cause or establish warning-free runtime behavior.

The iPad landscape check used its existing synthetic recipe with a long name and note. It covered the grouped ingredients and closing metadata/actions; that record had no photos, summary facts, steps, categories, or diary history. One native device-session timeout recovered after reinitialization. These captures establish the exercised wide layout, not every populated iPad state.

An intermediate native borderless Delete treatment exposed a 21-22 pt target height. The implementation uses the SDK's destructive style, which supplies the shared minimum target, and keeps the existing confirmation. The final iPhone check measured a 354 by 45.7 pt button and successfully opened and dismissed the confirmation without deleting the recipe.

Two native cooking Previews succeeded on iPhone: Light with standard text, and Dark with AX 5 text. They show the same isolated active-timer fixture. The current iPad cooking Preview timed out with PreviewsFoundationHost.TaskTimeoutError and returned no screenshot. This remains a Preview coverage gap, separate from the recipe's iPad runtime check.

Local before/after captures, hierarchies, and runtime logs are retained under .build/ci/mhui-composition-20260915/. No recipe fields were saved or records deleted during the interaction checks. Physical devices, VoiceOver, and a shipping-Xcode build remain separate evidence. Verification runs and interaction sessions were stopped. The original scheme, destination, and Simulator settings were restored and confirmed, and the workspace opened for this verification was closed.

Presentation Choices

MHUI 2.0 chooses each screen route explicitly: content List/Form presentation for product collections, details, and editors, stack composition for freely arranged reading and task screens, and native presentation for settings, subscription, and diagnostics. No List, Form, or screen-level ScrollView is nested inside mhScreen. The table reflects the routes as updated for 2.2, where native presentation keeps platform grouping and row geometry on MHUI's canvas and row surfaces; the earlier refinement history below describes the preceding baseline.

The September 17 refinement is implemented by b9133ecf, 5292ccd6, and 99c26972. It moved Recipe browsing, Search results and states, and the Diary landing screen to composed MHUI surfaces without changing their routes or data operations. The 2.0 update follows the released package guidance for content List presentation while retaining the composed Recipe Detail route.

Surface Choice Preserved behavior
Recipe list Content List with MHContainerContent; unframed empty state Resume entry, sort, recipe rows, custom selection routing and context actions
Recipe Detail mhScreen with native title, open-canvas sections and grouped rows Photos, facts, cooking and diary actions, tag and diary routes, sharing, duplicate and delete
Recipe diary history Content List with MHContainerContent Chronological diary rows and diary routes
Recipe form Content Form with explicit mhRow() rows and MHUI headers Fields, photo controls, reordering, deletion, drafts, Save and Cancel
Diary landing mhScreen and sections Today, suggestions, chronological month groups and navigation
Diary detail and recipe selection Content List with MHContainerContent Meal groups, recipe routes, multi-selection, search, notes and actions
Diary form and new-recipe registration Content Form Date picker, meal selection routes, note, validation, Save and Cancel
Search Native searchable field; content List results; unframed states Search activation, discovery routes, result navigation and keyboard behavior
Ingredient/category tags Content List/Form with MHContainerContent Search, selection, rename and merge/delete conditions
Settings Native List with MHContainerContent Native settings controls, footers, destructive and disabled states, and the Shortcuts link row
Subscription host Native List without an added row surface MHPlatform-owned StoreKit section and its own background
Photo collection mhScreen and mhSection around the existing adaptive grid Source groups, image order, minimum thumbnail width and navigation
Photo detail Content List with MHContainerContent Preview size, recipe associations, dates, full-screen route and deletion confirmation
Detached recipe editors MHUI input chrome around the existing TextEditor Full-height native editor, placeholder, keyboard, text conversion, inference and Cancel
Cooking mhScreen with native title, sections and semantic actions Step list and selection, timers, End Session and diary continuation
Debug lists and object inspectors Native List with MHContainerContent; the Previews list adds no row surface Existing diagnostic content, model routes, package-owned previews and native swipe behavior

Native and Owning-Package Presentations

Full-screen photo paging retains its native black media canvas. Horizontal recipe photo carousels and form photo strips retain native scrolling. System navigation, tabs, toolbars, searchable fields, empty/loading controls, alerts, sheets, pickers, camera, sharing, TipKit, and startup/update presentations retain their native or owning-package behavior. App-owned result and state hosts may use MHUI layout without reimplementing those controls. Subscription, advertisements, licenses, and logs remain owned by MHPlatform. App-owned host containers may use MHUI without restyling the package's controls.

Compact form suggestion chips and photo-overlay controls retain their existing native interaction chrome. App Intent search snippets keep the native presentation of reused recipe sections. Navigation wrappers inherit the application theme and do not add a second screen container.

Detached editors keep their full-height native TextEditor and keyboard-resizing canvas. MHUI owns the input inset, fill, border, and focus treatment. Adding mhScreen here would introduce an unnecessary outer scroll container.

Verification Record

The recipe list/form slice is committed as 7efbec7a. The Swift formatter, repository rules, and diff checks pass. Native Xcode builds succeeded for that slice and the subsequent app-wide presentation changes, both with zero errors. Verification uses Xcode 27.0 (27A266a) and iOS 27 simulator tooling; it is not shipping-toolchain evidence. Source and project hashes matched the recorded handoff before and after the full build.

The rollout starts from the installed application with five synthetic recipes, ten diaries, ten photos, and an existing cooking session on a dedicated iOS 27 iPhone simulator. Before captures include recipe list/form, diary list/detail/ form, search, tag list/detail/form, settings, and the photo collection. Edit forms were cancelled without saving; no store was erased or reseeded.

Current-run logs, screenshots, source identity, and native integration responses are retained locally under .build/ci/mhui-rollout-20260914/. Only exercised states count as runtime evidence. Builds and simulator checks do not establish VoiceOver, real-device, distribution, or release readiness.

The screen choices above are implemented. The following evidence describes the exercised states; it is not a complete device or accessibility matrix.

Recipe List retains the Resume entry and five rows. The form shows the same name, photos, inference entry, serving size, time, and six ingredients. Focus opens the Japanese keyboard and Cancel returns to Recipe Detail. At accessibility size 1, the observed first four ingredient names and quantities remain readable in the native adaptive layout. That capture does not cover every field at large text sizes.

The cooking slice is committed as 6cc21b25. Next/Previous and horizontal paging each moved from step 1 to 2 and back. A one-minute timer counted from 00:59 to 00:50, then Cancel returned to the idle choices. End Session opened its existing confirmation; Cancel and Close retained the session. Dark and accessibility size 1 captures show the lower actions without text overlap. Another one-minute timer expired naturally and displayed Timer Finished, Repeat, Next Step, and Cancel Timer. The timer follow-up's Next Step moved to step 2 and cleared the timer; Previous restored step 1. Repeat was not invoked. The final sample is restored to step 1 with no timer, Light, and Large text.

The detached-editor slice is committed as 16ad954e. Both the recipe-text inference editor and bulk editor retain their existing content and Japanese keyboard behavior. Focus shows the MHUI input border and keyboard-resized viewport. Cancel returns to unchanged parent form values; cancelling that form returns to Recipe Detail. Inference, Done, and Update were not executed.

The diary slice is committed as 13e8d8d6. List, meal-group detail, and the native date/meal form retain the baseline content. The breakfast chooser accepted and removed a temporary carbonara checkmark, restored its original pancake selection, and returned to the form. Cancel returned to Diary Detail without saving. No diary information-architecture change is included.

The search/tag slice is committed as 03d0dcda. A carbonara query displayed the matching recipe and photo; clearing the query restored discovery. Category list, detail, and form retained Italian and its associated recipe; Cancel returned without renaming. Existing English fragments in tag copy remain unchanged.

The settings/diagnostics slice is committed as e066f5ca. Settings and the loaded subscription presentation were inspected without changing settings, purchasing, or restoring. Debug navigation reached the model list, ingredient-object list, and an ingredient inspector showing the same value, amount, order, recipe, and dates. This is representative shared-container evidence; every diagnostic object type was not individually exercised.

The photo slice is committed as bdaa7a8b. Both source groups retain their five photos and original order. The adaptive grid keeps its 120-point minimum; MHUI's screen margins change the phone view from three to two columns. Scrolling reveals all ten photos. Opening the Image Playground carbonara reaches its recipe/date metadata and full-screen image; closing and returning retains the original grid scroll position. No image was deleted or replaced.

The same built app was installed on a dedicated iOS 27 iPad simulator with its existing single synthetic recipe and no photos. The centered native recipe form retained its 580-point sheet width. A long ingredient name wrapped onto two lines while its quantity stayed in the trailing column; Cancel retained the existing data. The Photos sidebar displayed its native empty state. This does not cover a populated iPad photo grid or every form and navigation path on iPad.

Native rendering of the existing CookingSessionView preview succeeded in portrait and landscape. The landscape capture shows the progress and step card at a wide viewport. Its lower actions were outside that initial preview viewport, so it is supplementary layout evidence, not iPad interaction proof.

Destructive-button contrast remains a shared-treatment review item. A sampled sRGB screenshot estimate for End Session is approximately 2.8:1 in Light and 3.4:1 in Dark. MHUI uses semibold body text here; the Apple HIG contrast guidance lists 4.5:1 for text up to 17 points. This sample is not an Accessibility Inspector certification and does not cover changing glass backgrounds, pressed states, or all devices. Verify and address the MHUI destructive treatment before claiming contrast acceptance. The MHUI package and its base palette were not edited in this app-local rollout. The local runtime/contrast-samples.json records pixel locations, RGB samples, and image hashes.

An intermittent navigation observation is retained separately: in the older recipe-list/form build, List's Resume Cooking entry followed by Close once left the Recipe Detail large title invisible. The final presentation build showed the title after that route and retained the inline title and scroll position after Detail's Resume entry. One check of each final route did not reproduce the disappearance. No routing fix was made, and its cause or resolution is not established.

Runtime logs are not warning-free. The full build's phone run recorded eight SwiftUI glassEffect() multiple-update faults during cooking, form dismissal, diary navigation, and category presentation. The preceding recipe-only run also recorded two, but its coverage differs, so the counts do not establish a regression rate or cause. Native subscription presentation recorded six StoreKit navigation-destination-in-lazy-container warnings and one repeated bound-preference warning. The app remained in the same process and the observed controls remained usable. Subscription links, purchase, and restore behavior were not verified. Raw logs and the extracted full-errors-faults.log remain local under the rollout runtime directory. The iPad run recorded no SwiftUI Invalid Configuration messages, but retained WebKit-launch and system messages; neither run is a clean-log acceptance result.

The standard integration initially lost its workspace interaction session and reported a simulator connection failure. Verification recovered through the official persistent Xcode bridge: native builds produced fixed app artifacts, and official simctl installed those artifacts on the dedicated simulators. Subsequent interaction-session loss was recovered without restarting the phone app. A stale success log was excluded from the build evidence.

Verification runs and interaction sessions were stopped. Xcode's original Cookle scheme and iPhone 18 Pro destination were restored and rediscovered to confirm the final selection. Only the two dedicated verification simulators were shut down; the original project window remains open.

Representative Before and After

These original screenshots use the same synthetic production-app data and Japanese locale. The comparison changes presentation only. Native form fields and their layout remain; MHUI supplies the shared canvas.

Before MHUI
Recipe form before Recipe form after
Cooking controls before Cooking controls after
Bulk editor before Bulk editor after
Photo grid before Photo grid after

Cooking keeps the same 320-point step pager and native long-step scrolling. MHUI replaces glass content panels with stable surfaces and moves the existing section headings above those surfaces. Controls keep their actions and order; the changed spacing makes the full sequence taller. The comparison scrolls to the same lower actions, so the visible part of the step card differs.

The photo collection trades first-viewport density for shared screen margins and larger thumbnails. Its second group continues below the first viewport; the lower grid capture shows the remaining images. Cooking also has targeted Dark and accessibility size 1 captures. These show wrapping and layout, not quantitative contrast acceptance. The expired timer records the third timer state and its three existing actions. The iPad ingredient form records native sheet layout and long-name wrapping with a separate existing synthetic recipe.

Destructive Contrast Measurement

Measured 2026-09-21 on the current build, replacing the earlier estimate the audit flagged as unusable. Surface: the cooking session's running-timer card, whose Cancel Timer label is the app's only destructive text in that flow. Devices: iPhone 18 Pro (402x874 pt, 3x) and iPad 11" (834x1210 pt, 2x), both iOS 27.0. Values are sampled from the screenshots by luminance, taking the darkest and lightest pixel inside the label's glyph band, and the ratio is the WCAG relative-luminance formula.

Appearance Label Background Ratio
Light #FF383C #FFFDFA 3.52:1
Light + Increase Contrast #E9152D #FFFFFF 4.56:1
Dark #FF4245 #25221E 4.61:1
Dark + Increase Contrast #FF6165 #0C0E0F 6.59:1

Phone and tablet produce identical values, so this is a colour result rather than a layout one.

The label's glyph band measures 41 px at 3x and 26 px at 2x, so roughly 13 pt, and it is not bold. WCAG's large-text allowance of 3:1 therefore does not apply and the threshold is 4.5:1. Light appearance without Increase Contrast is the one condition below it. Dark appearance, either Increase Contrast setting, and any accessibility text size all clear the threshold; at accessibility-extra-large the same colours pass only because the 34 pt glyphs do qualify as large text.

Reduce Transparency was enabled through Settings and the cooking screen recaptured. The glass close control lightens from #F0EEE8 to #F5F5F3 and the navigation bar gains a separator, so the control layer does respond. The step card interior is byte-identical at #FAF8F3, confirming that content surfaces are already opaque and carry no glass to reduce. The destructive ratio is unchanged at 3.52:1, so Reduce Transparency is not a mitigation here.

This is a measurement, not an accepted visual direction. Choosing between a darker destructive tint, a filled treatment, and leaving the system colour as Apple supplies it remains open on #119.