diff --git a/investigation/ui-parity-matrix.md b/investigation/ui-parity-matrix.md index 6d17846a..d8d710c4 100644 --- a/investigation/ui-parity-matrix.md +++ b/investigation/ui-parity-matrix.md @@ -33,16 +33,95 @@ Statuses: - `Divergent`: Windows exposes a different product concept in the place where the macOS surface belongs; it must be separated or redesigned before parity. - `Out of scope`: removed from the parity requirement by a product decision. The row - is kept for history and is tracked as an enhancement issue. It is not counted as a - parity surface. + is kept for history and is not counted as a parity surface. This includes + source-confirmed extras under the 2026-10-13 policy: a row may remain in its + historical section, with its parity issue narrowed and any removal separately + approved. Optional additions use enhancement tracking; an unwanted extra's + removal is not a request to add an enhancement. + +## 2026-10-14 reference intake + +The primary local macOS recording is source +`2ccf303a04f995184aae1d4b738a9eca0f71b79e`: 354 items, comprising 244 +Recorded, 4 Differs from request, 3 Absent on macOS and 103 Exists, not recorded. +It records observations, not conformance. The bounded different-vendor intake +opened 12 primary and 3 comparison images and checked 5 metadata negative controls; it +did not visually review all 784 images. Follow the canonical worker kickoff's +publication-hold notice and individual image privacy-clearance rule. Neither +reference bundle is committed here. + +The `764-final-fixtures-fitted` images show the **ParityRef project canvas at +90%**, despite stale global-selection labels. Use them for the recorded cards, +not global-graph, overview-start or lane-caption evidence. The separately +recorded global overview is fitted at 45%. Copy scale, backing scale and +canvas zoom are different measurements; source card size remains 250x96. + +The Windows reference below is **Windows beta26 (pre-wave-1)**, installed +`0.1.78-windows.beta26`, not current main or a wave-2 head. A historical pair +cannot validate current behavior. The 30 rows recovered from the earlier +review's unassessed list are therefore `Partial` qualification gaps until +their required current pairs and runtime evidence agree. This is not a product +failure finding and does not reopen a closed functional issue merely because +a macOS state was not recorded. Existing Windows functional evidence is retained. + +The 98 row identities are unchanged. This intake changes 30 unsupported visual +validation statuses and classifies the sidebar-only Needs-you extra outside +parity: **6 Validated / 89 Partial / 3 Out of scope**. Historical dated counts +below remain historical. Final A-E merged-slice reconciliation is separate; +no whole claim is closed by this reference intake. + +| Recovered row | Exact macOS reference or limit | Historical Windows pairing / current qualification | +| --- | --- | --- | +| Update command | Dev-build disabled command recorded, not release offer/install | Menu/readback context only; current recapture required | +| Tray lifecycle | No dedicated macOS tray counterpart established | Retain native restore/exit evidence; platform qualification and current recapture required | +| Connection failure presentation | Daemon-disconnected attempt differs; graph remains, no recorded banner | No matching historical failure image; source/state review and current recapture required | +| No-project Welcome detail | Fresh Welcome recorded | Historical Welcome pair reviewed; icon, background, density and button differ; current recapture required | +| Empty global graph | Exact empty state not established by populated overview | Historical empty-global candidate is not a matching macOS pair; current recapture required | +| Empty project canvas | Exact selected-project empty state not recorded | Empty lanes/global overview are not substitutes; current recapture required | +| Project context menu | Folder-row popup recorded; actions not executed | Historical project popup not captured; exact selection/action qualification and current recapture required | +| Recent projects | Add Folder recents recorded | Historical native-menu readback is not a screenshot pair; current recapture required | +| Add Folder menu | Open/Clone/Remote/Codespace and recents recorded | Compare exact menu context, not a neighboring popup; current recapture required | +| Sidebar update banner | Exists, not recorded; updater environment needed | Windows offer is a different surface; current recapture required | +| Sidebar error footer | Clone failure differs; other error paths remain source-backed | No exact historical footer pair; current recapture required | +| Activity strip | Optional bottom strip now recorded | Historical Windows activity is in the sidebar, not below the canvas; current recapture required | +| Node positioning | Static fit/layout is not direct-move or persistence evidence | Preserve Windows drag/persistence evidence; source applicability and current recapture required | +| Connector handles | Actual drag recorded; not every hover/context | Historical connector/form evidence is not a current paired hover/drag verdict; current recapture required | +| Worktree reclaim offer | Sweeper capture is not resolved-card Reclaim/Keep | Exact macOS inline offer remains unrecorded; current recapture required | +| Composite card actions | Idle/stopped context menus recorded, not action results | No exact historical Composite action pair; current recapture required | +| Composite breadcrumb | Loop bar is not the group breadcrumb | Exact macOS breadcrumb pair unavailable; current recapture required | +| Quick Chats canvas | Populated two-chat canvas recorded | Historical Windows canvas is empty; it is not a populated pair; current recapture required | +| Quick Chat cards | Populated cards/menu recorded without backend execution | No exact historical populated-card pair; current recapture required | +| Rename chat | Named title prompt recorded | No historical chat-rename prompt pair; current recapture required | +| Delete chat | Named confirmation recorded; no deletion performed | No historical chat-delete prompt pair; current recapture required | +| Chat rename/delete | Same two prompts, distinct ledger claim | Reusing references does not double-count proof; current recapture required | +| Open Folder | Entry points recorded; successful native picker operation not recorded | Preserve Windows picker/cancel evidence; native chrome may differ; current recapture required | +| Clone Repository sheet | Empty form/local failure recorded; no successful clone | No exact historical clone-form pair; current recapture required | +| Add Remote Repository sheet | Blank ingress form recorded; no remote dial | Advanced connection diagnostics are not this ingress form; current recapture required | +| Remote Connection info | Exists, not recorded | Blank Add Remote form is not established connection info; current recapture required | +| Project Settings sheet | Source confirms controls; no exact recording | Historical Windows Settings sheet reviewed, but macOS app Settings is not its pair; current recapture required | +| Available update alert | Exists, not recorded in a release-configured environment | Historical beta26 offer remains functional evidence for closed #741, not a new visual pair; current recapture required | +| Project delete loops | Confirmation recorded; fixture not deleted | Historical loop-delete prompt is not project-delete-loops; current recapture required | +| Project remove/trash | Remove and Trash alternatives recorded; nothing removed | No historical project lifecycle dialog pair; current recapture required | + +Source-confirmed absences are narrow. The normal macOS sidebar's attention +section is commented out; toolbar/canvas attention remains. A generic free-text +status band is absent, not all errors or progress. All three edge kinds are +executable, so an inert-kind/Fires-disabled requirement is invalid, not the +Fires picker. Narrow those criteria before planning a separate Windows-extra +removal; do not fold removals into the approved A-E slices. Activity is recorded, +not an extra to remove. The richer New Workspace preview/footer and Save +Template scope options now have reference captures but remain unmatched by +the bounded #808 geometry fix; its six whole claims remain open. ## Preview delivery lanes The [Windows preview-readiness plan](windows-preview-release-plan.md) separates release-critical functional bugs/core qualification, optional functionality, -polish, and evidence gaps. It maps every current Partial surface to a delivery +polish, and evidence gaps. It maps the pre-intake Partial set to a delivery lane and alpha disposition without changing this ledger's macOS-equivalence -rule, row names, statuses, or existing evidence. A scoped tester preview need +rule, row names or existing evidence. The 30 reference-only qualification rows +above are not yet mapped by that plan; they do not assert new release-blocking +product defects or change its functional priorities. A scoped tester preview need not wait for full parity, but unreadable terminals, lost input, unreachable controls and unsafe mutations are not cosmetic work. @@ -109,9 +188,9 @@ process dump and child-process inventory before shared product changes. | File/Loop/Terminal menus | Discoverable project, worktree, navigation, workspace, update, settings, and help commands with state-aware enablement | Startup menu replacement and UTF-16 corruption are fixed. Reclaim/Reveal require a selected row; Save requires the Worktrees dialog open. Worktrees inspection and reclaim now run on owned background workers; while provider work is active the native File menu, project/background menus, and fixed UIA action patterns derive a busy capability instead of advertising a second invocation. The fixed UIA action nodes are offscreen with empty bounds rather than sharing the visible Graph rectangle. Loop commands use distinct actionable-target thresholds, and Terminal tab/pane commands require multiple tabs or panes. Hidden-window tests call `MainWindow.updateMenu` and verify the real native HMENU `MF_GRAYED` bits in unavailable and available states. The green Windows shell CI run 36489223062 inspected the live File > Add Folder and Recent Folders HMENU labels/order, invoked a real Recent Folders command without terminating the shell, and exercised live Help/update enablement transitions; its workspace walkthrough also created and switched mounted tabs. The new Worktrees busy/UIA behavior has App/native-linked unit coverage but no installed Dev Box walkthrough yet. Windows CI did not read the complete live Loop/Terminal menu states in equivalent graph and terminal contexts or exercise their keyboard commands. Unit HMENU coverage and adjacent workspace actions cannot substitute for that missing user-visible walkthrough, so the row remains `Partial`. The beta25 Dev Box qualification (`0.1.78-windows.beta25`, installed package, production `graphcoded`, 2560x1440 at 100%, injected `SendInput` and UIA; return bundle reviewed 2026-10-13) D8 read the live File, Loop, Terminal, Workspace, View and Help menu labels and shortcuts, and 6F exercised Ctrl+Shift+T, Alt+Shift+D and Ctrl+Shift+W. Enablement states in graph versus terminal contexts were not read, so the row stays `Partial`. The 2026-10-13 testing-gaps Dev Box run read every native menu item in three contexts. Six macOS Loop-menu commands have no Windows equivalent: Back, Forward, Show/Hide Loop Panel, Restart Session, Restart All Sessions… and Send Message to All Loops…. Enablement also diverges: with no workspace open, Windows enables Show in Graph, Stop Loop, New Tab and the splits, and in a one-pane workspace it disables Close Pane and Close Tab. **Tracked in [#722](https://github.com/scgopi/GraphCode/issues/722) (implementation gap).** | Partial | | Workspace lifecycle | List/switch, create, rename, delete with fail-closed confirmation, and keyboard/UIA reachability | Windows discovers `Default` plus `.graphcode-*` siblings and exposes New/Rename/Delete and Ctrl+Alt paging. Manage now has an owned row model/native list, Default/creation-time/name-tie order, identity-deduplicated current-outside-home inclusion, full-path detail, current/default/open/uncertain-window refusals, and captured-identity Open/New/Rename handoff after modal teardown. An App-owned single joinable reader supplies bounded **saved top-level** graph-header counts, not live/descendant totals; current live content, missing/unreadable/invalid/duplicate/limited/unsupported-location data remain explicitly unavailable, not partial zero. Fixed local/non-reparse reads use existing project JSON and the documented mailroom-array exception, no daemon/backend or window activation. Done/Escape cancels; pending actions wait for reader cancellation/join while the modal pumps, and shutdown drains before allocator teardown (a stalled local disk can delay shutdown). Manager Delete is enabled and shares rename's refusals, identity revalidation after confirmation, and reservation; deletion itself is recoverable: the folder is staged aside, the target workspace's daemon is stopped by its own derived shutdown event, the folder goes to the Recycle Bin with `FOF_ALLOWUNDO`, and only then are its saved sessions ended with `zmx kill --force`. A failed stage refuses without effect, a daemon that will not stop or a failed recycle renames the folder back and ends no sessions, and a failed rename-back reports the exact staged path instead of claiming a rollback. Ordinary menu ordering/Open/New semantics are unchanged. Next/Previous now reread the manager-ordered list, include validated current outside home, filter identified running windows, wrap both ways, recheck the target, and use a restore-only API with no launcher. Closed/disappeared targets never cold-open; any unidentified flag or lookup/restore failure refuses with status. Existing SID/session/class/published-metadata checks are preserved, not executable-path attestation. Menu capability counts known rows plus implicit current, without periodic window polling. Injected production-helper RED/GREEN, allocation-failure/owned-refresh, ordering/dedup/offset/race/refusal tests and pure menu-capability tests execute in the existing App/MainWindow roots; full native roots compile/link without execution and the ReleaseSafe app builds without launch. Manager coverage remains pure owned-data/explicit disposable fixtures, controlled memory-only joined threads, and filtered form/App data seams; no new shown manager/native-control/window-lookup/UIA/runtime proof is claimed. Existing lifecycle helper and never-shown native-control regressions cover accepted text lifetime, allocation cleanup, normalized naming/collisions, lexical identity, exact-window and one-launch routing, Default/current/open refusals, child-only support/daemon-pipe isolation, canonical plus legacy reservations, unidentified-window refusal, fail-closed Settings rebinding, and disposable confirmed mutation preservation. Lexical identity is not junction equivalence. Shown-dialog accessibility/keyboard/layout, full multi-instance/save-reload behavior, reliable live totals, and real running-cycle keyboard/window proof remain residuals. Deletion's evidence is unit-level only: every teardown effect is injected through a comptime seam, so no test recycles a folder, signals a real daemon, or kills a real session, and no live walkthrough has confirmed a recovered folder in the Recycle Bin, a daemon actually exiting, or sessions actually ending. Sessions saved outside the workspace's own `projects` directory (extra terminal tabs/splits, whose layout files are written relative to the process working directory) are not discoverable for a non-current workspace and are reported as unended rather than assumed absent. Shared-host menu failures still have an unproven cause; no full lifecycle parity or host-only diagnosis is claimed. Narrowed 2026-10-13 to macOS scope (requirements macOS lacks were dropped; see the issue). **Tracked in [#723](https://github.com/scgopi/GraphCode/issues/723) (implementation gap).** | Partial | | Help menu | GraphCode Basics and normal About entry | The live Help menu exposes GraphCode Basics, which reopens onboarding, and About GraphCode, which opens a native versioned product dialog. The populated UIA gate verifies the dialog identity, version text, and close behavior | Validated | -| Update command | Check for Updates, disabled while checking/installing | Reachable from the Help menu's native menu bar, immediately reports "Checking for updates..." status and disables the command the instant a check is invoked, and — after fixing a real bug where the background check's completion never refreshed the menu bit because the only refresh path was gated on unrelated daemon-connectivity state — now reliably re-enables the command once the check settles. A dedicated live UIA gate assertion (reading the real native `HMENU` bit via `GetMenuState`, not the fragile UIA tree) and a Win32-window-backed unit test both confirm the disable/re-enable cycle. When the settled result is an available update, the gate additionally waits for the real offer, dismisses it via Later, verifies the modal disappears, and requires the shell owner to be enabled again before continuing; failure/no-update outcomes are required not to present an offer. In-app installation is now implemented as a separate scope (see Install progress/Relaunch prompt, Partial) | Validated | -| Tray lifecycle | Restore and exit without foreground daemon window | `TrayLive.Tests.ps1` exercises the physical icon, Open, close-to-hide, single-instance restore, Explorer recovery, popup contents, and visible Exit activation | Validated | -| Connection failure presentation | Explicit visible failure without replacing normal navigation | A persistent inline canvas banner now reports daemon unavailability while leaving sidebar and destination navigation intact; ingress errors take precedence when present. The live UIA gate forces the disconnected state and verifies the dedicated banner text and bounds | Validated | +| Update command | Check for Updates, disabled while checking/installing | Reachable from the Help menu's native menu bar, immediately reports "Checking for updates..." status and disables the command the instant a check is invoked, and — after fixing a real bug where the background check's completion never refreshed the menu bit because the only refresh path was gated on unrelated daemon-connectivity state — now reliably re-enables the command once the check settles. A dedicated live UIA gate assertion (reading the real native `HMENU` bit via `GetMenuState`, not the fragile UIA tree) and a Win32-window-backed unit test both confirm the disable/re-enable cycle. When the settled result is an available update, the gate additionally waits for the real offer, dismisses it via Later, verifies the modal disappears, and requires the shell owner to be enabled again before continuing; failure/no-update outcomes are required not to present an offer. In-app installation is now implemented as a separate scope (see Install progress/Relaunch prompt, Partial) | Partial | +| Tray lifecycle | Restore and exit without foreground daemon window | `TrayLive.Tests.ps1` exercises the physical icon, Open, close-to-hide, single-instance restore, Explorer recovery, popup contents, and visible Exit activation | Partial | +| Connection failure presentation | Explicit visible failure without replacing normal navigation | A persistent inline canvas banner now reports daemon unavailability while leaving sidebar and destination navigation intact; ingress errors take precedence when present. The live UIA gate forces the disconnected state and verifies the dedicated banner text and bounds | Partial | Running-cycle follow-up evidence: the final lookup actually used for activation now refuses mixed identified/unidentified results before activating that same @@ -128,9 +207,9 @@ native keyboard/accelerator/window proof; the workspace row remains Partial. | macOS surface | Required visible behavior | Windows evidence | Status | |---|---|---|---| | Four-page onboarding | Visual terminology tour, Skip/Back/Continue/Get Started, backend selection, reopen, persisted seen state | Custom rounded Win32 onboarding retains all four pages, Skip/Back/Continue/Get Started, backend selection, and Help > GraphCode Basics reopen. The 2026-10-01 manual package launch from `59ebed1` correctly demoted the earlier unsupported `Validated` claim by exposing four defects. Current accepted main fixes their source paths without supplying the final package flight: [#573](https://github.com/scgopi/GraphCode/pull/573) honors the effective `GRAPHCODE_SUPPORT_DIR` (3/3 focused, 10/10 full onboarding tests) and closes [#554](https://github.com/scgopi/GraphCode/issues/554); [#577](https://github.com/scgopi/GraphCode/pull/577) makes the startup endpoint available before the rendezvous secret exists (focused GREEN, 177/177 DaemonClient tests) and closes [#555](https://github.com/scgopi/GraphCode/issues/555). App-native stack `#581` then merged [#579](https://github.com/scgopi/GraphCode/pull/579), scheduling the daemon callback/connection before genuine first-run onboarding enters its modal loop, and [#580](https://github.com/scgopi/GraphCode/pull/580), adding a named UIA fragment tree plus shared deterministic UIA/mouse/Tab/Shift+Tab/Enter/Space action and focus behavior. The stack passed 734/734 App tests and an isolated shown-window probe that discovered all four pages/actions, invoked navigation/backend controls, set UIA focus, and posted `WM_KEYDOWN` traversal. These are source, focused runtime, and shown-window results, not the ordinary installed production path or desktop-level native keyboard evidence. [#556](https://github.com/scgopi/GraphCode/issues/556) therefore remains open as source-fixed/evidence-remaining until the exact packaged install → first launch → onboarding → connected Welcome path runs with production `graphcoded`, an owned desktop, native keyboard operation, isolated persisted marker evidence, and any assistive-technology behavior claimed. Reopen/page content exist, but the whole macOS-equivalent visible/runtime contract is not yet qualified. The beta25 Dev Box qualification (`0.1.78-windows.beta25`, installed package, production `graphcoded`, 2560x1440 at 100%, injected `SendInput` and UIA; return bundle reviewed 2026-10-13) ran the installed package from a scrubbed 11-key environment against production `graphcoded`: first run showed all four pages, Back, the backend choices and Get Started; Escape, Skip, Complete and an existing marker each behaved as expected, and a relaunch did not reshow onboarding. Navigation used injected mouse clicks at UIA centers; native keyboard operation of onboarding was not exercised, so [#556](https://github.com/scgopi/GraphCode/issues/556) and this row stay open. Narrowed 2026-10-13 to macOS scope (requirements macOS lacks were dropped; see the issue). **Tracked in [#556](https://github.com/scgopi/GraphCode/issues/556) (testing gap).** | Partial | -| No-project Welcome detail | Graph icon, pitch, explanatory copy, Open Folder action, inline error | Windows matches the centered Graph identity, pitch, explanatory copy, and single Open Folder action. Persistent project-ingress failures now also render as a bounded, wrapped inline canvas alert without replacing navigation; focused geometry coverage and the populated UIA gate verify the alert text and live bounds | Validated | -| Empty global graph | “Nothing running yet”, explanatory copy, Open Folder action, New Loop action | The dedicated overview empty state exposes both bounded Open Folder and New Loop actions; New Loop targets the daemon's `graphcode://global` project. The live UIA gate switches to an empty model, verifies both visible native controls, invokes New Loop, and observes the node form | Validated | -| Empty project canvas | Project-specific empty message and New Loop action | The dedicated “No loops yet” project state exposes its visible New Loop action. The live UIA gate installs an empty local project, invokes that exact command, and observes the project-scoped node form | Validated | +| No-project Welcome detail | Graph icon, pitch, explanatory copy, Open Folder action, inline error | Windows matches the centered Graph identity, pitch, explanatory copy, and single Open Folder action. Persistent project-ingress failures now also render as a bounded, wrapped inline canvas alert without replacing navigation; focused geometry coverage and the populated UIA gate verify the alert text and live bounds | Partial | +| Empty global graph | “Nothing running yet”, explanatory copy, Open Folder action, New Loop action | The dedicated overview empty state exposes both bounded Open Folder and New Loop actions; New Loop targets the daemon's `graphcode://global` project. The live UIA gate switches to an empty model, verifies both visible native controls, invokes New Loop, and observes the node form | Partial | +| Empty project canvas | Project-specific empty message and New Loop action | The dedicated “No loops yet” project state exposes its visible New Loop action. The live UIA gate installs an empty local project, invokes that exact command, and observes the project-scoped node form | Partial | | Empty Quick Chats canvas | Explanation of Quick Chats and New Chat action | Live walkthrough verified the dedicated explanation and New Chat action with corrected non-overlapping layout **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found no glyph, shortened copy, no top-right New Chat, and the attention rail is drawn. **Tracked in [#774](https://github.com/scgopi/GraphCode/issues/774) (implementation gap).** | Partial | ## Sidebar @@ -143,14 +222,14 @@ native keyboard/accelerator/window proof; the workspace row remains Partial. | Project rows | Selection, folder type, hover New Loop, disclosure | Open project rows retain selection and local/remote glyphs, reveal hover-only New Loop and disclosure controls, and collapse/restore their own loop tree without changing row identity. The live UIA gate invokes the project-row New Loop action into the real native node form and exercises project collapse/expand through stable UIA actions. **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found "v L" glyphs and about 40 px gaps instead of folder rows with + and a chevron. **Tracked in [#767](https://github.com/scgopi/GraphCode/issues/767) (implementation gap).** | Partial | | Nested loop tree | Edge-derived hierarchy, persisted expansion, drag reorder of roots | Handoff edges derive a cycle-safe root/descendant tree; nested rows disclose and collapse by stable node ID, expanded IDs persist atomically in the GraphCode support directory, and root rows now reorder through live pointer drag backed by the existing transactional `root` records. Focused Sidebar/Wire coverage and the deterministic UIA gate verify observable reorder plus emission of the new `sidebarNodesReordered` daemon command for server-side persistence parity. **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found no indentation; children hidden; goal and timed loops not visible. **Tracked in [#767](https://github.com/scgopi/GraphCode/issues/767) (implementation gap).** | Partial | | Loop row presentation | Type stripe, title, elapsed time, state indicator | Rows now show a loop-type stripe, title, compact state indicator, and a compact elapsed value derived from `createdAt`. `Sidebar.elapsedText` now has focused boundary coverage for every unit rollover (seconds/minutes/hours/days) and its invalid-input guards (`created_at<=0`, `now<=created_at`), reverified via `zig test` and the full `WindowsShell.Tests.ps1` suite. This is still text painted directly onto the sidebar's `HDC` with no UIA identity of its own (the same limitation `Sidebar.updateBannerAt` had before this change), so a live assertion that reads the *rendered pixels* of the elapsed column was not captured this session; only the formatting logic and the row's overall live-rendering-without-crashing are executable evidence today. The beta25 Dev Box qualification (`0.1.78-windows.beta25`, installed package, production `graphcoded`, 2560x1440 at 100%, injected `SendInput` and UIA; return bundle reviewed 2026-10-13) rendered the stripe, title, state and elapsed columns without overlap, and a fresh loop showed `6s` in the sidebar with the loop bar at `elapsed <1m` (`section6b-age-d.png`, `f2-sidebar-h820.png`, reviewed). The elapsed text still has no UIA identity of its own. **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found every type bar orange; state shown as text instead of a dot. **Tracked in [#767](https://github.com/scgopi/GraphCode/issues/767) (implementation gap).** | Partial | -| Project context menu | Move, worktrees, settings, Explorer, remote info, close, remove, delete loops/project | Project rows expose the lifecycle actions plus the Windows Recycle Bin path for local folders. Move is deliberately **not** an Explorer `/select` alias: `GraphContextMenu.moveProjectMenuItem()` appends "Move Project... (unavailable: daemon support required)" with `MF_GRAYED` while `Wire.supportsProjectRelocation()` is false, and the stale command path surfaces that explicit reason instead of opening Explorer. The live UIA gate now drives the real `TrackPopupMenu` popup (`MainWindow.wm_uia_context_menu` -> the same `GraphContextMenu.show()` the mouse path calls) and asserts the live menu's ordered items, that Move is command 5149 with that exact text and a disabled state, that a remote project's menu omits Move/Recycle Bin/Explorer entirely, and that the popup dismisses without wedging the shell. Note the observation channel: a popup menu appears in the UIA tree only as an empty Pane with no `MenuItem` children, so item identity/text/enabled state are read through `MN_GETHMENU` and the Win32 menu API against the HMENU the shell handed to `TrackPopupMenu` — live evidence of what the shell actually renders, but not UIA-tree evidence. | Validated | +| Project context menu | Move, worktrees, settings, Explorer, remote info, close, remove, delete loops/project | Project rows expose the lifecycle actions plus the Windows Recycle Bin path for local folders. Move is deliberately **not** an Explorer `/select` alias: `GraphContextMenu.moveProjectMenuItem()` appends "Move Project... (unavailable: daemon support required)" with `MF_GRAYED` while `Wire.supportsProjectRelocation()` is false, and the stale command path surfaces that explicit reason instead of opening Explorer. The live UIA gate now drives the real `TrackPopupMenu` popup (`MainWindow.wm_uia_context_menu` -> the same `GraphContextMenu.show()` the mouse path calls) and asserts the live menu's ordered items, that Move is command 5149 with that exact text and a disabled state, that a remote project's menu omits Move/Recycle Bin/Explorer entirely, and that the popup dismisses without wedging the shell. Note the observation channel: a popup menu appears in the UIA tree only as an empty Pane with no `MenuItem` children, so item identity/text/enabled state are read through `MN_GETHMENU` and the Win32 menu API against the HMENU the shell handed to `TrackPopupMenu` — live evidence of what the shell actually renders, but not UIA-tree evidence. | Partial | | Loop context menu | Open, composite actions, rename, stop, delete | Sidebar and canvas loop rows share stable-ID Open, Rename, Stop, and Delete actions. Composite cards expose Open Group, Pilot Once, and Arm Schedule; the drilled-in canvas addresses mutations through the parent composite. The live UIA gate now opens and reads all three `wm_uia_context_menu` loop variants: target 3 (a plain wired loop) asserts Open/Rename/Stop/Delete are present and that every composite-only and unwired-only command is absent; target 6 (a composite, not-yet-piloted loop) asserts Open Group/Pilot Once/Arm Schedule are present with Arm Schedule rendered `MF_GRAYED` (not piloted), and that unwired-only commands are absent; target 7 (an unwired loop node, added live via the sidebar-reorder fixture mutation) asserts Wire it up/Mark as entry are present and composite-only commands are absent. As with the project context menu, item identity/text/enabled state are read through `MN_GETHMENU` and the Win32 menu API against the HMENU the shell handed to `TrackPopupMenu` — live evidence of what the shell actually renders, not UIA-tree evidence **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found no Export/Import or Change to…; Windows-only Edit Details; no separators. **Tracked in [#778](https://github.com/scgopi/GraphCode/issues/778) (implementation gap).** | Partial | -| Recent projects | Reachable from Add Folder menu | Recent and currently-open projects are now exposed as distinct sidebar rows, with unopened recents remaining under the LOCAL/REMOTE sections while open workspaces use separate `open-project` identities. The deterministic UIA gate verifies the split presentation and section behavior. The live gate now also walks the Recent Folders submenu reachable from Add Folder end-to-end: it sends a real `WM_INITMENUPOPUP` (the message `App.zig` uses to refresh `recent_folders` from the live model before a popup shows, so the read reflects the fixture's recent projects rather than pre-fixture placeholder state), reads the submenu's live items in fixture order with their stable `recent_folder_command_base`-derived command IDs, and invokes the second entry through the real `WM_COMMAND` route, confirming the shell routes it without crashing | Validated | -| Add Folder menu | Open Folder, Clone, Add Remote, recents | File now groups Open Folder, Clone Repository, Add Remote Repository, and Add Codespace under Add Folder and adds a dedicated Recent Folders submenu with its own command range; that submenu is now located rather than positionally indexed, so a new ingress entry can no longer silently retarget the rebuild. Focused MainWindow coverage validates the native menu structure and recent-folder command wiring. The live UIA gate now reads the Add Folder submenu directly off the live `HMENU` (`GetMenu`/`GetSubMenu`, not `TrackPopupMenu`, since this is the persistent menu bar) and asserts all four action labels plus the Recent Folders submenu; see the Recent projects row above for the live Recent Folders walkthrough this shares | Validated | -| Sidebar update banner | Available version and click-to-install action | A persistent footer banner now shows the retained offered version and reopens the native update offer when clicked. The banner now also has its own UIA element (`sidebar-update-banner-*`, name "Update available", invokable button, bounds equal to the drawn rect, opening the same update offer as a click); App tests cover that bounds/name/invoke routing, but the live gate has not been changed to use it, so the next sentence still describes the gate's pixel-click path. On a viewport too short to leave two rows of sidebar content beside it, the banner (like the inline error footer, which collapses first) is not painted, published, or clickable; only the status line remains. A native provider test shows COM `IInvokeProvider::Invoke` posts exactly the dynamic-invoke command for the banner identity, and an App test shows that command and a banner click open the same offer (version and release URL); these are two linked tests, not one test spanning COM to the dialog, and the real dialog is still only opened by the live gate's click path. The live UIA gate now drives this through the real click path rather than the `GRAPHCODE_UIA_SHOW_UPDATE` bypass: the gate computes the banner's live pixel geometry from the shell's real client height (matching the same viewport-bottom formula the paint code uses) and posts a genuine synthetic `WM_LBUTTONDOWN`/`WM_LBUTTONUP` at that point, then verifies the real `GraphCode Update Available` dialog opens with the offered `GraphCode 9.9.9-test` version text, dismisses it via the live Later command, and confirms the shell survives. **In-app install remains deliberately Blocked** — the offer still hands installation off to the verified release page, and this row's evidence does not claim otherwise | Validated | -| Sidebar error footer | Persistent, scoped project-ingress error | Folder, clone, remote, and daemon-open failures now persist in a dedicated red sidebar footer independently of transient status. Successful project ingress clears it, wrapped layout preserves long messages, and the deterministic UIA gate verifies the dedicated footer identity plus multi-line bounds below the update offer. | Validated | -| Needs-you section | Navigable list with reason/project and Stop action | Up to four entries now expose selection, explicit reason copy, stable UIA identities, click/UIA navigation, and a dedicated Stop action. Focused routing coverage plus the deterministic UIA gate verify Stop targets the populated entry's real project path and loop ID. **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found overlaps the sidebar footer. The next macOS ground-truth capture must confirm whether macOS shows it (`AppSidebarMonitor.swift` has a "NEEDS YOU" monitor; Run A did not show it). **Tracked in [#767](https://github.com/scgopi/GraphCode/issues/767) (implementation gap).** | Partial | -| Activity strip | Optional bottom strip, summary, attention-only filter, horizontally scrolling actionable events | Activity events retain project/node identity and timestamps, render timestamped cards, expose stable UIA rows plus scroll controls, and now keep a real horizontal viewport with an attention-only filter. Focused Sidebar coverage and the deterministic UIA gate verify scroll-state changes, attention-only filtering, and card navigation into the selected loop workspace. | Validated | +| Recent projects | Reachable from Add Folder menu | Recent and currently-open projects are now exposed as distinct sidebar rows, with unopened recents remaining under the LOCAL/REMOTE sections while open workspaces use separate `open-project` identities. The deterministic UIA gate verifies the split presentation and section behavior. The live gate now also walks the Recent Folders submenu reachable from Add Folder end-to-end: it sends a real `WM_INITMENUPOPUP` (the message `App.zig` uses to refresh `recent_folders` from the live model before a popup shows, so the read reflects the fixture's recent projects rather than pre-fixture placeholder state), reads the submenu's live items in fixture order with their stable `recent_folder_command_base`-derived command IDs, and invokes the second entry through the real `WM_COMMAND` route, confirming the shell routes it without crashing | Partial | +| Add Folder menu | Open Folder, Clone, Add Remote, recents | File now groups Open Folder, Clone Repository, Add Remote Repository, and Add Codespace under Add Folder and adds a dedicated Recent Folders submenu with its own command range; that submenu is now located rather than positionally indexed, so a new ingress entry can no longer silently retarget the rebuild. Focused MainWindow coverage validates the native menu structure and recent-folder command wiring. The live UIA gate now reads the Add Folder submenu directly off the live `HMENU` (`GetMenu`/`GetSubMenu`, not `TrackPopupMenu`, since this is the persistent menu bar) and asserts all four action labels plus the Recent Folders submenu; see the Recent projects row above for the live Recent Folders walkthrough this shares | Partial | +| Sidebar update banner | Available version and click-to-install action | A persistent footer banner now shows the retained offered version and reopens the native update offer when clicked. The banner now also has its own UIA element (`sidebar-update-banner-*`, name "Update available", invokable button, bounds equal to the drawn rect, opening the same update offer as a click); App tests cover that bounds/name/invoke routing, but the live gate has not been changed to use it, so the next sentence still describes the gate's pixel-click path. On a viewport too short to leave two rows of sidebar content beside it, the banner (like the inline error footer, which collapses first) is not painted, published, or clickable; only the status line remains. A native provider test shows COM `IInvokeProvider::Invoke` posts exactly the dynamic-invoke command for the banner identity, and an App test shows that command and a banner click open the same offer (version and release URL); these are two linked tests, not one test spanning COM to the dialog, and the real dialog is still only opened by the live gate's click path. The live UIA gate now drives this through the real click path rather than the `GRAPHCODE_UIA_SHOW_UPDATE` bypass: the gate computes the banner's live pixel geometry from the shell's real client height (matching the same viewport-bottom formula the paint code uses) and posts a genuine synthetic `WM_LBUTTONDOWN`/`WM_LBUTTONUP` at that point, then verifies the real `GraphCode Update Available` dialog opens with the offered `GraphCode 9.9.9-test` version text, dismisses it via the live Later command, and confirms the shell survives. **In-app install remains deliberately Blocked** — the offer still hands installation off to the verified release page, and this row's evidence does not claim otherwise | Partial | +| Sidebar error footer | Persistent, scoped project-ingress error | Folder, clone, remote, and daemon-open failures now persist in a dedicated red sidebar footer independently of transient status. Successful project ingress clears it, wrapped layout preserves long messages, and the deterministic UIA gate verifies the dedicated footer identity plus multi-line bounds below the update offer. | Partial | +| Needs-you section | No normal-sidebar attention list is required by the pinned macOS source | Windows exposes up to four entries with reason/project, navigation and Stop; the existing focused/runtime evidence is retained as Windows functionality. **Reopened (visual) 2026-10-13:** the prior review found footer overlap. **Reference intake 2026-10-14:** `AppSidebarView.swift:334` comments out the normal sidebar attention section; `AppSidebarMonitor.swift` is not evidence that it is mounted there. This is the 2026-10-13 extras-are-not-parity classification, confirmed by the returned source/reference, not a claim that removal has landed. Toolbar/canvas attention remains in scope. [#767](https://github.com/scgopi/GraphCode/issues/767) is narrowed to that source-based distinction; implementation of the sidebar-extra removal needs a separate bounded approval and reachable equivalent actions, not an expansion of the current navigation slice. | Out of scope | +| Activity strip | Optional bottom strip, summary, attention-only filter, horizontally scrolling actionable events | Activity events retain project/node identity and timestamps, render timestamped cards, expose stable UIA rows plus scroll controls, and now keep a real horizontal viewport with an attention-only filter. Focused Sidebar coverage and the deterministic UIA gate verify scroll-state changes, attention-only filtering, and card navigation into the selected loop workspace. | Partial | ## Graph overview and project canvas @@ -162,16 +241,16 @@ native keyboard/accelerator/window proof; the workspace row remains Partial. | Pan and anchored zoom | Pan, pointer-centered wheel/pinch zoom | Mouse pan and pointer-centered wheel zoom remain intact and unchanged, with the same focused regression coverage as before (`GraphCanvas.zig`: "canvas zoom keeps the graph point beneath the cursor stable", "canvas wheel zoom scales high-resolution trackpad deltas"). Native touchscreen pinch-zoom and pan are now implemented and routed through the main window: `MainWindow.zig` registers `GID_PAN` (with `GC_PAN_WITH_INERTIA`) and `GID_ZOOM` via `SetGestureConfig`, leaving the remaining gesture classes (`GID_ROTATE`/`GID_TWOFINGERTAP`/`GID_PRESSANDTAP`) at their existing OS defaults rather than explicitly blocking gestures this app has no opinion on, with a real registration test against a genuine `HWND` plus two independent negative controls — a malformed native `SetGestureConfig` call and a genuinely invalid `HWND` passed straight through the production `registerCanvasGestureConfig` helper itself — proving the helper's own `GetLastError()` capture path actually fires, not just the raw Win32 API. `App.zig`'s `WM_GESTURE` case decodes `GID_PAN` and `GID_ZOOM` via a pure `CanvasInput.classifyGesture` decision table (including a distinct outcome for a gesture delivered as a single combined begin+end message, so it can never reuse a stale prior gesture's baseline), requires the active surface to actually render the graph canvas (not just the wheel-region rectangle, which the terminal workspace surface shares), and applies `GraphCanvas.zig`'s `beginPinchZoom`/`continuePinchZoom`/`endPinchZoom` against a per-gesture identity hash of surface+project so a same-region destination change mid-gesture (surface switch, or project switch while still graph-capable) resets the baseline instead of silently continuing to scale the wrong canvas; a failed `GetClientRect` is guarded and treated as unhandled rather than classified against an undefined rect, and the gesture handle is closed before any call that could re-enter the message loop. This is source-mapped, automated routing/unit evidence, not live hardware-input evidence: this session held no live UIA capture slot this pass, so pinch is proven by code mapping and a full deterministic test suite (non-compounding/clamp/zero-distance/lifecycle/context-mismatch/routing matrix, verified with genuine temporary-regression RED/GREEN passes against the production helpers, not GREEN-only), not an actual touchscreen or Precision Touchpad device. Per Microsoft's documented default, Precision Touchpad pinch on a classic Win32 window is emulated as synthetic Ctrl+`WM_MOUSEWHEEL`, not delivered as `WM_GESTURE`, so this implementation targets true touchscreen digitizers specifically; Precision Touchpad pinch behavior is not separately implemented or verified here. Touch-driven pan (`GID_PAN`) is now implemented alongside pinch: the window registers the pan gesture class and `App.zig` routes `GID_PAN` through the same `CanvasInput` decision table into `GraphCanvas.zig` pan offsets, with begin/end/cancel resetting the baseline, a destination change mid-gesture resetting it, and the existing wheel and pinch tests unchanged. Left Partial: touchscreen pinch and pan both have real source and automated-test coverage but no live device evidence, because touch and Precision Touchpad hardware is unavailable to CI. Narrowed 2026-10-13 to macOS scope (requirements macOS lacks were dropped; see the issue). **Tracked in [#726](https://github.com/scgopi/GraphCode/issues/726) (implementation gap).** | Partial | | Zoom controls | Zoom out, actual size, zoom in, fit with shortcuts/help | Visible bottom-right controls provide zoom out, percentage/actual size, zoom in, and fit. A visible shortcut/help line accompanies the controls; Ctrl+-, Ctrl+0, Ctrl+=, and Ctrl+9 remain represented in the View menu. The Windows shell toolchain blocker is resolved and `Tools\windows\uia-live-gate.ps1` now runs against the live executable: it locates the `zoom-out`, `actual-size`, `zoom-in`, and `fit-canvas` UIA fragments, requires non-empty bounds, resolves each `InvokePattern`, and then actually invokes zoom-in, actual-size, zoom-out, and fit-canvas in sequence against the running shell, all of which completed without error across many consecutive live runs **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found segmented rectangles and hint text instead of the macOS icon capsule. **Tracked in [#781](https://github.com/scgopi/GraphCode/issues/781) (implementation gap).** | Partial | | New Loop canvas button | Visible top-right add action | A live-validated top-right New Loop button is now present on non-empty project canvases and remains centered in the empty state **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found native "New Loop" button instead of the "+ New Node" control; overlaps the rail and sidebar. **Tracked in [#764](https://github.com/scgopi/GraphCode/issues/764) (implementation gap).** | Partial | -| Composite breadcrumb | Current group, project back action, loop count | Open Group swaps the project canvas to the authoritative nested graph, renders its cards and edges through the normal interactive canvas, and exposes a clickable `Project > Group` breadcrumb with loop count that restores and reselects the parent. Nested graph selection survives daemon refreshes, and the populated live UIA gate invokes Open Group, verifies both nested cards, and invokes the bounded Back breadcrumb to restore the parent canvas | Validated | +| Composite breadcrumb | Current group, project back action, loop count | Open Group swaps the project canvas to the authoritative nested graph, renders its cards and edges through the normal interactive canvas, and exposes a clickable `Project > Group` breadcrumb with loop count that restores and reselects the parent. Nested graph selection survives daemon refreshes, and the populated live UIA gate invokes Open Group, verifies both nested cards, and invokes the bounded Back breadcrumb to restore the parent canvas | Partial | | Canvas attention rail | Count/oldest context and Review action | The rail exposes a clickable Review target and uses `createdAt` from the daemon model when present to show a true `oldest ` label alongside the oldest attention item title. Focused hit testing passes, and the Windows shell toolchain blocker is now resolved: the rail has no dedicated UIA element of its own (it is a full-width band GDI hit-test region), so `Tools\windows\uia-live-gate.ps1` posts a real `WM_LBUTTONDOWN`/`WM_LBUTTONUP` at the rail's exact screen rect against the live executable and verifies the click drives `App.zig`'s `.review_attention` -> `selectNextAttention()` routing by observing the resulting `SelectionItemPattern` selection actually move from one card to the NEEDS YOU card, passing across many consecutive live runs **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found a stray band covers cards; Review is not a button; the rail is drawn on Quick Chats. **Tracked in [#766](https://github.com/scgopi/GraphCode/issues/766) (implementation gap).** | Partial | -| Node positioning | Persisted positions and direct card movement where supported | Project cards can be dragged directly, with movement transformed correctly at non-default zoom, shared geometry/hit testing updated during the drag, and capture-loss cancellation restoring the prior position. Offsets are keyed to stable node identity, remapped across daemon reorder, and atomically persisted under the configured GraphCode support directory. Focused reorder/reload regressions and a real physical drag capture validate the complete flow | Validated | -| Connector handles | Hover handles and drag-to-connect | The right-edge connector tracks hover, paints a visible handle and plus affordance, and preserves the drag-to-connect path. Focused rendering/input coverage passes, and the Windows shell toolchain blocker is now resolved: `Tools\windows\uia-live-gate.ps1` synthesizes real `WM_MOUSEMOVE` hover messages at the source card's outgoing connector position and confirms the live `0x7ACDFF` hover handle pixel actually appears on screen (`Test-ScreenPixelNear`), then drives a full `WM_LBUTTONDOWN`/`WM_MOUSEMOVE`/`WM_LBUTTONUP` drag from that connector onto a second card and confirms the resulting native "Create or edit edge" dialog locks its From/To fields to the exact dragged source and dropped target loop IDs, all passing across many consecutive live runs | Validated | +| Node positioning | Persisted positions and direct card movement where supported | Project cards can be dragged directly, with movement transformed correctly at non-default zoom, shared geometry/hit testing updated during the drag, and capture-loss cancellation restoring the prior position. Offsets are keyed to stable node identity, remapped across daemon reorder, and atomically persisted under the configured GraphCode support directory. Focused reorder/reload regressions and a real physical drag capture validate the complete flow | Partial | +| Connector handles | Hover handles and drag-to-connect | The right-edge connector tracks hover, paints a visible handle and plus affordance, and preserves the drag-to-connect path. Focused rendering/input coverage passes, and the Windows shell toolchain blocker is now resolved: `Tools\windows\uia-live-gate.ps1` synthesizes real `WM_MOUSEMOVE` hover messages at the source card's outgoing connector position and confirms the live `0x7ACDFF` hover handle pixel actually appears on screen (`Test-ScreenPixelNear`), then drives a full `WM_LBUTTONDOWN`/`WM_MOUSEMOVE`/`WM_LBUTTONUP` drag from that connector onto a second card and confirms the resulting native "Create or edit edge" dialog locks its From/To fields to the exact dragged source and dropped target loop IDs, all passing across many consecutive live runs | Partial | | Loop card identity | Loop-type stripe, title, state pill, entry/cycle role | Project and overview cards now use loop-type-colored stripes while retaining lifecycle state text, START, UNWIRED, and attention labels. Focused color regression coverage passes; live evidence remains blocked. Narrowed 2026-10-13 to macOS scope (requirements macOS lacks were dropped; see the issue). **Tracked in [#727](https://github.com/scgopi/GraphCode/issues/727) (implementation gap).** | Partial | | Loop card live detail | Goal/prompt/check line, progress, metric change, elapsed/backend/model/worktree metadata | Cards prioritize goal, trigger, or check detail, retain current activity, and add metric pass/change text, elapsed age, backend identity, token usage, model tier, and worktree/branch metadata from the same decoded daemon fields used by the workspace loop bar. Focused card metadata tests (`GraphCanvas.zig`: "loop card metadata includes backend elapsed and token usage when reported") pass, and the `windows-shell` CI job's live UIA gate exercises the populated card fixture end to end (run https://github.com/scgopi/GraphCode/actions/runs/35638849754, passing, merged as PR #399) **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found raw state and backend ids on a sparse 250x106 card instead of the compact macOS card with a state pill and meta line. **Tracked in [#764](https://github.com/scgopi/GraphCode/issues/764) (implementation gap).** | Partial | | Loop card attention | Reason-aware amber presentation and primary action | NEEDS YOU cards render a card-level reason-specific primary button: `Reply` for reported awaiting-input sessions and `Inspect` for other attention reasons, both routed through the normal loop-opening path. Focused action-label tests (`GraphCanvas.zig`: "attention cards expose reason-specific primary actions") pass, and the live UIA gate's `attention-action-*` assertion for the deterministic awaiting-input card passed on `windows-shell` (run https://github.com/scgopi/GraphCode/actions/runs/35638849754, merged as PR #399) **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found no NEEDS YOU pill, glow or Inspect on cards that need attention. **Tracked in [#764](https://github.com/scgopi/GraphCode/issues/764) (implementation gap).** | Partial | | Unwired card recovery | Explanation, Wire it up, Mark as entry | Cards with no inbound or outbound edge now show an explicit UNWIRED warning and recovery explanation. Their native context menu exposes Wire it up, which enters the existing drag-to-connect flow, and Mark as entry, which changes the card to START for the session. Focused role/action tests plus live menu and post-action captures validate the flow **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found a text hint instead of the on-card Wire it up / Mark as entry controls. **Tracked in [#764](https://github.com/scgopi/GraphCode/issues/764) (implementation gap).** | Partial | -| Worktree reclaim offer | Reclaim and Keep actions on resolved card | Safe resolved cards with a matching landed, clean, pushed worktree expose separate Reclaim and Keep targets. Reclaim revalidates safety and Keep suppresses the offer for the session. Canvas Reclaim/Keep descendants are now emitted through the UIA provider and invoke the same fail-closed paths. Focused geometry/safety coverage passes, and `Tools\windows\uia-live-gate.ps1` now asserts the live Reclaim/Keep descendants under the Graph fragment (name, non-empty bounds, InvokePattern, and correct RawView/ControlView sibling linkage) via the `windows-shell` CI job (PR #385, run 35422364203, passing) | Validated | -| Composite card actions | Open Group, Pilot Once, Arm Schedule | Canvas and sidebar composite menus expose all three actions. Open Group is live-validated; nested creates, edits, deletes, edge changes, pilot, and arm commands use the daemon's authoritative `subGraphCommand` envelope; and Arm Schedule is disabled unless the decoded pilot state is exactly `piloted` | Validated | +| Worktree reclaim offer | Reclaim and Keep actions on resolved card | Safe resolved cards with a matching landed, clean, pushed worktree expose separate Reclaim and Keep targets. Reclaim revalidates safety and Keep suppresses the offer for the session. Canvas Reclaim/Keep descendants are now emitted through the UIA provider and invoke the same fail-closed paths. Focused geometry/safety coverage passes, and `Tools\windows\uia-live-gate.ps1` now asserts the live Reclaim/Keep descendants under the Graph fragment (name, non-empty bounds, InvokePattern, and correct RawView/ControlView sibling linkage) via the `windows-shell` CI job (PR #385, run 35422364203, passing) | Partial | +| Composite card actions | Open Group, Pilot Once, Arm Schedule | Canvas and sidebar composite menus expose all three actions. Open Group is live-validated; nested creates, edits, deletes, edge changes, pilot, and arm commands use the daemon's authoritative `subGraphCommand` envelope; and Arm Schedule is disabled unless the decoded pilot state is exactly `piloted` | Partial | | Edge presentation | Kind style, fired state, cycle label | Windows retains typed optional cycle guards and derives fired state from authoritative `fireCount`, with missing/null legacy fallback. Raw snapshot JSON reaches the production label formatter for maximum/until/flat-pass and empty-guard summaries; signed/null/malformed inputs, Unicode/long text, owned copies, refresh/composite transitions, and allocation-failure cleanup have executable coverage. Kind styling, selected emphasis, fixed 148-by-20 label bounds, ellipsis, and collision placement are retained. This is exact-string and static-geometry evidence only: full visible wording, the macOS context-menu summary, rendered pixels, and live label evidence remain unverified. Narrowed 2026-10-13 to macOS scope (requirements macOS lacks were dropped; see the issue). **Tracked in [#728](https://github.com/scgopi/GraphCode/issues/728) (implementation gap).** | Partial | | Edge creation sheet | Kind/condition/transform/cycle controls with conditional validation | The guided native form provides endpoint selectors, conditional fields, validation, keyboard traversal, scrolling, and recap. Menu and connector creation now share the full draft sender, retaining condition, payload transform, all optional cycle guards, and spawn target. Project/composite identity and endpoint IDs/titles are owned across the modal; stale model/selection/client subgraph addressing and missing or changed endpoint choices are explicitly rejected without retargeting. The update subscription can still observe another cached project or refresh independently: outgoing creation explicitly addresses the captured project. Registered pure production-path tests inspect the real client's outgoing queue, including cached-project selection, Unicode/quotes, callback-induced graph changes, cancellation, and allocation failures. The reduced connector sender fails the same accepted-draft fixture that the full sender passes. Earlier live evidence only opened the form and checked endpoints/recap before cancellation; at that point, daemon acceptance and persistence were also unproven. The added headless harness starts the real `graphcoded.exe` with isolated support state; production `sendCreateEdgeDraft` receives a correlated V2 `graphChanged` response, and daemon save/reload preserves edge identity, endpoints, condition, transform, spawn target, and cycle guard. The hosted `windows-shell integration` job 109978958907 (run 36742113814, merged as #540) then drove the real native sheet end to end against the connected protocol stub: Create Edge from the live canvas popup, the source picker carrying the seeded daemon node ID, native keyboard selection of kind/condition/transform, real `SendInput` text entry into payload and both cycle-guard fields with injected-event counts matching exactly (clear 2/2; text 32/32, 24/24, 2/2) and stable `WM_GETTEXT` readback, a rejected empty-template submission that showed the exact reason `Enter the template or script that should carry context.` while leaving the daemon command-log bytes and graph-command count unchanged, and an accepted submission whose `createEdge` wire matched every native choice and was answered by a correlated reply. The preceding intentional-failure run 36739940627 (job 109971468469) recorded the same full evidence before its deliberate late assertion. This is stub-daemon evidence, not `graphcoded` persistence; the accessibility provider still exposes no edge fragment, so rendering is corroborated only by republished graph state and the live Edit Edge hit test; native macOS parity evidence remains absent. Narrowed 2026-10-13 to macOS scope (requirements macOS lacks were dropped; see the issue). **Tracked in [#729](https://github.com/scgopi/GraphCode/issues/729) (testing gap).** | Partial | | Custody child creation | New Child Node on unresolved parents, inherited editable backend, daemon-owned custody | Project-canvas/sidebar node menus consume the tested unresolved-only item plan (5119). Owned popup target/settings/child-only exact-project worktree snapshots feed the existing guarded node form and template/attachment continuation. Original popup context is checked before normal initial selection; final guards never reselect, reject project/composite/address drift or deleted/resolved/type/backend-changed parents, and allow rename/reorder/unresolved progress. Tests exercise the production initializer/transfer boundary and real data-only client queue, including cached B while observing A, root-versus-composite same IDs, UUID/null wire fields, cancellation and allocation failures. `createdBy` produces one create command: GraphStore owns the fired handoff/report-back memo and normal startup. No new protocol or parent/session mutation. Native display/action results, overview right-click, daemon acceptance/persistence, and inherited downstream-send failure handling remain unverified. The merged ordinary-creation path now retains the owned worktree snapshots whose evidence is recorded in Node creation sheet, while custody retains its pre-popup owned snapshot; template backend settings remain a separate residual. Narrowed 2026-10-13 to macOS scope (requirements macOS lacks were dropped; see the issue). **Tracked in [#730](https://github.com/scgopi/GraphCode/issues/730) (implementation gap).** | Partial | @@ -185,11 +264,11 @@ native keyboard/accelerator/window proof; the workspace row remains Partial. | macOS surface | Required visible behavior | Windows evidence | Status | |---|---|---|---| -| Quick Chats canvas | Band, cards, pan/zoom, add button, empty state | The real executable was exercised with two deterministic chats. The band, transformed cards, top-right New Chat action, bottom-right zoom controls, and 100% → 110% zoom transition were captured live. Context actions are wired, and the populated live UIA gate validates named, bounded, invokable Quick Chat cards plus the populated-canvas New Chat action | Validated | -| Quick Chat cards | Title, chat identity, optional backend badge, open/rename/delete menu | A populated live fixture verified title/default-chat identity/optional backend rendering and direct opening (`openQuickChat` was observed by the protocol stub). Cards now expose Open Chat, Rename, and Delete Chat context actions | Validated | +| Quick Chats canvas | Band, cards, pan/zoom, add button, empty state | The real executable was exercised with two deterministic chats. The band, transformed cards, top-right New Chat action, bottom-right zoom controls, and 100% → 110% zoom transition were captured live. Context actions are wired, and the populated live UIA gate validates named, bounded, invokable Quick Chat cards plus the populated-canvas New Chat action | Partial | +| Quick Chat cards | Title, chat identity, optional backend badge, open/rename/delete menu | A populated live fixture verified title/default-chat identity/optional backend rendering and direct opening (`openQuickChat` was observed by the protocol stub). Cards now expose Open Chat, Rename, and Delete Chat context actions | Partial | | Create chat | Visible New Chat controls | Empty and populated Quick Chats canvases expose the New Chat action in the macOS placements. The live UIA gate invokes the populated canvas action and the sidebar/header action; the existing empty-state walkthrough invokes the centered empty-state action **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found no top-right "+ New Chat" on the empty canvas. **Tracked in [#774](https://github.com/scgopi/GraphCode/issues/774) (implementation gap).** | Partial | -| Rename chat | Single title prompt from row/card | Uses a dedicated single-title modal from the card/keyboard action, trims input, and rejects empty titles | Validated | -| Delete chat | Named confirmation explaining session/scrollback deletion | Uses a named warning that explains terminal-session and scrollback removal, defaults to cancellation, and only sends deletion after confirmation | Validated | +| Rename chat | Single title prompt from row/card | Uses a dedicated single-title modal from the card/keyboard action, trims input, and rejects empty titles | Partial | +| Delete chat | Named confirmation explaining session/scrollback deletion | Uses a named warning that explains terminal-session and scrollback removal, defaults to cancellation, and only sends deletion after confirmation | Partial | | Chat workspace | Opens a persistent terminal workspace | Opening a Quick Chat now exposes a bounded, selected `Quick Chat terminal workspace` UIA surface while the existing terminal panel remains persistent. The full native UIA walkthrough verifies the card invocation and workspace transition without duplicating loop-workspace implementation **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found shows the previous loop's loop bar and loop panel instead of the chat. **Tracked in [#774](https://github.com/scgopi/GraphCode/issues/774) (implementation gap).** | Partial | ## Loop terminal workspace @@ -213,10 +292,10 @@ native keyboard/accelerator/window proof; the workspace row remains Partial. | macOS surface | Required visible behavior | Windows evidence | Status | |---|---|---|---| -| Open Folder | Native picker from Welcome and Add Folder menu | Welcome and File menu commands use the Windows folder-only File Open dialog with filesystem/path validation. The live UIA gate invokes the empty-state action, verifies the titled native picker, and cancels it safely | Validated | -| Clone Repository sheet | Repository, location picker, derived folder, branch, depth, progress, inline failure, cancel | Clone runs behind a progress-capable native operation sheet with live output, cancellation, terminal status, and shared dark painting. Windows-shell contracts pass. The UIA gate opens the real sheet, verifies URL/destination/branch/depth fields, submits it empty to verify the inline URL error, and cancels it | Validated | -| Add Remote Repository sheet | Server/user/port/path, explanation, validation progress, inline selectable error | SSH validation runs on a worker while a validation sheet remains open and Connect is unavailable until completion. It shares Clone’s dark themed native dialog class. Windows-shell contracts pass. The UIA gate opens the real “Add SSH Repository” sheet, verifies host/user/port/path fields, submits it empty to verify inline validation, and cancels it | Validated | -| Remote Connection info | Read-only selectable connection sheet | Remote project context menus expose a dedicated read-only connection-information dialog with the encoded remote project identity and management guidance. The live UIA gate opens the native sheet, verifies both pieces of content, and closes it | Validated | +| Open Folder | Native picker from Welcome and Add Folder menu | Welcome and File menu commands use the Windows folder-only File Open dialog with filesystem/path validation. The live UIA gate invokes the empty-state action, verifies the titled native picker, and cancels it safely | Partial | +| Clone Repository sheet | Repository, location picker, derived folder, branch, depth, progress, inline failure, cancel | Clone runs behind a progress-capable native operation sheet with live output, cancellation, terminal status, and shared dark painting. Windows-shell contracts pass. The UIA gate opens the real sheet, verifies URL/destination/branch/depth fields, submits it empty to verify the inline URL error, and cancels it | Partial | +| Add Remote Repository sheet | Server/user/port/path, explanation, validation progress, inline selectable error | SSH validation runs on a worker while a validation sheet remains open and Connect is unavailable until completion. It shares Clone’s dark themed native dialog class. Windows-shell contracts pass. The UIA gate opens the real “Add SSH Repository” sheet, verifies host/user/port/path fields, submits it empty to verify inline validation, and cancels it | Partial | +| Remote Connection info | Read-only selectable connection sheet | Remote project context menus expose a dedicated read-only connection-information dialog with the encoded remote project identity and management guidance. The live UIA gate opens the native sheet, verifies both pieces of content, and closes it | Partial | | Add Codespace sheet | Authenticated codespace discovery, selection, workspace path, validation progress, empty/error/retry/cancel, opens the remote project | `Codespaces.zig` + `WindowsCodespaceDialog.zig` provide discovery, failure remediation, validation, submit gating, and `codespace://` project opening. Deterministic Codespaces/dialog/windows-shell coverage remains green. **Still partial:** the available token lacks `codespace` scope; no real discovery-success, selection, validated dial, or rendered-sheet UIA walkthrough was possible. Only the 403/remediation path was exercised against real `gh`. **Tracked in [#739](https://github.com/scgopi/GraphCode/issues/739) (testing gap).** | Partial | ## Settings and worktrees @@ -225,7 +304,7 @@ native keyboard/accelerator/window proof; the workspace row remains Partial. |---|---|---|---| | Product Settings window | Backend, three permission pickers, model picker/auto toggle, activity, briefing, beta with explanatory copy | `WindowsProductSettings.zig` exposes native backend/model/Claude/Copilot/Codex selectors, routing/activity/briefing/beta controls, macOS-equivalent consequence copy, and Save/Cancel. Focused tests cover settings preservation and selector copy; `GRAPHCODE_UIA_GATE` mutation 15 opens the real window against an isolated settings file, verifies every required visible control/explanation, proves control-targeted Return saves while preserving unknown fields, and proves Escape cancels byte-for-byte **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found no section navigation or Templates; OpenCode/Pi agents missing; an em dash renders as "I". **Tracked in [#771](https://github.com/scgopi/GraphCode/issues/771) (implementation gap).** | Partial | | Infrastructure diagnostics | If retained, separate advanced surface | Daemon pipe/support-directory overrides are now explicitly labeled “Advanced Connection Settings...” while the normal Settings command opens product settings | Validated | -| Project Settings sheet | Resolve policy radio rows, safety explanation, size/count thresholds, immediate save | Valid threshold/radio edits persist immediately, while empty/partial threshold input preserves the last valid persisted value; Done remains dismiss-only. The shared dark native form is covered by focused and Windows-shell tests. The UIA gate uses the gate-only hook to open it and verifies policy, threshold-unit, and worktree content before cancelling | Validated | +| Project Settings sheet | Resolve policy radio rows, safety explanation, size/count thresholds, immediate save | Valid threshold/radio edits persist immediately, while empty/partial threshold input preserves the last valid persisted value; Done remains dismiss-only. The shared dark native form is covered by focused and Windows-shell tests. The UIA gate uses the gate-only hook to open it and verifies policy, threshold-unit, and worktree content before cancelling | Partial | | Worktree sweep sheet | Safe/look/in-use grouping, size summaries, default selections, reveal, inline destructive confirmation, recovery note | Sweep storage supports 256 rows, real directory sizes and aggregate totals, reveal, and a second destructive confirmation for dirty rows. Windows performs identity/status inspection, policy loading, safety revalidation, and removal away from the Win32 message thread, publishes discovered rows before recursive allocation sizing, then applies each size on the UI thread while preserving generation/owner checks. The shared visible/UIA state distinguishes reading, size-pending, complete, empty, partial-size failure, and inspection failure; a failed size retains every discovered row and names a retry/reveal path. Owned slow-provider App regressions prove the inspect and reclaim actions return before provider completion, rows/UIA appear while a synthetic size provider remains blocked, pending text becomes a final size, and partial errors retain rows. The disposable owned Git process fixture now covers locked-row selection and unlock, pre-mutation cancellation, repository/worktree identity checks, worktree plus branch deletion, exact recovery-log tip/path content before expected-tip branch deletion, branch-tip race refusal, per-row receipts, partial-result classification, and preservation of unrelated worktrees/refs. Native forms and UIA expose locked owned rows as actionable and name the unlock-before-remove path. The UIA gate opens the real sheet through the gate-only hook and verifies safe/look group rendering and Remove Selected, but does not execute destructive reclaim in an installed shell. The row remains `Partial` pending a live packaged Dev Box walkthrough of locked-row unlock, confirmation, pixels/keyboard/UIA state, recovery-log inspection, and post-action selection/model refresh. The beta25 Dev Box qualification (`0.1.78-windows.beta25`, installed package, production `graphcoded`, 2560x1440 at 100%, injected `SendInput` and UIA; return bundle reviewed 2026-10-13) ran section 6C in the installed shell against a disposable five-worktree fixture: the native sweep showed 2 safe / 2 look / 1 in-use groups with sizes and the default-selected safe rows, Show in Explorer and the recovery-log note (`wt-3-sweep.png`); Cancel left the fixture unchanged; reclaim of the landed row and of the locked row (unlock path shown) each removed exactly that worktree and branch, logged the exact tip, and refreshed the list with no other change; a dirty row required the inline second confirmation and was not removed when cancelled; the logged tip recovered the branch. Input was injected, not physical. **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found "Remove Selected" is clipped; no grouped SAFE TO REMOVE / LOOK FIRST / IN USE layout. **Tracked in [#777](https://github.com/scgopi/GraphCode/issues/777) (implementation gap).** | Partial | | Worktree notice chip | Threshold-driven titlebar and lane notice | Explicit inspection installs compact value observations on each exact `GraphSummary` owner; replacing the full inspection, selecting another project, or reordering lanes does not transfer its counts. Overview chips share one presentation/geometry source for paint, hit testing, and path-keyed UIA data, reuse the existing Worktrees action, and show uninspected, incomplete-size, policy-unavailable, stale, and failed-refresh states without fabricated zero/freshness. Local Git projects now trigger background discovery when their graph first appears; SSH and Codespace projects use non-mutating remote command providers, with fixture-only model/provider tests for remote discovery. Project canvases expose their populated count/reclaimable chip through shared paint, hit testing, and UIA geometry. The titlebar aggregates every noticed owner, selects the largest byte accumulator, reports the number of additional noticed folders, and routes review to that exact owner rather than the currently selected project. Checked policy outcomes distinguish missing/legacy defaults from unreadable or malformed configuration. Failed policy writes also reconcile the captured owner's checked readback while preserving the original write error. The shared inclusive count-or-binary-GiB evaluator uses exact known bytes; partial measurements are approximate, and unknown policy or stale observations cannot claim a configured breach. Relevant binding/state/connection/mutation signals stale observations; nested comparisons reuse the existing decoder and scoped IDs under depth, work, and scratch-memory bounds, and comparison uncertainty remains explicitly stale. Title/position-only edits and supported reordering do not manufacture a refresh. Existing owner close/restore eviction removes observations. An exact-current-owner raw-inspection accessor keeps correct-owner rows visible below threshold or when stale/policy-unknown, while excluding foreign current-root rows without changing retained modal state. Pure production-helper/mapper tests cover boundaries, atomic replacement, ownership, nested changes/limits, injected partial-write reconciliation, error states, old action rectangles, path resolution, titlebar aggregation, remote/Codespace fixtures, and literal 96/144/192-DPI UIA-data bounds. macOS `AppFeature+Worktrees.reloadStats` counts `assessments.count` after the opened checkout is removed; prunable rows remain in that count but are excluded from the byte loop. `GitClient.liveValue.worktreeSizeBytes` parses `du -sk` output as 1-KiB disk-usage units, an allocated-usage measure rather than logical file lengths. Windows reads local `FILE_STANDARD_INFORMATION.AllocationSize`, rounds complete local totals to KiB, and uses remote `du -sk`; local accounting remains a deliberate allocated-size approximation, not proven identical to macOS filesystem accounting. This remains unit/native-linked evidence, not a live installed local/SSH/Codespace multi-lane walkthrough, so the row stays `Partial`. **Tracked in [#740](https://github.com/scgopi/GraphCode/issues/740) (testing gap).** | Partial | @@ -252,15 +331,15 @@ for testing; the others need implementation work. Use | macOS surface | Required visible behavior | Windows evidence | Status | |---|---|---|---| -| Available update alert | Install, Release Notes, Later | The native offer now conditions Install on whether the real feed check resolved a Windows asset URL (`WindowsUpdates.zig`/`App.showAvailableUpdate`): when one exists Install is enabled and triggers the real download/verify/extract/upgrade pipeline; when none exists (the real, currently-live state — see Install progress) Install stays visibly disabled with an honest reason, replacing the old permanent "not implemented" label. `UpdateOfferDialog.zig`'s `buttonsFor(installable)` is unit-tested for both states, and a real, live `feed-check` run against the actual `scgopi/GraphCode` releases API (`Tools/windows/Tests/WindowsUpdateInstall.Live.Tests.ps1`) confirms the disabled path is genuine, not simulated, for the current release. What is **not** live-witnessed: clicking Install through a real enabled offer end-to-end in the running UI, because no Windows release asset currently exists to enable it against — that gap is honestly disclosed rather than faked. **Validated 2026-10-13** by the testing-gaps Dev Box run (installed `0.1.78-windows.beta26`, 2560x1440 at 100%, injected input; return bundle reviewed in the release plan): with beta updates on, the live feed offer named `0.1.78-windows.beta27` with Install, Release Notes and Later enabled; Release Notes opened the beta27 release page and Later closed the offer with the installation unchanged. Closed [#741](https://github.com/scgopi/GraphCode/issues/741). | Validated | +| Available update alert | Install, Release Notes, Later | The native offer now conditions Install on whether the real feed check resolved a Windows asset URL (`WindowsUpdates.zig`/`App.showAvailableUpdate`): when one exists Install is enabled and triggers the real download/verify/extract/upgrade pipeline; when none exists (the real, currently-live state — see Install progress) Install stays visibly disabled with an honest reason, replacing the old permanent "not implemented" label. `UpdateOfferDialog.zig`'s `buttonsFor(installable)` is unit-tested for both states, and a real, live `feed-check` run against the actual `scgopi/GraphCode` releases API (`Tools/windows/Tests/WindowsUpdateInstall.Live.Tests.ps1`) confirms the disabled path is genuine, not simulated, for the current release. What is **not** live-witnessed: clicking Install through a real enabled offer end-to-end in the running UI, because no Windows release asset currently exists to enable it against — that gap is honestly disclosed rather than faked. **Validated 2026-10-13** by the testing-gaps Dev Box run (installed `0.1.78-windows.beta26`, 2560x1440 at 100%, injected input; return bundle reviewed in the release plan): with beta updates on, the live feed offer named `0.1.78-windows.beta27` with Install, Release Notes and Later enabled; Release Notes opened the beta27 release page and Later closed the offer with the installation unchanged. Closed [#741](https://github.com/scgopi/GraphCode/issues/741). | Partial | | Install progress | In-window progress indicator | `WindowsUpdateInstall.zig` now implements the full download → SHA-256 checksum verify → extract → `GraphCode-Setup.ps1 -Command Upgrade` pipeline, reusing the existing packaging verification/rollback logic rather than a second copy, and reports phase/fraction progress through a `ProgressFn` callback. `UpdateInstallDialog.zig` renders that progress in a native window (download %, verifying, extracting, installing) plus a failure state; both are unit-tested (14 tests total across the two files, part of the 42-file/273-test hermetic `WindowsShell.Tests.ps1` suite). Real, non-simulated live evidence (`WindowsUpdateInstall.Live.Tests.ps1`, invoked directly — not part of the hermetic suite since it makes real network calls): a real HTTPS download of a real multi-megabyte GitHub release asset streams genuine progress (100+ real progress reports, 0→100%) and its SHA-256 is verified against the asset's real published digest before extraction is attempted; a deliberately wrong digest is rejected with `ChecksumMismatch` strictly before extraction, proving the checksum gate is not vacuous. Honestly out of scope and **not** provable right now: extracting and upgrading a real Windows ZIP asset end-to-end, because the last recorded and just-reconfirmed-live asset check found only macOS DMGs published — there is no real Windows asset to extract. Also unproven: whether `Move-InstallDirectory`'s rename succeeds while `graphcode-windows.exe` is the actual running, self-updating process (the existing `Packaging.RealLifecycle.Tests.ps1` proves the *opposite* guarantee — that a locked file blocks and rolls back — not this scenario). In the 2026-10-13 testing-gaps Dev Box run, the live in-app install from beta26 to beta27 failed every time, after Downloading, Extracting and Installing, with `UpgradeFailed`. Root cause: the shell had been started from PowerShell 7 and passed that `PSModulePath` to `powershell.exe`, which then could not load `Get-FileHash`. The fix lands separately; live upgrade evidence is still missing. **Tracked in [#742](https://github.com/scgopi/GraphCode/issues/742) (testing gap).** | Partial | | Relaunch prompt | Relaunch Now/Later and session continuity explanation | `UpdateInstallDialog.zig` presents Relaunch Now / Later with session-continuity copy after a successful install, and `App.runInstall`/`relaunchAfterUpdate` wire the outcome: Relaunch Now respawns the executable (same `CreateProcessW` pattern as `launchWorkspace`) and then quits the current process; Later leaves the update staged and shows an honest status message. Pure logic (`relaunch_message`, outcome handling) is unit-tested; the real Win32 window/thread code compiles and runs but is not live-driven by UI automation in this PR. This row cannot move past `Partial` genuinely: there is no real Windows release asset to drive a real install to completion today, so the actual relaunch — and whether zmx-backed terminal sessions survive an Upgrade-triggered restart specifically, as opposed to the differently-scoped scenario `DaemonHandoff.Live.Tests.ps1` already covers — remains unproven live. Faking that would violate this fleet's evidence policy, so the row is left honestly `Partial` rather than asserted `Validated`. **Tracked in [#743](https://github.com/scgopi/GraphCode/issues/743) (testing gap).** | Partial | | Install failure | Download in Browser/Cancel with reason | `UpdateInstallDialog.zig` maps every `WindowsUpdateInstall.InstallError` (checksum unavailable/mismatch, download, extraction and its timeout, missing setup script, upgrade and its timeout, out of memory) to a distinct reason, switches the native progress window to that reason with a Close button, and `App.runInstall` surfaces it as status; cancelling during progress reports "Update install cancelled". The failure reason is carried by value (`FailureMessage`), so worker, out-of-memory, and window-closed failures all surface a reason without the caller freeing borrowed or static memory, and a worker thread that cannot start re-enables and reactivates the owner instead of leaving it disabled. Evidence is `UpdateInstallDialog.zig` unit tests of the outcome and startup-failure logic plus a compiling shell build, not a live walkthrough. Remains Partial: every terminal failure now renders a "Download in Browser" action beside Close, opening the release URL through an injected shell API that the tests substitute, so the mapping and invocation are covered by unit tests. The real `ShellExecuteW` handoff is never invoked by a test, and no published release has a Windows asset (v0.1.76 and 0.1.77-beta1 ship the macOS DMG only), so no real download/install failure and no real browser launch has been driven end to end. **Tracked in [#744](https://github.com/scgopi/GraphCode/issues/744) (testing gap).** | Partial | | Loop rename | Title field, Return submits, explanatory text | The dedicated single-title modal explains where the title appears, prepopulates the current value, trims and validates submission, and re-resolves the stable loop ID after the modal. The populated UIA gate edits the native field and verifies Return submits and closes the dialog. Dev Box qualification of `0.1.78-windows.beta17` found the dialog opened with keyboard focus on its frame rather than the Title edit (9904), so typing did nothing until the field was clicked; the shared `GraphCodeWindowsDialog` now selects the first field's text on creation and routes `WM_ACTIVATE`/`WM_SETFOCUS` to the remembered control. A `WindowsNativeDialogs.zig` test drives the real window class through `ShowWindow` activation, `WM_SETFOCUS`, and deactivate/reactivate, and failed before the fix; that is in-process native-message evidence, and a Dev Box rerun of physical typing into the opened dialog is still pending **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found buttons clipped; light window; copy differs from the macOS prompt. **Tracked in [#768](https://github.com/scgopi/GraphCode/issues/768) (implementation gap).** | Partial | | Loop delete | Named loop and full consequence message | Names the loop, explains graph-connection removal, and defaults to cancellation. The beta25 Dev Box qualification (`0.1.78-windows.beta25`, installed package, production `graphcoded`, 2560x1440 at 100%, injected `SendInput` and UIA; return bundle reviewed 2026-10-13) D6 confirmed it live: Delete Loop named the loop, Cancel left it, and confirming removed the loop and its UIA row. **Reopened (visual) 2026-10-13:** the side-by-side review against the macOS reference found system-style dialog with different copy, not the macOS sheet. **Tracked in [#768](https://github.com/scgopi/GraphCode/issues/768) (implementation gap).** | Partial | -| Chat rename/delete | Dedicated prompts | Dedicated single-title rename modal and named fail-closed deletion warning are wired from card actions and shortcuts | Validated | -| Project delete loops | Dedicated confirmation | Sidebar project menus expose Delete All Loops through one fail-closed implementation with graph and filesystem consequence copy, safe cancellation default, and the dedicated daemon command. The live UIA gate verifies the native confirmation and cancellation path | Validated | -| Project remove/trash | Distinct reversible remove and filesystem Trash choices | Remove from GraphCode is distinct, confirmed, and explicitly preserves files. Local project menus now add a separate confirmed Move Folder to Recycle Bin action using the Windows undo-capable shell operation; remote projects retain only the GraphCode removal action | Validated | +| Chat rename/delete | Dedicated prompts | Dedicated single-title rename modal and named fail-closed deletion warning are wired from card actions and shortcuts | Partial | +| Project delete loops | Dedicated confirmation | Sidebar project menus expose Delete All Loops through one fail-closed implementation with graph and filesystem consequence copy, safe cancellation default, and the dedicated daemon command. The live UIA gate verifies the native confirmation and cancellation path | Partial | +| Project remove/trash | Distinct reversible remove and filesystem Trash choices | Remove from GraphCode is distinct, confirmed, and explicitly preserves files. Local project menus now add a separate confirmed Move Folder to Recycle Bin action using the Windows undo-capable shell operation; remote projects retain only the GraphCode removal action | Partial | ## Accessibility, input, and visual behavior @@ -326,7 +405,10 @@ changes, and no row status depends on them. These surfaces were removed from the macOS/Windows parity requirement by a product decision. They are not counted in the Validated/Partial totals. Each one keeps its evidence and is tracked as an optional `enhancement` issue, for anyone who later wants -to test it or add support. +to test it or add support. Source-confirmed extras may also retain their historical +row location under the legend's carve-out, with a narrowed parity issue and separately +approved removal rather than an optional enhancement. The sidebar-only Needs-you row +above is such a classification. | macOS surface | Required visible behavior | Windows evidence | Status | |---|---|---|---| diff --git a/investigation/windows-parity-lane-kickoff.md b/investigation/windows-parity-lane-kickoff.md index f66e1347..7e8526cc 100644 --- a/investigation/windows-parity-lane-kickoff.md +++ b/investigation/windows-parity-lane-kickoff.md @@ -86,9 +86,22 @@ the macOS path to the same result exists on Windows; if it doesn't, keep the act record it as a deliberate extra. References on this machine: -- **macOS captures:** `%USERPROFILE%\Downloads\GraphCode-macOS-Reference-RunA\GraphCode-macOS-Reference-RunA\`. - Use the `@1x-srgb.png` files and `README.md`. +- **Primary macOS reference:** the coordinator-provided, read-only ground-truth + bundle from source `2ccf303a04f995184aae1d4b738a9eca0f71b79e`. Read its + `README.md`, item index and complete privacy report before opening the applicable + `@1x-srgb.png` images. `Recorded` is an observation, not a conformance verdict; + `Exists, not recorded` is not absence. Match the actual selection and state. + Fitted canvas pixels are not authored card dimensions or 100% zoom. +- **Publication hold:** consult the local notice + `C:\gc-ref\macos-groundtruth-2ccf303a.DO-NOT-PUBLISH.txt` by path only; do not + copy the notice or held images. Every other image needs individual visual privacy + clearance before upload. A sample review, correct masks or matching hashes do not + clear unreviewed images, especially masked terminal captures. +- **Historical macOS fallback:** Run A is secondary, only for a state the primary + lacks. Keep its source, fixture and evidence limits distinct. - **Windows beta26 "before" captures:** `C:\GraphCode-DevBox-Return\media\`. + Label them **Windows beta26 (pre-wave-1)**, not current main or a wave-2 head. + They can support a historical pair; current behavior requires current evidence. - **Side-by-side review:** `C:\gc-logs\visual-parity-review.md`. - **macOS source audit:** `C:\gc-logs\parity-extras-audit.md`. - **Privacy:** never upload or quote `734/*.zip` contents or `721-needs-you-chip-clicked`. diff --git a/investigation/windows-parity-orchestration-plan.md b/investigation/windows-parity-orchestration-plan.md index dad149ae..a87ba923 100644 --- a/investigation/windows-parity-orchestration-plan.md +++ b/investigation/windows-parity-orchestration-plan.md @@ -384,23 +384,42 @@ silently. ## macOS ground truth -The next macOS run uses the ground-truth prompt template: -- the agent records what macOS does; -- statuses are `Recorded`, `Differs from request`, `Absent on macOS` and - `Exists, not recorded`; -- inventory is checked against source first; -- the fixture is corrected (spaced titles via UI rename, `--check` on turn - loops, a cycle-only component, and a UI-created guarded edge); -- menus are read in the same selection state on both platforms; -- the privacy scan covers archive contents. - -It must cover the 30 rows the side-by-side review could not assess, plus: -- the edge sheet; -- Project Settings; -- the update dialogs; -- populated Quick Chats; -- the RUNNING and BLOCKED card states; -- whether macOS shows a sidebar Needs-you section. +The local ground-truth recording from source +`2ccf303a04f995184aae1d4b738a9eca0f71b79e` has returned. It is the primary +reference ahead of Run A, not a conformance verdict or a committed image bundle. +Its 354 items are 244 `Recorded`, 4 `Differs from request`, 3 `Absent on macOS` +and 103 `Exists, not recorded`. An unrecorded updater, workspace, input or +type/state combination is not an absent feature. Source-confirm an absence's +precise scope before narrowing an issue or planning a Windows-extra removal. + +The bounded different-vendor intake opened 12 primary and 3 comparison images +and checked 5 metadata negative controls; it did not visually clear all 784 images. +Observe the local publication-hold notice referenced by the canonical worker +kickoff. Every image needs its own privacy clearance before upload; hashes, +OCR and correctly black mask rectangles do not prove that adjacent content is +safe. Never commit the bundle, its hold notice or a wholesale copy. + +Use the `@1x-srgb` copies after reading the privacy report, item notes and +capture metadata. Distinguish native backing scale, copy scale and canvas zoom. +The `764-final-fixtures-fitted` images show the **ParityRef project canvas at +90%**, not the global graph claimed by stale metadata. They remain useful for +the recorded cards, not global-graph, overview-start or lane-caption evidence. +Use the separately recorded global overview for that context. Likewise, a +disabled global menu command is not evidence that a similarly named workspace +bar button is disabled. + +The ledger's dated intake recovers all 30 previously unassessed row identities. +Pair only exact states that were actually recorded. The retained Windows +bundle is **Windows beta26 (pre-wave-1)**; a historical pair is not a verdict +on current main. Missing current pairs are qualification gaps, not invented +product failures, and do not satisfy the ledger's `Validated` gate. + +Keep this reference intake separate from final A-E reconciliation on merged +heads. Existing approved slices are not reopened unless the source or recording +contradicts them. Partial slices, source/UIA checks and new macOS images do not +close whole claims. Any extra removal needs its own bounded approval and an +audit of reachable equivalent actions. No screenshot, golden-image or pixel +baseline CI lane is revived by this intake. ## Cadence