Repository navigation
Windows parity: Canvas loop cards match the macOS card (layout, states, roles, colours) #764
Copy link
Copy link
Open
Labels
P1 layoutParity priority 1: layout, clipping, overlap, broken rendering vs macOSParity priority 1: layout, clipping, overlap, broken rendering vs macOSenhancementNew feature or requestNew feature or requestparityWindows/macOS UI parity ledger row (investigation/ui-parity-matrix.md)Windows/macOS UI parity ledger row (investigation/ui-parity-matrix.md)visual parityVisual fidelity against the macOS reference capturesVisual fidelity against the macOS reference captureswindowsWindows portWindows port
Description
Visual and functional parity work item, from the 2026-10-13 side-by-side review.
- Comparison: macOS reference Run A (app at
09eda11a, Dark, 2x) against the Windows testing-gaps run (installed0.1.78-windows.beta26, 2560x1440 at 100%). - Ground truth: macOS is the reference. Only platform chrome may differ: the title bar, window buttons, menu-bar location and native file pickers.
- Evidence limits:
- File names below refer to the two local evidence bundles. The next macOS ground-truth run will attach captures.
- Difference IDs (D1, E2, …) refer to the review report.
- The reviewer opened the paired images it cites. Some surfaces could not be reviewed; they are listed under "Captures needed" in the ledger entry.
- Done when: every acceptance box is met and shown with paired screenshots in the PR. Before/after Windows captures go next to the macOS capture, and a reviewer from a different model vendor confirms them. A UIA readback or green unit test alone does not satisfy a visual criterion.
Evidence:
- macOS:
740/740-parityref-above-threshold-8-linked-canvas,727/727-canvas-final-states; - Windows:
tg720-project-canvas-1440,tg727-728-canvas; - differences D1–D10;
- source:
GraphCanvas.zig:1660-1700, 1899-1904,DesignTokens.zig:101-104.
Acceptance criteria:
- A card at 100% matches macOS: 250x96 pt (
LoopCardView.Metrics.size,graphcode/Sources/Features/Canvas/LoopCardView.swift:47; the 727 capture is at 68% zoom) with a semibold title, a right-aligned state pill (IDLE / DONE / STOPPED / NEEDS YOU / RUNNING / BLOCKED), a mono detail line and a mono meta line ("■ · · "). - Type stripes and dots use the macOS
LoopTypeAppearanceaccents: Main #d3dae3, Goal #199e70, Timed #c98500, Turn #d55181, Composite #9085e9. Use one shared table for the canvas, sidebar, loop bar, jump palette and New Loop tiles. - Entry loops show the green "entry" chip, and the ENTRY marker node with lines to the entry ports appears as in
727-canvas-final-states. - Unwired cards show an inline "Wire it up" button and a "Mark as entry" link. The "No connections · right-click to recover" text is removed.
- Loops awaiting input show an amber pill, an amber glow and an "Inspect" or "Reply" button whenever the rail or toolbar counts them.
- Cards are laid out by flow (ENTRY → Main → … → leaves, with sketches stacked under ENTRY), and the canvas opens fitted to content.
- Port dots appear on the card edges, and the project group frame carries the "N worktrees · N reclaimable" chip.
- The add action is "+ New Node", outlined, at the top right.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P1 layoutParity priority 1: layout, clipping, overlap, broken rendering vs macOSParity priority 1: layout, clipping, overlap, broken rendering vs macOSenhancementNew feature or requestNew feature or requestparityWindows/macOS UI parity ledger row (investigation/ui-parity-matrix.md)Windows/macOS UI parity ledger row (investigation/ui-parity-matrix.md)visual parityVisual fidelity against the macOS reference capturesVisual fidelity against the macOS reference captureswindowsWindows portWindows port
Activity
coneilen commentedon Oct 14, 2026
Correction (coordinator, 2026-10-14): the card size at 100% is 250x96 pt, per \LoopCardView.Metrics.size\ in \graphcode/Sources/Features/Canvas/LoopCardView.swift:47. The earlier about-200x75 figure was measured from a 68%-zoom capture. Lane B2 caught this.
coneilen commentedon Oct 14, 2026
Escalation record (wave 1, lane B), 2026-10-14 04:45 PDT.
gpt-6.1-sol, high, long_context (lane B2)claude-sonnet-5.5), per the abandon rule ininvestigation/windows-parity-orchestration-plan.mdclaude-sonnet-5.5, xhigh, long_context (lane B3); reviewergpt-6.1-solState handed over: frozen head
717e8599onfix-canvas-card-layout, not rebased; no PR opened.Reviewer-accepted work:
Open findings, which B3 must close test-first:
DT_PATH_ELLIPSISdoes not middle-elide forward-slash branch metadata, so backend and age get hard-clipped. Needs a measured manual middle ellipsis.Coordinator decisions:
investigation/visual-baseline/manifest.jsonkeeps250x106. It's a historical pin atece55b6, where macOS really was 250x106.LoopCardView.swift:47.coneilen commentedon Oct 14, 2026
Wave 1 stopped (operator decision, 2026-10-14). No PR was opened; B3 reached
e63c06felocally. All this work is abandoned.Decisions and findings to reuse in wave 2:
LoopCardView.swift:47). Leave the250x106entry ininvestigation/visual-baseline/manifest.jsonalone: it's a historical pin atece55b6..system(size: 10.5, design: .monospaced), use Consolas.DT_PATH_ELLIPSISdoesn't middle-elide branch names that contain forward slashes. Use a measured middle ellipsis, so that the backend and age are never clipped.Restarting from
mainunderinvestigation/windows-parity-lane-kickoff.md.coneilen commentedon Oct 14, 2026
Implementation plan (wave 2)
Planning worker
pb, lane B. Source baseline:origin/mainand this worktree both at8ea81062a6220e1d2ecfdaa8a73d8eb59ac575b4. Read-only investigation; no product edits, builds, desktop use, or runtime claims.Complexity rating
Rating: highly complex. This assessment covers only the compact-card slice approved in the coordinator corrections:
GraphCanvas.zig, card-localDesignTokens.zig, the existing singleAppFont.zigcache, and the project-card action block inApp.zig'ssyncAccessibilityToplus its never-shown regression. The denied ledger edit is excluded.The reason is the many interdependent steps across large files criterion, not the total issue size or a new general-purpose UI framework: the project and overview currently have different renderers and card dimensions; making both consume one compact body couples font measurement to title/pill allocation, owned Unicode text to measured middle elision, and overview dimensions to lane/content extents. Shrinking the card also moves existing actionable rectangles, so paint, pointer hit tests and App UIA publication must change consistently without breaking identities, DPI conversion or reclaim safety. The shared process-lifetime font-cache extension must preserve handles borrowed by unrelated native controls while adding face/weight keys and bounded-growth behavior. These coupled geometry, ownership and publication changes span the five implementation steps below even after removing all ledger work. This is more than an isolated size, label or drawing adjustment. Boxes 2-8 and every other exclusion in the coordinator correction remain outside this assessment and implementation.
Prior decisions verified
Read Wave 1 stopped first, then the earlier review/escalation findings. The abandoned heads are not implementation starting points.
graphcode/Sources/Features/Canvas/LoopCardView.swift:46-52. I also readgit show ece55b6:graphcode/Sources/Features/Canvas/LoopCardView.swift: that historical version really says 250 x 106. Do not editinvestigation/visual-baseline/manifest.json:70.LoopCardView.swift:127-135), not the existing regular Windows 14.LoopCardPresentation.swift:233-241), prefixed by a drawn six-point type square (LoopCardView.swift:265-278).claudeCodeis the default and is omitted; do not replace it with an always-present "Claude Code" badge.GraphCanvas.zig:1802-1843); do not replace it with 256-byte activity / 128-byte metric buffers and reproduce wave 1's truncation.DT_PATH_ELLIPSIS, for slash-containing branch names. Reserve the backend and age before allocating branch width. The Windows main renderer uses tail ellipsis, so the specific path-ellipsis failure is a retained review finding, not a new runtime reproduction in this planning session.AppFont.zig:26-58is a process-global, process-lifetime cache. Cache tests must measure growth from a recorded starting point, then zero additional growth on a repeated identical sweep, not an absolute final count.All eight acceptance boxes: source comparison and cause
Line references below are against the baseline above.
macmeansgraphcode/Sources/Features/;winmeansgraphcode-windows/src/.mac/Canvas/LoopCardView.swift:46-52,64-85,127-175,265-278,354-380: 250x96, 8-point top/bottom and 11-point horizontal padding, six-point row spacing, semibold title and right-aligned fixed-content pill; mono single-line live/detail/meta.mac/Canvas/LoopCardPresentation.swift:108-160,175-180,233-241,272-281: activity with pass prefix before type-specific fallback, human action before metric progress, ordered metadata, real coarse duration.mac/App/LoopStateAppearance.swift:31-42,49-53,88-121: uppercase state vocabulary, hollow/solid indicators, distinct fill/ink; Timed idle is SCHEDULED, not IDLE.win/DesignTokens.zig:102-105is 250x106.win/GraphCanvas.zig:1655-1718paints title, raw lowercase state on a separate row, variable extra START/UNWIRED row, then rows at state+20/+35/+43.drawText/drawTextRectselect regular Segoe (2445-2485).nodeMetadata(1802-1843) mixes pass/metric/raw backend/coarse age/tokens/branch/tier in one 128-byte line. Overview separately paints 220x86 cards with just title/raw state (809-853,903-919).drawNodeanddrawOverviewhave independent renderers; the geometry reserves a whole row for state and never measures a title/pill pair. For an entry at 100%, metadata starts at y=90 inside a 106-high card; simply changing the height clips it.nodePrimaryDetailprioritizes handed goal over live activity; metadata has neither a type label nor backend presentation mapping, and the fixed stream silently returns truncated data. This is the primary slice.mac/App/LoopTypeAppearance.swift:43-47defines Main #d3dae3, Goal #199e70, Timed #c98500, Turn #d55181, Composite #9085e9.win/GraphCanvas.zig:1903-1909has wrong canvas colors and no Timed case; its panel-only table (2148-2154) is already correct.Sidebar.zig:485-490andTerminalSurface.zig:7169-7174have other wrong tables.JumpPalette.zig:1323-1329is already correct.NativeForms.zig:229-234has correct tile literals.mac/Canvas/CardEntryRole.swift:33-48,55-70derives roles and draws green lowercaseentry;mac/Canvas/LoopCardView.swift:112-125,293-297draws leading-edge ports/chips. The ENTRY origin still exists:mac/Canvas/CanvasBand.swift:129-194draws the centered origin dot, ENTRY word, and quiet tethers;Project/ProjectCanvasView.swift:360-385,399-421supplies ports and band. Do not mistake older "marker replaced" comments for executable behavior.win/GraphCanvas.zig:1683-1684,1937-1949draws START/UNWIRED as upper labels and has no cycle-only role.paintproject arm (691-706) draws edges/cards but no group band, origin or tethers.nodeRoleonly checks inbound/outbound and declared entries; no band/origin layer exists. Follow-up needs role, group geometry and origin routing together; painting an unrelated START dot is not the fix. Deferred.mac/Canvas/LoopCardView.swift:65-75,248-262: inline Wire it up button and Mark as entry link replace normal live/detail rows, while meta remains.mac/Project/ProjectCanvasCards.swift:40-41starts wiring / dispatches marking. Overview's same verbs navigate to that loop's folder (mac/Overview/GraphOverviewCards.swift:179-185).win/GraphCanvas.zig:1697-1698draws the old sentence. Actions exist only in context menus;win/App.zig:4390-4424already implements session entry acknowledgment andbeginWireSelectedNode.mac/Project/ProjectCanvasView.swift:43-61,75-80builds one rollup/reason map for rail and card tint.LoopCardView.swift:58-60,86-107,167-183uses it for surface/border/glow;LoopCardPresentation.swift:155-160,175-180chooses Reply for awaiting input and Inspect for blocked.GraphcodeKit/Sources/Domain/LoopNode.swift:506-525projects live presence before stored state, including awaiting input on a resolved/blocked node.win/GraphModel.zig:1325-1341,1379-1389counts awaitingInput presence regardless of stored state.win/GraphCanvas.zig:1911-1934only notices awaitingInput when state is running, and separately approximates stranded blocked using handoff kind, unlikeGraphModel'sblocks_targetpath.cardTextLayout:2050-2064hides actions under 75% zoom;drawNodealways uses ordinary flat card fill. Overview has no attention actions.App.zig:7852-7853). A faithful repair needs one authoritative reason/identity path and action availability independent of the count's display location. This slice adds correct pill words for the fields it already receives and preserves/repositions existing project buttons, but does not claim to close box 5: authoritative rollup, glow and overview actions remain a separate change.mac/Canvas/LaneLayout.swift:20-36,39-115,146-200lays out starts/chains by graph depth and puts loose loops in a block below chains, with wrapping row budgets;mac/Project/ProjectCanvasView.swift:185-215measures full extents and fits only while untouched.win/GraphCanvas.zig:1881-1887uses index %3 and /3 with absolute sidebar/header offsets.overviewCardBounds:903-919also grids by index.contentSize:1020-1036uses counts, not actual moved-node extents.CanvasState.fit:370-381exists but is not an opening-layout policy; App invokes it for explicit Fit (6810-6816).mac/Canvas/LoopCardView.swift:112-125. Group band follows card extents:mac/Canvas/CanvasBand.swift:41-59; worktree chip is absent until nonzero stats and reads count plus nonzero reclaimable (66-80); project supplies it outside composites (ProjectCanvasView.swift:388-421).win/GraphCanvas.zig:1638-1653computes connector points, butdrawNode:1706-1710only paints an outgoing hover square.projectWorktreeChip:412-449already has count/reclaimable text, but paints at fixed viewport-top bounds and no enclosing band.mac/Canvas/CanvasAddButton.swift:17-39is a dark, bordered, radius-8 control, 30 high, plus glyph plus 12-point semibold New Node.mac/Project/ProjectCanvasView.swift:103-110anchors it top right.win/App.zig:7055-7059,7063-7112creates/moves an ordinary native light New Loop button; it also shares its handle/state with empty global and Quick Chat actions.Ledger rows read: Graph overview/project canvas and Loop authoring sections, especially Loop card identity/live detail/attention, Unwired card recovery, Folder lanes/bands and New Loop canvas button. They remain Partial. The live-detail row currently lists tokens/model tier as requirements/evidence; the stopped-comment decision explicitly supersedes that card-meta wording, not their availability in workspace details.
First PR: compact, readable card presentation only
Target: acceptance box 1's card presentation at 100% in both project canvas and global overview. Share the card body instead of fixing only project cards and leaving the overview's second renderer behind. No product feature deletion.
To leave unchecked: boxes 2-8. In particular, a NEEDS YOU pill in this PR is not proof of attention-rollup parity or glow; START/UNWIRED roles and their context-menu recovery remain until their follow-up; no entry marker, topology, band, add-button or cross-surface palette work. Quick Chat cards are not loop cards and remain unchanged.
Box 1 is a target, not pre-approved completion. Check it only after its focused assertions and paired image review pass. The full issue stays open (
Refs #764). If the reviewer requires a presently undecoded macOS field to satisfy the box, leave it partial and request a named decoder extension rather than silently inventing text or broadening the PR.Implementation steps and RED/GREEN contracts
All test names below are proposed, not tests I executed. Use existing registered roots, no new root/harness requirement. Start with passing-compilation tests against current entry points. If a seam needs extraction, first make a behavior-preserving extraction that still calls the current implementation, then obtain the assertion failure; a missing helper/compiler error does not count as RED.
Metrics and container-derived geometry.
DesignTokens.zigcard height only;GraphCanvas.zigCardTextLayout,cardTextLayout,nodeBounds,overviewCardBounds,overviewLaneHeightandcontentSizewhere overview pitches/extents need to accommodate the larger 250x96 card.GraphCanvas.zig,loop card parity metrics and rows fit the owning card: at zoom 1 assert project and overview widths=250, heights=96; bounds for title/pill/live/detail/meta inside the content inset; pairwise row separation and title-right <= pill-left-gap. Include long title and NEEDS YOU / SCHEDULED labels, translated x >1200, zoom 0.55/0.75/1/1.25/1.8 and nonzero pan. Assert adjacent overview cards and following lane do not overlap.GraphCanvas.zig:2913-2919must be updated intentionally, not merely have its old literal 106 hidden.Card-specific fonts through the one AppFont cache.
AppFont.zigCacheEntry/getScaledand additive style accessors;GraphCanvas.zigcard text drawing. Do not globally turn everydrawTextinto semibold or change dialog/sidebar fonts.(size,bold)behavior; extend that same cache with face and actual weight in its key. Add regular Consolas for live/detail/meta, semibold Segoe title, bold Segoe state label. Make GDI's integral-height rounding of 14.5/10.5 logical sizes explicit and test it; do not apply monitor DPI inside the logical mapped canvas a second time (App.zig:9115-9127). Retain cached handle ownership for process lifetime; do not add a second renderer-local cache or a cache-full path leaking a freshly-created font on every paint.AppFont.zig,loop card parity font faces weights and cache growth: inspectLOGFONTWwithGetObjectWfor family, weight and rounded height; preserve identity of existing regular/semibold API calls. Record initial cache size, sweep the finite card-size/style keys for zoom 0.55 through 1.8 and DPI 96/120/144/192, assert growth bounded by the number of unique requested keys, then repeat and assert zero further growth / same handles. Exercise existing callers' keys before the sweep. If storage needs more capacity, size it to the measured finite key set and test capacity handling; never evict an HFONT still borrowed by native controls.Owned presentation strings and measured elision.
GraphCanvas.zignodePrimaryDetail,nodeMetadata,writeMetricChange, card-specific age/presentation helpers and the shared card renderer called bydrawNode/drawOverview.Nodefields. Prefer collapsed activity withpass Nwhen reported; otherwise use the type's existing first instruction / goal / prompt / check / composite pilot data, without manufacturing daemon readings. Keep metric readings/change in a dedicated detail row instead of metadata. Keep complete allocated UTF-8/UTF-16 strings through measuring/drawing, and unwind ownership/errors explicitly; return no success-shaped truncated prefix.nowin whole Unix seconds. Known backend names come fromGraphcodeKit/Sources/Domain/BackendCapabilities.swift:70-79; reuse an existing suitable mapper if available, otherwise a card-local mapping is sufficient for this slice. Unknown wire identifiers must not be relabeled as a different known backend. Preserve non-cardformatTokenUsageandelapsedLabelbehavior used inloopDetailFooter/ attention rail; give card formatting its own accurate duration rather than changing unrelated surfaces.DT_PATH_ELLIPSIS, no byte-count approximations, no arbitrary string-length buffers. Tail-elide a live line only at render time. If the non-elidable fields alone cannot fit, report that exact case to the coordinator rather than clipping backend/age and claiming success.GraphCanvas.zig,loop card parity live and meta content: exact output parts for all five types, default/non-default backend, branch/no branch, real 0s/59s/1m/59m/1h/1d 2h boundaries; no tokens/tier/raw backend. Assert activity wins over a populated goal and includes the pass prefix; whitespace collapses. Separate metric 1->3/maximize and 3->1/minimize with at least two samples, no invented zero-sample trend. Update existing card-only metadata assertions (3111-3172) without removing detail-panel token assertions.nodePrimaryDetailreturns goal instead of reported activity; metadata lacks type, usescopilotCLI, includes tokens/tier, and has<1h/>1hinstead of actual duration.GraphCanvas.zig,loop card parity long Unicode text and middle elision: activity >256 bytes, branch >128 bytes with forward slashes and non-ASCII/supplementary characters, nonintegral huge finite metric (for example 1e150), and allocation-failure unwinding. Verify full owned source strings before elision, valid UTF-8/UTF-16 after elision, positive measured text counts, branch head+tail, total measured width <= available width and intact type/backend/age. Expected baseline RED: its 128-byte metadata stream loses the suffix; the current whole-line tail-ellipsis paint does not retain it. Re-run the same production paint into a hidden DIB so an unused "correct" formatter cannot pass whiledrawNodekeeps the old path.One body renderer, uppercase right-hand pill.
GraphCanvas.zigdrawNode,drawOverview, card-specific state presentation and paint helpers.stateColor's R/B-swapped old COLORREF literals as the new palette.LoopNode.displayStateis not representable byGraphModel.Node:6-35today; no decoder or lifecycle inference is authorized in this PR. Record that limit, and escalate with the exact field if it blocks box 1's review.GraphCanvas.zig,loop card parity pill words indicators and title allocation: table of supported state/type/presence combinations, including succeeded+awaitingInput and blocked+awaitingInput, running+idle and timed idle; word/ink/fill/ring assertions; measured pill remains right-aligned and title is the only truncated title-row text. Expected baseline RED: rawsucceeded/idleand no pill; existing draw calls select regular font. Use memory-DC paint with positive ink/dot/fill checks in named subrects, not "some pixel changed anywhere".Preserve existing project actions when reducing height.
GraphCanvas.zigattentionActionBounds,reclaimOfferBounds, their hit tests, anddrawNode; out-of-lease request:App.zigonly the project-card portion ofsyncAccessibilityand corresponding hidden-native tests.syncAccessibility'sbounds.right-20,bounds.bottom-12probe with direct per-node presentation/visibility lookup; the old point is no longer inside the moved action. Preserve existing action identities/invoke routing and safety checks. Do not wire new commands, change attention-rollup membership, or edit other App surfaces.GraphCanvas.zig,loop card parity actions never cover meta or each other: attention, reclaim, keep and long detail cases across zooms; shared hit targets inside the card and strictly above meta; no phantom hit target where the action isn't painted. Expected baseline RED: attentionbottom-28..bottom-8and reclaimbottom-24..bottom-5overlap the new bottom meta row and reclaim uses unscaled fixed insets.App.zig,loop card parity UIA actions share painted logical bounds and scale once: use the existing never-shownoverviewTestApp/OverviewAccessibilitySinkpattern (19791-19820), notRealShellWindow/full App suite. Seed named attention and safe reclaim fixtures; publish UIA data at 96/120/144/192 DPI and pan/zoom; assert exact identities/count >0, one physical conversion and the same per-node visibility/rect as paint/hit-test. Preserve negative cases for nonattention, kept or unsafe worktrees. Expected baseline RED is overlap/geometry and stale point-based publication when testing the compact layout, not inability to create a window.Evidence and directly related ledger wording.
investigation/ui-parity-matrix.md, Loop card live detail row only, to remove the obsolete tokens/model-tier card requirement and describe actual slice evidence/limits; keep status Partial. Do not mark neighboring rows validated.Tools/windows/Tests/WindowsShell.Tests.ps1:1032,1150,1214).File scope for approval
graphcode-windows/src/GraphCanvas.ziggraphcode-windows/src/DesignTokens.zigloop_card_height106 -> 96, plus only card-local named metrics/colors actually needed. No sidebar/header/terminal/grid/zoom metric sweep.graphcode-windows/src/AppFont.ziggraphcode-windows/src/App.zigsyncAccessibilityproject-card action visibility/rectangle block and one never-shown focused regression. No layout, menu, workspace, startup, add-control or decoder changes.investigation/ui-parity-matrix.mdNo changes to GraphModel, shared Swift, provider pins, the historical manifest, Sidebar, TerminalSurface, JumpPalette, NativeForms or the gate/runner scripts. Those broader needs are documented above for later slices, not permission to edit them now.
Risks and constraints
App.zig. The coordinator must approve the named UIA block/test and avoid concurrent overlap.AppFontaffects many native controls: old API defaults and font ownership must remain stable.git diff origin/main...HEADafter every rebase, especially preserving merged Windows: make the right loop panel readable and match its macOS hierarchy #789's text bounds/detail-panel geometry rather than restoring the abandoned card branch wholesale.App.zig:9115-9127); do not combine logical zoom with a secondselectForDpiscale. Tests cover 96/120/144/192 DPI, but cannot claim physical mixed-DPI hardware. Use COLORREF0x00BBGGRR; don't silently update Theme/historical manifest to make a contract pass.ValidationRunner.Tests.ps1cases before use.C:\gcs\ID,C:\gct\ID,C:\gcp\ID; real validation folderC:\gcID, total length <=7. Never usepb's or another worker's cache. Seed only from read-onlyC:\gc-cache, bootstrap pinned environment, load it in each shell; process-only TEMP/TMP/profile. Seedonboarding-seenin fixtureGRAPHCODE_SUPPORT_DIR. No stale real-profile zmx log use, junction validation roots, PATH Swift/Zig substitutions or full local desktop suites.Exact evidence plan
I opened the following existing images directly: macOS
727-canvas-final-states@1x-srgb.png,740-parityref-above-threshold-8-linked-canvas@1x-srgb.png,740-global-graph-both-lanes@1x-srgb.png, final RefMain crop and needsyou-idle RefGoal crop; Windows beta26tg727-728-canvas.pngandtg720-project-canvas-1440.png. The images show the final 727 canvas at 68%, the 740 project/global canvases at 80%. They are not 100%-zoom card-size measurements. The image showing NEEDS YOU with no button on RefGoal also proves not to infer action availability just from a pill/crop; test source-driven states explicitly.727/727-canvas-final-states@1x-srgb.pngplus727-final-RefMain,RefGoal,RefTimed,RefTurncrops740/740-parityref-above-threshold-8-linked-canvas@1x-srgb.pngand727/727-canvas-needsyou-idle-state@1x-srgb.png740/740-global-graph-both-lanes@1x-srgb.pngFixtures must be privacy-safe, offline/stub-backed and require no paid backend turn. Use stable node/project IDs, named rows rather than broad "all cards" counts, fixed
nowfor unit expectations and recorded capture clock for ages. No private bundle ZIPs or the forbidden needs-you-click capture.Execution sequence for implementer:
Seed/verify pinned tools/providers under the implementer's own roots and run
Tools\windows\bootstrap.ps1as specified by the kickoff. Redirect process TEMP/TMP; use eachenvironment.ps1.From
graphcode-windows, run the registered roots with positive-count checks and logs kept separately for RED/GREEN:GraphCanvas existing regression subset: select the changed card/overview geometry and Windows: make the right loop panel readable and match its macOS hierarchy #789 text-bound tests in focused runs; never report a zero-match filter as pass. App native tests need the complete native/provider library link arguments from
WindowsShell.Tests.ps1:1214-1217, with--test-filter "loop card parity"and owned caches appended; do not run unfiltered App locally. Build missing provider artifacts only through the pinned repository build route.From repo root, run
pwsh -NoProfile -File Tools\windows\validate.ps1 -Task visual-baselinewith the owned environment/scratch settings. This is source/fixture validation, not proof of rendered card parity. Leave the historical 250x106 token untouched.Publish draft PR, let exact-head CI run all unit shards, integration and packaging; count nonzero relevant jobs and cite run/job IDs. No local full unit/integration suite. Complete the required different-vendor code review, with actual log opens and complete rebase-diff inspection.
Only after code review plus exact-head green: request one <=15-minute desktop lease. Capture main-before and final-head-after at 100% using
PrintWindow(hwnd,hdc,2)and pixel verification. Keep full client geometry, DPI/zoom and source SHA with each image. No ActivateWindow/Alt-tap workaround. Exit via File > Exit; stop/verify only owned process IDs including zmx; release lease.Upload only safe fixtures and have the reviewer open every mac/before/after image, with a table stating which box each proves or leaves partial. Missing real mac100 or RUNNING/BLOCKED evidence stays explicitly unverified; a source-normalized image cannot silently become a native capture.
Fill the repository PR template with honest RED/GREEN/REGRESSION commands/results and Not verified list;
Refs #764, noFixes. Validate body, make ready, wait for exact-head checks again, hand off without merging.Planner evidence limit: source/issue/ledger/capture investigation only. Proposed RED results are predictions grounded in the named main implementations, not preserved failing test logs. Implementation must obtain and retain its own compiling behavioral RED before making the fix.
coneilen commentedon Oct 14, 2026
Plan approved (coordinator)
Approved: #764 (comment), compact passive loop-card presentation in project and overview only, with the existing project actions kept functional when the card shrinks. Boxes 2-8 remain open; box 1 is not checked until the final evidence actually supports it, and missing decoded state information remains an explicit limit.
Approved scope: graphcode-windows/src/GraphCanvas.zig (card body/layout, overview pitch/extents, owned text/elision, existing card action rectangles/tests; preserve #789 helpers); graphcode-windows/src/DesignTokens.zig (card-local metrics/colors only); graphcode-windows/src/AppFont.zig (the existing single cache, style key/accessors and growth tests, preserving every old API/default/handle lifetime); graphcode-windows/src/App.zig only the project-card action visibility/rectangles inside syncAccessibilityTo and the named never-shown regression. This is explicit approval of that out-of-lease App block.
Not approved: investigation/ui-parity-matrix.md. The coordinator owns the post-merge live-detail wording correction and will remove tokens/model tier without changing workspace-detail availability. No manifest, GraphModel, gate/runner, Sidebar, TerminalSurface, JumpPalette, NativeForms, topology, type-palette sweep, new overview actions or add-button changes. Leave historical manifest 250x106 untouched.
I verified the relied-on macOS claims: LoopCardView.swift:46-52,134-163,265-297 (250x96, fonts, title/pill, meta square and role chips); LoopCardPresentation.swift:108-141,155-180,185-241,272-281 (activity priority/pass prefix, detail/metric, ordered meta omitting default Claude Code and tokens/tier, duration); LoopStateAppearance.swift:31-53,74-121 (all words including timed SCHEDULED and hollow indicators); LoopTypeAppearance.swift:43-47 and BackendCapabilities.swift:70-79 (type/backend names). CanvasBand.swift:129-181 confirms ENTRY still exists; do not infer its removal from comments in LoopCardView. I opened the Run A final card canvas and observed its 68-percent zoom; screenshots are not intrinsic 100-percent size evidence.
Tests must first compile against existing production entry points or behavior-preserving seams and fail literal 250x96/project-and-overview, row containment, current metadata/activity, or actual font/paint assertions. Missing style/presentation helpers are not RED. Exercise both render consumers, title/pill allocation, complete long Unicode/slash-branch source strings, measured elision preserving backend/age, allocation cleanup, named action bounds/hits/UIA and positive executed counts. Preserve failed logs. Font-cache tests assert bounded growth from a populated starting point and zero second-sweep growth, never an absolute global count. No success-shaped truncated-string fallback or per-paint leaked cache-overflow font is permitted.
App coordination: C owns sidebar publication, D workspace publication, E context-menu construction. Your lease is the project-card block only; no edits to those neighboring branches. Rebase before each push and inspect every hunk. Run visual-baseline locally, exact-head CI for full regression, then accepted cross-vendor code review before one <=15-minute screenshot lease. Use Refs #764; do not promote any ledger row or claim full attention/state parity from a pill or hidden sink. Worker ib owns C:\gcs\ib, C:\gct\ib, C:\gcp\ib and real C:\gcib.
Implementation model (user-directed policy, 2026-10-14): gpt-6.1-sol, high, long_context. The actual plan has six interdependent steps across large GraphCanvas/App code: unify two different renderers, extend the process-global borrowed-font cache safely, introduce allocation-safe measured Unicode text/elision and state pills, and realign paint/hit/UIA action geometry. This is substantially more than a local card-layout fix and meets the many-interdependent-steps/shared-mechanism exception. No further scope expansion is implied. Reviewer remains claude-sonnet-5.5, high.
Launch hold (new user-directed planner-rating step): the approval/model assessment above was posted before this additional policy arrived. Scope/source review is complete, but effective model approval and implementation launch are pending the original planner's own standard/highly-complex rating and reason in its plan comment. No implementation session for this lane has launched.
Final model/launch approval: the original planner has now added highly complex with an explicit coupled-renderer/font-cache/owned-Unicode/paint-hit-UIA rationale to the plan comment. I read and accept that assessment for the approved compact-card scope. The launch hold is lifted: use gpt-6.1-sol, high, long_context, reviewer claude-sonnet-5.5, high. The denied ledger edit remains denied.
Narrow test-only scope extension (ib request): after reading both existing tests on main, approve only project/overview card rectangle and consequent overview lane/pitch literal updates in App.zig tests DPI UIA logical cards headers sidebar and direct inserts scale once and cross-project overview refresh emits both projects without changing the selected loop. Current literals encode 250x106 project and 220x86 overview cards, so preserving them would reject the intentionally approved 250x96 shared card. Keep identity/selected/card-count/refresh semantics and unrelated header/sidebar/workspace/chat expectations unchanged. Expected coordinates must remain independently calculated literals with once-only DPI conversion; do not derive the oracle from the production layout helper. No extra production scope is granted.
Additional test-only scope extension (ib): approve only beta_bounds literals in the existing App.zig test 'cross-project overview Open actions select exact projects and emit DPI scoped cards'. Read on main: old 96/144/192-DPI rectangles encode 220x86. The approved 250x96 bounds are {262,442,512,538}, {393,663,768,807}, {524,884,1024,1076}. Preserve the origin, six-card count, owner/row identities, selected flags, Open-action coordinates/outcomes and every other assertion. No additional production scope.
Coupled review/CI scope correction: approve overview pitch 260, minimum lane width 806 and content width 854, retaining 250x96 cards, positive 10px gap, row-major identities/order and consistent extents. Only the named existing App geometry literal tests may change consequently. Verify real narrow (~1028 client)/wide, zoom/pan, nonoverlap and content/action reachability; an in-client centre alone is not proof a whole button is visible. Preserve normal clipping/panning, no sticky caption or desktop widening.
Explicit new harness lease: uia-live-gate.ps1 Test-MultiProjectObservedRoster scale/height, Get-MultiProjectLaneGeometry scale/height/minimum, early lane Open action minimum and directly related explanatory comments (old 5994/6003/6034 sites); final independent oracle values 250/96/806. ValidationRunner.Tests.ps1 matching executable positive/negative narrow/wide geometry/roster cases, rejecting old 220x86/760 assumptions. Preserve all exact named rosters, owner/action identity and outcome assertions. Run the script locally. A prompt helpers, C sidebar oracle and E menu/connector oracle are disjoint and must survive rebase.
Metadata overflow policy: isolate metadata failure from title/pill/live/detail painting. Prefer measured head/middle-ellipsis/tail; if that minimum cannot fit, use one measured branch ellipsis only when it plus its extra separator fits. If no branch fragment fits but fixed type/backend/age do, omit only branch and its separator as explicitly tested/documented visual elision while retaining complete owned source. If fixed fields do not fit, log the specific error and draw a bounded metadata-unavailable marker only, not a blank card or clipped backend/age. Test exact width boundaries and the reported Composite/Copilot CLI/1h5m/main case, Unicode/surrogate cuts, allocation failures and action paint. Existing subgraphNodeCount reuse and honest build-log provenance correction stay in scope.
Reviewed actual integration failure 38592395839/job115950535486: early lane Open target used the stale floor and failed before later ratio checks. One change-caused CI failure and one substantive reviewer rejection (two findings), corrected in place; no escalation.
Additional exact early Worktrees coordinate lease: approve the old6068 laneWorktreesScreenX assignment from freshly read graph bounds using Left+24+Max(806,Width-48)-45, not Right-69 (which assumes the non-minimum branch). Matching ValidationRunner cases must extract/evaluate the actual production assignment AST for narrow and wide bounds, reject old959 as the Open target in the1028-client case, and validate the1005 Worktrees point against actual/visible control geometry. Keep all outcome/ownership/count/clip checks and actual-size assumptions; no desktop widening or broad coordinate replacement. Audit remaining overview caption/card consumers for stale220x86/760/right-edge assumptions and document untouched valid sites before final review. This conditional source finding is not an additional CI failure without an actual failed run.
Share compact loop-card presentation across project and overview (#814)
coneilen commentedon Oct 15, 2026
Merged the compact-card code slice in #814 as 4fafbfb after accepted code/narrow interaction review, current exact-head CI and fresh ready-event DCO. The operator explicitly moved deferred-visual merge authorization to now because #826 blocks captures. Visual verification is NotExecuted for that reason; no AFTER capture, paired-image acceptance or visual-parity claim is made. All acceptance boxes remain unchecked and #764 stays open. The original inherited journal sharing-violation CI failure and one successful targeted same-head rerun are retained in the PR. This merge is not current binary/capture admission: the old fresh a44/base65194 builds are historical only. Visuals will be reviewed in a later coordinated batch once the tooling is qualified; no ledger row is promoted by this merge.
Document bounded parity evidence and execution admission (#828)