diff --git a/investigation/ui-parity-matrix.md b/investigation/ui-parity-matrix.md index abb07e55..94bf5f49 100644 --- a/investigation/ui-parity-matrix.md +++ b/investigation/ui-parity-matrix.md @@ -20,10 +20,10 @@ Statuses: | macOS surface | Required visible behavior | Windows evidence | Status | |---|---|---|---| -| Main split view | Persistent sidebar; detail switches among welcome, global graph, project canvas, Quick Chats canvas, and loop workspace | Explicit destinations exist; the earlier stub walkthrough covered project → overview → workspace → Show in Graph with sidebar retention. The shared header now follows destination identity, distinguishes a Quick Chat workspace from a previously selected project, and keeps detail-panel toggling inside the loop workspace. Production-state and layout tests cover the destinations, narrow widths, and sidebar/panel independence. A local Console/WinSta0\\Default live gate found a visible shell and read `graphcode-root` with the shell in the background; foreground is not a prerequisite for UIA root access. Its desktop-wide update-dialog search returned null despite a visible native dialog, while PID-scoped `FromHandle` found the dialog and its Later button. One subsequent run reached the full gate result, but its output pipeline did not exit, and other runs hit unrelated intermittent assertions. No new F6/Jump/pixel/sidebar-effect or provider-backed workspace/panel parity proof was obtained | Partial | -| Window toolbar | Needs-you chip, worktree notice, jump field, contextual loop-panel toggle | Render, hit-test, UIA exposure, and focus order share header visibility/layout. Needs-you opens the selected attention target; cached local worktree notices honor the owning project and count/size threshold. Jump opens the existing palette even with no projects. The detail toggle is limited to loop workspaces with supported edge/metric content; workspace/project identity is no longer overpainted. F6 entry/exit, scoped traversal/activation, focus rendering, and marshaled UIA button focus are implemented, while ordinary Tab/Shift+Tab/Ctrl+Tab contracts remain. The header paints inside the buffered logical pass; literal 96/144/192-DPI bounds and hidden native client tests cover logical layout/input and exactly-once physical UIA conversion without rescaling terminal tabs. Production-helper tests, a hidden native Tab-to-command test, and a hidden empty-palette create/cancel test pass. A local live gate resolved the background shell UIA root and later observed true foreground ownership and worktree-row focus; this does not establish F6/keyboard activation, rendered toolbar pixels, sidebar effects, or provider-backed panel behavior. Desktop modal lookup required a PID-scoped HWND fallback; the gate remains intermittently unstable and this local result is not CI or full macOS parity evidence. Cross-project worktree-notice discovery/aggregation and summary/board/mailroom panel content remain separate residuals | Partial | +| Main split view | Persistent sidebar; detail switches among welcome, global graph, project canvas, Quick Chats canvas, and loop workspace | Explicit destinations exist; the shared header follows destination identity, distinguishes a Quick Chat workspace from a selected project, and keeps detail-panel toggling inside the loop workspace. Production-state and layout tests cover destinations, narrow widths, and sidebar/panel independence. The green Windows shell CI run 36489223062 acquired `graphcode-root` from a visible background shell, then drove Graph → project canvas via the painted lane Open action → Graph, opened Worktrees from the lane, opened Quick Chats and a Quick Chat terminal workspace, opened a selected-loop workspace, invoked Show in Graph, and returned through the same stable sidebar loop identity to the same project/workspace identities. This is live UIA plus real click/invocation evidence for destination and row identity, not a visual walkthrough. The macOS evidence observed welcome, global graph, Quick Chats, project, nested graph, and persistent sidebar, but did not reach terminal detail; Windows CI did not cover welcome/onboarding, narrow-width rendering, real provider content, or a visual sidebar/layout comparison. The full cross-platform row therefore remains unverified | Partial | +| Window toolbar | Needs-you chip, worktree notice, jump field, contextual loop-panel toggle | Render, hit-test, UIA exposure, and focus order share header visibility/layout. Needs-you opens the selected attention target; cached local worktree notices honor the owning project and count/size threshold. Jump opens the existing palette even with no projects. The detail toggle is limited to loop workspaces with supported edge/metric content; workspace/project identity is no longer overpainted. F6 entry/exit, scoped traversal/activation, focus rendering, and marshaled UIA button focus are implemented, while ordinary Tab/Shift+Tab/Ctrl+Tab contracts remain. The header paints inside the buffered logical pass; literal 96/144/192-DPI bounds and hidden native client tests cover logical layout/input and exactly-once physical UIA conversion without rescaling terminal tabs. The green Windows shell CI run 36489223062 provided live evidence for workspace toolbar identity, Jump filtering and Return navigation, and the contextual loop-panel Collapse/Expand control with non-empty bounds; it also exercised real foreground focus elsewhere in the shell. The macOS runtime evidence observed the named title, Jump, and the 8-versus-7 worktree-notice boundary, but not Needs You or the loop panel. Windows CI did not exercise the notice boundary or a populated Needs You chip, and neither side supplied a complete rendered-toolbar comparison or provider-backed panel-content walkthrough. Those are user-visible parts of this row, so it remains `Partial`; the separately owned Worktree notice chip row carries its own evidence | Partial | | Jump palette | Search field, ranked cross-project results, type/state/project context, mouse and keyboard selection | Ctrl+P and Ctrl+J open a native modal palette with live exact-ID, exact-title, title-prefix, and substring ranking across projects. Results visibly include project, loop type, and state; Up/Down, Return, Escape, and mouse double-click are supported. The deterministic UIA gate verifies a visible search field, contextual cross-project results, and keyboard navigation changing the selected loop. | Validated | -| 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 and the five readable runtime groups were probed. Reclaim/Reveal require a selected row (`worktreeRowSelected()` retains dedicated unit coverage); Save requires the Worktrees dialog open. Loop commands now gray out when they have no actionable target: Jump requires a loaded loop anywhere, Next/Previous require at least two loops or one unselected loop in the active graph, Create Edge requires two active-graph loops, and Stop requires a selected loop. These distinct thresholds follow their different production handlers and are intentional. Terminal Next/Previous Tab and Focus Next/Previous Pane require multiple tabs or panes in the selected tab. A hidden-window test calls `MainWindow.updateMenu` and verifies the real native HMENU `MF_GRAYED` bits in both unavailable and available states; this is unit/runtime Win32-menu evidence, not a live application walkthrough. A local built shell exposed its UIA root while background, and the live gate traversed worktree rows and menu actions after PID-scoped update-dialog resolution; root inspection does not require foreground. A complete, reliably exiting live Worktrees-menu walkthrough and broader project-management parity remain unverified | Partial | +| 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. 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 macOS runtime evidence read global-graph File/Loop/Terminal labels and enablement through Accessibility, but did not invoke key equivalents or enter a Terminal context. 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` | 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 | 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 | @@ -94,9 +94,9 @@ native keyboard/accelerator/window proof; the workspace row remains 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 | Partial | | Edge editing | Preserve identity/configuration and refuse stale edits | Windows uses an owned modal snapshot and one checked `updateEdge`, retaining endpoints, current fireCount, transform/spawn settings and unchanged optional legacy guards. Root/direct-composite scope and current cache are rechecked without treating observation subscription as authorization. Existing serialized daemon commands, blocking, parent roll-up and root publication remain authoritative; deeper new edit wrappers are refused. Production-helper regressions exercise actual Wire JSON/unstarted queues, foreign scopes, refresh, cancellation and allocation cleanup. Edit-only live/submit capture reads complete Unicode text and blocks acceptance on per-field read/allocation errors; injected-reader and initializer tests show no controls. In-memory Swift store tests cover CAS, kind/blocking rules, root publication, preview refusal and serialized legacy-child writeback followed by an edit that retains runtime progress. This is not native editing, daemon acceptance/persistence or macOS runtime evidence; macOS sources expose creation-time configuration and delete, not an existing edit UI | Partial | | Node creation sheet | Loop-type teaching tiles, conditional fields, backend/model/branch pickers, recap, validation reason | A guided native form provides loop-type/backend/model choices, type-specific fields, explanatory copy, accessible checkboxes, inline validation, keyboard traversal, scrolling, and a live-updating recap. The native Branch picker offers inspection choices plus “This folder”; existing tests cover its empty state and selected binding, and earlier gate evidence covers the recap, Branch picker, and distinct Attach control. Staging now reserves a uniquely named file exclusively: the production append/removal regression first demonstrated A/B/C → remove B → add D overwriting C's bytes, then passed with C's original path and bytes preserved. Offline in-file coverage also checks template-restored/legacy files, preexisting destination collisions, partial-write rollback, allocation failures without orphan copies, invalid inputs, exactly eight files and the ninth rejection, and the exact 10 MiB/+1-byte boundary. Existing attachment DTO/wire tests remain passing; these are no-window helper/filesystem results, not OS input or daemon persistence evidence. Creation choices now own an exact-project snapshot of inspected path/branch strings across cache/model replacement; baseline aliasing and foreign-cache regressions fail before the fix and pass afterward. Noninteractive production-projection tests cover snapshot lifetime, projection without a loaded graph, and allocation-failure cleanup. Separate pure initializer/builder-to-Wire tests verify exact non-default repository/id/path/branch fields, initial/current/template-restored selection, and “This folder” clearing with available choices; legacy empty-choice hidden binding remains unchanged. This does not establish actual native non-default selection, a Git-inspection-to-creation flow, or daemon save/reload. **Still partial:** actual inspected nondefault binding and project-scoped ownership across pumped modals remain unproved; New branch and remote/global branch visibility differ from macOS; authentic OS picker acceptance/cancellation, clipboard paste/drop, and native-input → request → daemon save/reload evidence remain outstanding. Per-file removed-file reclamation and legacy unguarded cleanup remain separate residuals. Creation now retains the original project/composite context and validates after modal teardown, before attachment transfer, across normal, template-load-error, empty-library, and template-loop submissions without switching selection or client scope. Bounded offline production-boundary RED/GREEN and owned temporary-file tests cover stale-scope refusal, loaded-project closure, same-path refresh/promotion, path-only starts, valid empty composites, template continuation, allocation unwinding, and checked cleanup failures. Guarded staging reserves its attachment-directory leaf exclusively; cancellation/refusal and zero-reference acceptance abandon only that owned leaf, while nonzero accepted attachment bytes survive. Zero-reference drafts preserve existing empty-ID/wire behavior. These are helper/model/unstarted-client-queue proofs, not live modal, OS picker, or daemon-persistence evidence; path-only external disappearance and downstream send failure remain limitations | Partial | -| Node update/rename | Dedicated rename prompt and safe typed updates | Rename retains its dedicated safe prompt. Edit Details uses `NativeForms.update` and `sendUpdateNodeForm`; its project/node identity is now owned across the modal message loop and re-resolved afterward, and changed strings are compared against the form's owned initial snapshot rather than potentially freed graph strings. Original numeric scalars and clear-versus-unchanged semantics are preserved. Production-helper tests cover source mutation, unchanged/changed typed fields, cancellation, clearing, and allocation failures. The lifetime test rejects the original borrowed baseline. Earlier focused attempts stopped at background-menu activation before reaching editor or rename actions; a separate local live gate now accessed the background UIA root and later read native context-menu contents after foreground acquisition, but did not submit a rename or Edit Details action. App-level dispatch, cancellation, and returned model results remain unverified | Partial | +| Node update/rename | Dedicated rename prompt and safe typed updates | Rename retains its dedicated safe prompt. Edit Details uses `NativeForms.update` and `sendUpdateNodeForm`; project/node identity is owned across the modal loop and re-resolved afterward, changed strings are compared with an owned initial snapshot, and numeric plus clear-versus-unchanged semantics are preserved. Production-helper tests cover mutation, unchanged/changed typed fields, cancellation, clearing, allocation failures, and the former borrowed-baseline lifetime bug. The green Windows shell CI run 36489223062 opened the live Rename Loop dialog, verified its explanation, Title label, and prefilled current title, typed a replacement title and submitted it with Return, and observed the dialog close. The same run found Rename and Edit Details in live plain, composite, and unwired node popups. It did not verify the renamed title in the graph/sidebar/model after submission and did not open, cancel, or submit Edit Details. macOS runtime evidence did verify a root rename reaching overview/sidebar, but reproduced a nested Rename action that showed no dialog and did not exercise typed retype. Presence plus dialog closure is not end-to-end update parity, so app-level rename result and Edit Details behavior remain residuals and the row stays `Partial` | Partial | | Delete confirmations | Named object, consequences, safe default | Loop deletion names the loop and explains graph-connection removal. Edge deletion now names both endpoint loops and the connection kind, explains that the loops remain, re-resolves the stable edge after confirmation, and defaults to cancellation | Validated | -| Canvas context menu | Folder actions on background; complete node/edge actions | Project backgrounds now expose existing Worktrees, Project Settings, and Explorer routes with captured project context; unavailable non-filesystem actions are disabled and global scope omits them. Create Edge remains present but disabled with fewer than two loops. Resolved node menus omit Stop, matching macOS; composite/template/unwired actions and the absence of Message/Memo are preserved. Tests inspect the same native HMENU builder used by `TrackPopupMenu`, including an exact disabled-item assertion that fails when Create Edge is removed. The existing gate already inspects plain/composite/unwired popup contents; its succeeded-node Stop assertion now requires absence. Earlier focused attempts read a background popup without completing an action, and a separate minimal native control failed foreground acquisition for an unproven reason; neither blocks background UIA root inspection. A new local live gate run acquired real foreground, read a 12-item native project context menu and dismissed it, but did not prove node/edge/background action results, New Child, import/export, custody child creation, or sketch promotion. The gate remains intermittently unstable | Partial | +| Canvas context menu | Folder actions on background; complete node/edge actions | Project backgrounds expose Worktrees, Project Settings, and Explorer routes with captured project context; unavailable non-filesystem actions are disabled and global scope omits them. Create Edge remains present but disabled with fewer than two loops. Resolved node menus omit Stop; composite/template/unwired actions and the absence of Message/Memo are preserved. Tests inspect the same native HMENU builder used by `TrackPopupMenu`. The green Windows shell CI run 36489223062 opened and read the real native plain, composite, and unwired loop popups, required their state-specific labels and absences, verified disabled Arm Schedule for an unpiloted composite, and dismissed each menu without losing the UIA tree. It also read local and remote project popups, including disabled unavailable Move Project and omission of local-only actions for a remote project. macOS runtime evidence sampled Composite, Main, and background menus but did not open its edge menu. Neither runtime drove a destructive confirmation or edge popup, and Windows CI did not invoke node/background menu results, New Child, import/export, custody creation, or promotion. Those actions are part of this row's explicit node/edge contract, so popup presence and enablement alone do not justify promotion | Partial | | Sketch promotion | Promote a sketch to Goal, Turn, or Timed without replacing its identity or session | Canvas and sidebar context menus use one production submenu plan and focused native forms. Owned popup/form snapshots reject stale scope, selection, type, and deletion; initial selection of a different cached project remains supported independently of the observation subscription. Filtered pure tests exercise the actual App selection adapter, typed native-form builder, and unstarted DaemonClient outbound queue, including composite addressing and allocation failures. Three emitted fixtures decode as existing Swift `promoteNode` variants, and the full Windows application builds ReleaseSafe. A native Win32 test attaches the production node popup to a hidden HWND and checks the Goal/Turn/Timed submenu's presence, IDs, labels, and enabled states through the actual HMENU; it does not show or select the popup. Local command construction/queueing and this native menu state are proven, but native keyboard interaction, UIA, app launch, and real-daemon acceptance/persistence remain unexercised | Partial | ## Quick Chats