Skip to content

feat(front-2): full design-parity handoff — Gray UI stack, all surfaces, testing pass - #806

Merged
radandevist merged 327 commits into
developfrom
feat/front-2-full-parity-handoff
Jul 15, 2026
Merged

feat(front-2): full design-parity handoff — Gray UI stack, all surfaces, testing pass#806
radandevist merged 327 commits into
developfrom
feat/front-2-full-parity-handoff

Conversation

@radandevist

Copy link
Copy Markdown
Collaborator

Closes #805.

The complete front-2 design-parity handoff: 159 commits, 325 files, +54k/−5.4k. Supersedes the 5-PR stack plan (#804 closed unmerged); lands as one unit. Every round below was gate-verified green when it closed (build + vitest + full docker-Playwright e2e); the branch tip stands at 156/156 e2e, 693/693 vitest.

Reviewer note on scope: not front-only — 49 files under apps/api (file storage + upload endpoint, org-profile fields, tenant detail counts/level filter, bulk remove + CSV export, throttled last-activity) plus small client-ts/shared-ts changes rode along because the design work kept needing backend support.

Act 1 — Design-system foundation

Gray UI token layer (--publy-*, both themes), design-invariant guard tests, route metadata, rebuilt authenticated shell, product UI primitives, restyled data-table foundation; staff-admin tokens + shell (handoff tasks 1–2).

Act 2 — The Gray UI pivot

  • Stack swap (81e5a70f): HeroUI removed entirely; ~27 in-house primitives in src/components/ui/ on @base-ui/react + CVA, @tabler/icons-react; every route family migrated; design-system guard script wired into pnpm test.
  • Visual parity passes: table system to the Gray UI spec; shell/cards/chips/detail/list parity; responsive passes.
  • Full-parity handoff foundations (141475e3…): nav-registry decision, design guards, app shell, table + overlay/form foundations; all 7 latent e2e failures cleared (a054182f).
  • Staff screens (handoff 2c/2d/2g–2i): user detail, user edit, profiles, invitations — with review remediations.
  • Owner design-feedback batch: dark palette + instant theme switch, card/ring treatment, table column geometry + truncation, error views & empty states redesign, deep-linkable detail tabs, malformed-id→404 ruling, conventions codified in the repo guide.

Act 3 — Slices, enrichment, testing pass

  • Feature-parity status matrix + two-slice scope decision (current, not permanent).
  • Auth slice: split-brand auth layout; login/signup/verify-email/reset-password; accept-invitation with its 5 branches; topbar user menu; cross-tab logout/login/theme/locale sync; language switcher; tenant portal org picker.
  • Tenants design-002 round: tenant detail rebuilt with rail-only routes; profiles/invitations/users tabs rebuilt; create-tenant to full fidelity; invite/profile forms in drawers; API detail counts, level filter, bulk remove + CSV export.
  • Enrichment round: org-profile fields (API + forms), throttled last-activity tracking, tab-refocus stampede fix, floating selection bar, file uploads (local-disk storage + staff upload endpoint + real logo upload field, logo in create body).
  • Owner testing pass (11 findings + 2 rulings): uploaded-logo URLs resolved against the API origin; single shell scroller + form action-bar/aside layout model; menu/select/outline chrome rulings; profile cards to design fidelity; tenants status filter + all-levels entry; Pending tenant status exposed; long-away blank-page fix — the ssr:false authed layout had a null pending fallback, now ships a static shell skeleton in the SSR HTML itself (cold-boot-stability.spec.ts guards it).

Deploy prerequisite

Uploads persist to local disk — production needs a Dokploy persistent volume at /app/.artifacts/storage before this deploys, or uploaded logos vanish on redeploy.

Merge-strategy note

A squash collapses 159 commits into one on develop. If you want the per-round history browsable from develop, use a merge commit for this PR instead of the usual squash.

🤖 Generated with Claude Code

radandevist and others added 30 commits July 10, 2026 08:55
…eviation

SPEC's 2b/3a grids assume columns the API does not return (Role/Profiles/2FA/
Last-active; Plan/Owner/Created). Profiles and invitations use the literal SPEC
pixel values; staff-users and tenants keep the widths that have a SPEC
counterpart and let the longest free-text column absorb the remainder.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eparator

A single '*' in a Playwright glob compiles to ([^/]*) and stops at '/'; only
'**' becomes (.*). A trailing single star therefore matches the collection
endpoint but never its sub-paths, so the handler is dead code and the request
escapes to the real API while the spec still passes. This silently defeated
three specs across two packets despite being documented in the trap list.

Scan e2e/ (previously unscanned) and add no-single-star-route-glob. Existing
sites are annotated with a reason rather than widened, because widening changes
what a mock intercepts and must be argued per spec. Suppression requires a
reason after the rule id, so it cannot be added thoughtlessly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… paragraph

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
'demo-user-id' is not a GUID, so the API answers 400 malformed-id and the
route renders the error view — which has no .publy-detail-grid. The other
shell specs get away with that id because they only assert on the panel.

The assertions were already right; only the navigation was wrong.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eedback batch

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
P13 sized the icon container but the svg glyph kept its call-site size-7
(28px), which wins over a layered rule. An un-layered .publy-state-icon svg
rule (100% of the 40/48px box) beats every Tailwind layer, valorizing the
icon as intended without editing 61 call sites.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…earch

50 worktrees under .worktrees/ (45 with their own node_modules) were being
watched with no excludes configured, ballooning VS Code's remote fileWatcher
process to ~4.4GB RSS.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
files.exclude hides folders from the tree entirely, not just from search
and the watcher — that broke browsing into worktrees and scratch notes.
They stay out of files.watcherExclude/search.exclude, so no RAM regression.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ctive actions out of headers, consistent back-links
…ions guide

Captures the standing decisions from the front-2 parity review (borders,
radius, destructive-action placement, error/empty states, malformed-id -> 404,
back-links, data honesty, navigation) so future work inherits them by default.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…default

The default-size (36px) button radius is 12px under the owner-ratified per-size
scale (xs 8 / sm 10 / default 12 / lg 14). The p15 radius change updated the
artboard-assertions but missed this e2e pin; the button renders correctly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two files under staff-users/$userId/ were unformatted since wave 5 (71296ed);
the CI 'Check formatting' step (pnpm format = oxfmt --check) fails on them.
Formatting-only (line-wrapping); typecheck 0, affected tests 22/22.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jul 15, 2026
.dump/orchestration/W4-API-report.md and W4-API.STATUS were force-added past
the .dump gitignore in wave 4; they are orchestration scratch and must not land
on develop. No product code affected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@radandevist
radandevist merged commit 2714a4c into develop Jul 15, 2026
7 checks passed
@radandevist
radandevist deleted the feat/front-2-full-parity-handoff branch July 15, 2026 03:47
radandevist added a commit that referenced this pull request Jul 17, 2026
## Why
Epic A (#194) had no authoritative design for the jobs/worker infrastructure. #806 shipped a typed invitation-email outbox; #632 asked for the generic design that supersedes it. This document is that reference: `APP_ROLE` hosting, a single generic `job_queue`, the email fold, and the build order for #633#636.

## What this is
`docs/implementation-plans/jobs-worker-infrastructure.md` — the authoritative architecture reference for PublyApp's background jobs and worker.

Ratified decisions:
- **D1** — role-based hosting: one codebase, one image, `APP_ROLE=api|worker|all`.
- **D2** (owner revision) — emails are **jobs on the generic `job_queue`**; delivery history lives in `email_log` from day one. Supersedes the two-lane/typed-outbox ruling; `invitation_email_outbox` folds via expand/contract.
- **D3** — pure Postgres, no broker.

## How it was reviewed
Authored, then put through an **adversarial merge-challenge loop** against GPT-5.6-sol at high effort, on the owner's instruction. **10 rounds**, ~80 findings, remediated by Claude Opus 4.8 (cross-family reviewer discipline). Findings by round: 17 → 12 → 9 → 7 → 3 → 5 → 3 → 3 → 4 → 7. All 10 review records are committed under `docs/reviews/jobs-infra-design-challenge/` — the full adversarial history, not a summary.

The loop caught design defects that would otherwise have shipped, including: unfenced stale schedule triggers surviving a cron edit (`schedule_epoch`); an expiry sweep that destroyed the evidence of its own expiry; a retention job that deleted the row making another retention job safe; and repeated cases of a claimed property being stronger than the mechanism enforcing it.

## Status — read this before treating any section as settled
**The loop did NOT end in `CHALLENGE: MERGE-READY`.** It ended by owner decision after round 10, with round 10's remediation **unvalidated** — every prior round was checked by the next, and that repeatedly mattered (round 8's headline fix graded *Mis-absorbed*; round 9 found two blockers inside round 8's new mechanisms). The status block and §11 record this honestly.

§11 **"Known open items"** lists what round 10 could not close, each filed as a GitHub issue against the phase that will implement it. **O6–O31** are author-decided and remain pending owner ratification.

A five-round-old fabrication was found during the final round and corrected: the `audit_logs` INSERT promised for engine transitions named four columns the shipped table does not have, against a `user_id NOT NULL` FK the engine cannot satisfy. Every "immutable AuditLog entry" specified for an engine transition since round 5 was unbuildable. Engine evidence now writes `job_dead_letter_events` (O30).

## Doc-vs-code
The code on #853/#854/#857/#858 implements an earlier state of this design. The document is deliberately ahead of it and marks the gaps inline as captain-alignment items; a gap analysis against this final version follows separately. Where doc and code disagree, **the doc is the intent and the code is the backlog** — except where an item is marked a suspected live defect, which is a bug.

## Verification
Doc-only change. No code, schema, or test touched. Cross-references resolved, fences balanced, review records byte-identical to their sources.

Closes #632
radandevist added a commit that referenced this pull request Aug 25, 2026
…#823)

The static class-string simulator (~900 lines) could not model @layer
precedence, so it kept certifying a ring that a non-layered rule had
already beaten in every real browser — the exact blindness four
reviewers converged on during the #806 rounds 6 & 7.

What stays under vitest (no cascade model needed):
- --publy-focus-ring >= 3:1 against surface tokens, light AND dark themes
- ui-F1 choice-chip pre-fix regression proof
- fail-closed tripwires (inline ring styles, runtime string composition)
- coverage tripwires (button/badge variant keys pinned, routes/ consumer
  discovery)

The rendered-cascade half of the contract moves to the Playwright spec
added in the next commit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Epic: front-2 full design-parity handoff (Gray UI)

1 participant