Add Loop UI design system tokens and canonical state mapping (#194) - #525
Add Loop UI design system tokens and canonical state mapping (#194)#525mberrys wants to merge 5 commits into
Conversation
Adds pdfquick::tokens (LoopLibQuick/sources/looptokens.h/.cpp): semantic spacing and colour-role tokens with dark/light/high-contrast values, each foreground/background pair WCAG contrast-checked. Adds resolveStateVisual() (loopstatevisual.h/.cpp), the canonical finding/check presentation mapping issue #194 asks for, with a table-driven test (UnitTestsLoopStateVisual) asserting an incomplete check and an actively-waived finding never resolve to the passed treatment. Documents both in docs/LOOP_DESIGN_SYSTEM.md, including why this uses the repo's current Loop/Quick naming rather than the issue's stale pre-rebrand Pdf4QtLibGui/Loupe paths, and what remains open (component implementations land with their consuming surfaces #193, #195, #196, #127, which are not yet implemented). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NxoABBuEB3mYqr8QyA6KuB
scripts/ci/check_loop_identity.py fails CI on any tracked text file containing the pre-rebrand product name outside its historical-evidence allowlist. The "Naming note" section quoted that name three times while explaining why this doc uses current naming instead of issue #194's stale paths; reword it to make the same point without the literal token. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NxoABBuEB3mYqr8QyA6KuB
|
3 were mine — The other 5 are pre-existing on Generated by Claude Code |
Adding UnitTestsLoopStateVisual to UnitTests/CMakeLists.txt bumped the project-wide CMake target count the Phase 5 Widgets inventory tracks (its generator enumerates every target to prove widgets-linkage status, not just widgets-related ones). Regenerate docs/generated/phase5-widgets-inventory.json via scripts/generate_phase5_widgets_evidence.py --write (new target's widgets_linkage is "none", as expected) and update the test's hardcoded target count (70 -> 71) to match. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NxoABBuEB3mYqr8QyA6KuB
|
Follow-up on the Loop identity findings: fixed the 5 remaining legacy product-token occurrences so this PR is green on its own (base dev is still red at those paths).\n\n- .github/workflows/reusable-linux.yml:79 and reusable-windows.yml:92: working-directory loupe -> loop. This was also the agent-fast failure (No such file or directory .../loupe).\n- scripts/budget_exhaustion/generate_corpus.py:14, UnitTests/tst_budgetexhaustiontest.cpp:133, UnitTests/testdata/budget-exhaustion/manifest.json:190: schema_kind loupe-processing-budget-exhaustion-corpus -> loop-processing-budget-exhaustion-corpus (manifest regenerated via generate_corpus.py, --check passes locally).\n\nVerified locally: check_loop_identity.contract_findings() == [], check_source_integrity.py passes, generate_corpus.py --check passes, check-change.py dry-run passes with head-branch cc/hopeful-galileo-k8b2cu. |
agent-fast's clang-tidy step runs on every changed C++ file regardless of module classification, but the cmake --build step that generates each test's AUTOMOC .moc file only runs for targets selected by classify()/selected_values() against agent-policy.json's module_boundaries paths. UnitTestsBudgetExhaustion was already listed in core's `tests`, but its source file, UnitTests/tst_budgetexhaustiontest.cpp, was missing from core's `paths` glob list, so a change touching only that file never classified as "core" and the target was never built before clang-tidy ran on it standalone -- producing "tst_budgetexhaustiontest.moc file not found". Surfaced by 0aa0d4c's one-line fix to that file. Add the missing path entry so the target builds first, as it does for every other core test file already listed there. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NxoABBuEB3mYqr8QyA6KuB
|
Root cause: Fixed and pushed (ed178bd): added Generated by Claude Code |
Summary
Implements the load-bearing pieces of #194 ("Define and implement the Loupe UI design system"):
pdfquick::tokens(LoopLibQuick/sources/looptokens.h/.cpp) — semantic spacing tokens (4px grid) and aColorRoleenum resolved perLoopTheme(Dark/Light/HighContrast). No call site hardcodes a colour; every foreground/background pair is WCAG contrast-checked indocs/LOOP_DESIGN_SYSTEM.md.resolveStateVisual()(LoopLibQuick/sources/loopstatevisual.h/.cpp) — the single canonical finding/check presentation mapping the issue calls for, consumed by(finding, status, decision). Implements the two invariants [0.2.1] Define and implement the Loupe UI design system #194 is actually about: an incomplete check never renders as a pass, and an actively-waived finding never renders as a pass.docs/LOOP_DESIGN_SYSTEM.md— the token table with contrast figures, the canonical state table, and current adoption state.UnitTests/tst_loopstatevisualtest.cpp(UnitTestsLoopStateVisual) — table-driven over severities, check statuses, waive/non-waive decisions, stale vs. active decisions, and out-of-schema inputs; explicitly asserts the two never-passed invariants.Scope decisions (read before reviewing)
The issue text is stale. #194 (and #193/#195/#196/#127) were written against a pre-rebrand snapshot:
Pdf4QtLibGui/loupe/…andPdf4QtEditorPlugins/…no longer exist (Widgets GUI retired, Loupe → Loop rebrand). This PR implements against the repo's actual current layout —pdfquick::tokensinLoopLibQuick,docs/LOOP_DESIGN_SYSTEM.md— and explains the translation in the doc's "Naming note".docs/quick-design-tokens.json(issue #178) already defined a provisional dark-theme contract for the Quick canvas; this extends it to a full role set and a light theme rather than duplicating it.Components are not included. Issue §3's finding card / inspector row / overlay / progress / empty-state / error-state / confirm implementations have no consuming surface yet — #193, #195, #196, and #127 are all still open. Building fixtures with nothing to host them would be speculative;
docs/LOOP_DESIGN_SYSTEM.mdrecords this and says each should land with its consuming surface, built on the tokens and mapping here.CanvasPaletteis left as-is. It already reuses one colour for both focus ring and warning severity, which the newColorRoleset intentionally separates (FocusRingvs.SeverityWarning). Re-pointing the canvas overlay at these tokens is canvas-specific work with its own visual-regression needs, tracked as adoption work rather than done here.Build/test verification is incomplete. This environment has no configured Qt 6.11 CMake build (
/home/user/loop/builddoes not exist) and provisioning one is outside this session's autonomous budget (configure_or_reconfigureand toolchain changes require approval). I ran everything that doesn't need a configured build:clang-format --dry-run --Werroron all touched/added C++ files — clean.scripts/ci/check_source_integrity.py— pass.scripts/generate-architecture-catalogs.py --check— pass (regenerated to addUnitTestsLoopStateVisual).scripts/agent/generate-adapters.py— pass, no drift beyondagent-policy.jsonitself.cmake --build/ctest/clang-tidy-18for the newUnitTestsLoopStateVisualtarget could not be run here and need CI or a maintainer to confirm the build. I read every relevant existing source (PreflightFinding/PreflightCheckStatus/PreflightDecisioninLoopLibCore,CanvasPalette, theLoopLibQuick/ProductQuickAccessibilitySmokeCMake linkage) to keep the new code consistent, but flagging this honestly rather than claiming a green build I couldn't produce.One build-graph note:
UnitTests/CMakeLists.txtcurrently has no target linkingLoopLibQuickat all (pre-existing —tst_quickcanvastest.cppetc. exist as source but aren't wired to any target, and linking the SHAREDLoopLibQuicklibrary as a plainadd_executableneedsqt_add_executable()+qt_import_qml_plugins()perProductQuickAccessibilitySmoke/CMakeLists.txt, which no existing UnitTests target does). Sincelooptokens.cpp/loopstatevisual.cpponly needQColor(no Qml/Quick), the new test compiles those two translation units directly intoUnitTestsLoopStateVisualinstead of linking the shared library, avoiding that untested link edge.UnitTests/CMakeLists.txtis a protected path (flaggedrisk: highbycheck-change.py) for this reason — the change is additive and follows the existing sibling-target pattern otherwise.Test plan
clang-format --dry-run --Werroron all new/changed filesscripts/ci/check_source_integrity.pyscripts/generate-architecture-catalogs.py --checkscripts/agent/generate-adapters.pychanges/cc-hopeful-galileo-k8b2cu.md)cmake --build+ctest -R UnitTestsLoopStateVisual(needs a configured Qt 6.11 build — not available in this session)🤖 Generated with Claude Code
https://claude.ai/code/session_01NxoABBuEB3mYqr8QyA6KuB
Generated by Claude Code