From 4d8a06beba107b114c7d87878f90c1cc6ddce55e Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Sat, 31 Oct 2026 04:23:56 -0700 Subject: [PATCH 1/5] refactor(board): route task status and priority colour through tokens (TASK-698) Board priority and ownership dots read --v2-prio-* and --v2-status-* tokens instead of literal theme values. Values are unchanged (mono today), so the rendered board is identical. The D215 colour choice becomes a token value swap, not a rework. Layout-invariant pins move with the rules. Written by Rivet, a Commonly agent. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: rivet Agent-Model: claude/claude-haiku-5-5/default --- .../v2/__tests__/v2-layout-invariants.test.ts | 15 +++++++++----- frontend/src/v2/v2.css | 20 +++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/frontend/src/v2/__tests__/v2-layout-invariants.test.ts b/frontend/src/v2/__tests__/v2-layout-invariants.test.ts index f4279325a4..682ce51060 100644 --- a/frontend/src/v2/__tests__/v2-layout-invariants.test.ts +++ b/frontend/src/v2/__tests__/v2-layout-invariants.test.ts @@ -5041,16 +5041,21 @@ describe('task priority and lease signals (TASK-443)', () => { expect(badge).toContain('var(--v2-font-mono)'); expect(badge).toContain('border-radius: 4px'); expect(badge).toContain('background: none'); + expect(badge).toContain('color: var(--v2-prio-ink)'); + expect(badge).toContain('border: 1px solid var(--v2-prio-edge)'); const urgent = ruleBody(css, '.v2-board__priority--p0'); - expect(urgent).toContain('border-color: var(--v2-text-primary)'); - expect(urgent).toContain('color: var(--v2-text-primary)'); + expect(urgent).toContain('border-color: var(--v2-prio-p0-ink)'); + expect(urgent).toContain('color: var(--v2-prio-p0-ink)'); + // Status and priority colour are tokens, so the D215 colour choice is a value swap. + expect(css).toMatch(/--v2-prio-p0-ink:\s*var\(--v2-text-primary\)/); + expect(css).toMatch(/--v2-status-live:\s*var\(--v2-accent\)/); expect(urgent).not.toMatch(/background/); }); test('live, unclaimed and expired ownership retain distinct dots', () => { - expect(ruleBody(css, '.v2-board__owner-dot--live')).toContain('background: var(--v2-accent)'); - expect(ruleBody(css, '.v2-board__owner-dot--not-claimed')).toContain('border: 1px dashed var(--v2-border-strong)'); + expect(ruleBody(css, '.v2-board__owner-dot--live')).toContain('background: var(--v2-status-live)'); + expect(ruleBody(css, '.v2-board__owner-dot--not-claimed')).toContain('border: 1px dashed var(--v2-status-idle)'); const expired = ruleBody(css, '.v2-board__owner-dot--expired'); - expect(expired).toContain('border: 1px solid var(--v2-border-strong)'); + expect(expired).toContain('border: 1px solid var(--v2-status-idle)'); expect(expired).toContain('background: none'); }); }); diff --git a/frontend/src/v2/v2.css b/frontend/src/v2/v2.css index 3f20c14957..e2a3641d40 100644 --- a/frontend/src/v2/v2.css +++ b/frontend/src/v2/v2.css @@ -112,6 +112,14 @@ body.modern-ui.v2-canvas { --v2-danger: #ef4444; --v2-danger-text: #b91c1c; --v2-danger-soft: rgba(239, 68, 68, 0.10); + /* TASK-687/698: board status and priority colour. Mono today; the D215 colour + option (A mono or B colour) is a value swap here, not a rework. These resolve + through the theme's own text and border tokens, so dark needs no extra block. */ + --v2-prio-p0-ink: var(--v2-text-primary); + --v2-prio-ink: var(--v2-text-secondary); + --v2-prio-edge: var(--v2-border); + --v2-status-live: var(--v2-accent); + --v2-status-idle: var(--v2-border-strong); /* Agent role colors */ --v2-pink: #f472b6; @@ -13522,19 +13530,19 @@ body.modern-ui.v2-canvas { .v2-board__priority { display: inline-block; padding: 0 5px; - border: 1px solid var(--v2-border); + border: 1px solid var(--v2-prio-edge); border-radius: 4px; font: 500 11px/16px var(--v2-font-mono); - color: var(--v2-text-secondary); + color: var(--v2-prio-ink); background: none; } -.v2-board__priority--p0 { border-color: var(--v2-text-primary); color: var(--v2-text-primary); } +.v2-board__priority--p0 { border-color: var(--v2-prio-p0-ink); color: var(--v2-prio-p0-ink); } .v2-board__card-title { font-size: 14px; line-height: 20px; } .v2-board__owner-line { display: flex; align-items: center; gap: 6px; font: 500 11px/16px var(--v2-font-mono); color: var(--v2-text-secondary); } .v2-board__owner-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; } -.v2-board__owner-dot--live { background: var(--v2-accent); } -.v2-board__owner-dot--not-claimed { border: 1px dashed var(--v2-border-strong); } -.v2-board__owner-dot--expired { border: 1px solid var(--v2-border-strong); background: none; } +.v2-board__owner-dot--live { background: var(--v2-status-live); } +.v2-board__owner-dot--not-claimed { border: 1px dashed var(--v2-status-idle); } +.v2-board__owner-dot--expired { border: 1px solid var(--v2-status-idle); background: none; } .v2-board__card--done { border-color: var(--v2-border-soft); } .v2-board__card--done .v2-board__card-title { color: var(--v2-text-secondary); } .v2-root button.v2-board__card-move { min-height: 32px; padding: 0 10px; border-radius: 4px; } From 12f608b712ae3e0c25f7a1e66513926c9f83ded0 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Sat, 31 Oct 2026 05:04:53 -0700 Subject: [PATCH 2/5] style(board): B-lite status and priority colour tokens (TASK-687/698) Blocked and P0 go red, in progress stays cobalt, P1/P2/pending/done stay grey with no green. Blocked cards get a 3px left edge; P0 is the only filled badge. The three faint greys move to AA values (light pending ring and P2 label #667085, dark P2 #8b94a5). Light and dark values sit in the base and both dark blocks of v2.css. Co-Authored-By: Claude Haiku 5.5 Co-authored-by: rivet Agent-Model: claude/claude-haiku-5-5/default --- .../v2/__tests__/v2-layout-invariants.test.ts | 17 +++++++--- frontend/src/v2/components/V2PodBoard.tsx | 6 ++-- frontend/src/v2/v2.css | 33 +++++++++++++++---- 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/frontend/src/v2/__tests__/v2-layout-invariants.test.ts b/frontend/src/v2/__tests__/v2-layout-invariants.test.ts index 682ce51060..2c3d199226 100644 --- a/frontend/src/v2/__tests__/v2-layout-invariants.test.ts +++ b/frontend/src/v2/__tests__/v2-layout-invariants.test.ts @@ -5043,17 +5043,24 @@ describe('task priority and lease signals (TASK-443)', () => { expect(badge).toContain('background: none'); expect(badge).toContain('color: var(--v2-prio-ink)'); expect(badge).toContain('border: 1px solid var(--v2-prio-edge)'); + // P0 is the only filled badge: red fill, white label (B-lite, Sam 10-31). const urgent = ruleBody(css, '.v2-board__priority--p0'); - expect(urgent).toContain('border-color: var(--v2-prio-p0-ink)'); - expect(urgent).toContain('color: var(--v2-prio-p0-ink)'); + expect(urgent).toContain('background: var(--v2-prio-p0-bg)'); + expect(urgent).toContain('color: var(--v2-prio-p0-fg)'); // Status and priority colour are tokens, so the D215 colour choice is a value swap. - expect(css).toMatch(/--v2-prio-p0-ink:\s*var\(--v2-text-primary\)/); + expect(css).toMatch(/--v2-prio-p0-bg:\s*#b42318/); + expect(css).toMatch(/--v2-prio-p2-fg:\s*#667085/); expect(css).toMatch(/--v2-status-live:\s*var\(--v2-accent\)/); - expect(urgent).not.toMatch(/background/); + expect(ruleBody(css, '.v2-board__priority--p2')).toContain('color: var(--v2-prio-p2-fg)'); + }); + test('blocked is red with a thin edge on blocked cards only', () => { + expect(css).toMatch(/--v2-status-blocked:\s*#d92d20/); + expect(ruleBody(css, '.v2-board__card--blocked')).toContain('box-shadow: inset 3px 0 0 var(--v2-status-blocked-edge)'); + expect(ruleBody(css, '.v2-board__col--blocked .v2-board__col-name')).toContain('color: var(--v2-status-blocked)'); }); test('live, unclaimed and expired ownership retain distinct dots', () => { expect(ruleBody(css, '.v2-board__owner-dot--live')).toContain('background: var(--v2-status-live)'); - expect(ruleBody(css, '.v2-board__owner-dot--not-claimed')).toContain('border: 1px dashed var(--v2-status-idle)'); + expect(ruleBody(css, '.v2-board__owner-dot--not-claimed')).toContain('border: 1px dashed var(--v2-status-pending)'); const expired = ruleBody(css, '.v2-board__owner-dot--expired'); expect(expired).toContain('border: 1px solid var(--v2-status-idle)'); expect(expired).toContain('background: none'); diff --git a/frontend/src/v2/components/V2PodBoard.tsx b/frontend/src/v2/components/V2PodBoard.tsx index f9ac01575e..477e7a54fa 100644 --- a/frontend/src/v2/components/V2PodBoard.tsx +++ b/frontend/src/v2/components/V2PodBoard.tsx @@ -735,7 +735,7 @@ const V2PodBoard: React.FC = () => { {COLUMNS.map((col) => { const items = columnTasks.get(col.key) || []; return ( -
+
{t(col.labelKey)} {items.length} @@ -744,7 +744,7 @@ const V2PodBoard: React.FC = () => {
{t(col.emptyKey)}
)} {items.map((task) => ( -
+