# Phase 17: Chat & Planning — Specification

**Created:** 2026-05-17
**Ambiguity score:** 0.13 (gate: ≤ 0.20)
**Requirements:** 6 locked

## Goal

Restyle the discussion view and planning page using design system components so both surfaces are visually consistent with the Phase 15–16 restyled tablos, with own-vs-others message alignment and date-grouped planning events.

## Background

Phases 15–16 restyled the dashboard and tablo-detail surfaces using the design system (`ui.Card`, `.overview-section`, `.project-card`, CSS tokens). The discussion view (`backend/templates/discussion.templ`) and planning page (`backend/templates/planning.templ`) were not touched and remain visually inconsistent: they use raw inline Tailwind classes with no card surfaces or overview-section structure.

Current gaps:
- **Discussion**: `DiscussionMessageRow` renders identical flat rows for all messages. `DiscussionMessageView` has no `IsOwn` field. The SSE stream handler (`DiscussionMessageFromRow`) also omits own-user context.
- **Planning**: `PlanningPage` uses a raw `<ul>` list with no overview-section heading. `PlanningEventRow` has `DateLabel string` but no day-separator logic. Events are not grouped under date headers.

## Requirements

1. **Discussion message alignment**: Own messages render right-aligned with a distinct background; others render left-aligned.
   - Current: All `DiscussionMessageRow` items are identical flat rows — no user-context field exists in `DiscussionMessageView`
   - Target: `DiscussionMessageView` gains an `IsOwn bool` field; `DiscussionMessagesFromRows` accepts a current-user ID parameter to set it; the template renders own messages in a right-aligned bubble (e.g. `bg-blue-50`/`bg-slate-50`) and others left-aligned
   - Acceptance: Viewing a discussion where the signed-in user sent some messages shows own messages right-aligned with a different background; other users' messages are left-aligned

2. **SSE stream own-message alignment**: New messages posted via SSE also render right-aligned for the posting user.
   - Current: `DiscussionMessageFromRow` (used by the stream handler) has no user context; new messages stream without alignment differentiation
   - Target: The SSE/stream path that renders a new `DiscussionMessageRow` also sets `IsOwn = true` for the posting user's message (the stream handler already knows the author)
   - Acceptance: Posting a new message via the composer results in the new message row appearing right-aligned in the thread immediately (without reload)

3. **Discussion card surface**: The message list container uses a card-style surface consistent with Phase 16 tab panels.
   - Current: Messages container is a plain `div.rounded.border.border-slate-200.bg-white`
   - Target: Messages container uses the `.ui-card` CSS class (or equivalent design token surface) so border-radius, shadow, and background match the Phase 16 card surfaces
   - Acceptance: The discussion message container visually matches the card surfaces in the files and events tabs of the tablo-detail page

4. **Planning overview-section heading**: The planning page header uses the `.overview-section` + `.overview-section-heading` layout classes.
   - Current: Page header is a plain `<div class="space-y-6">` + nested flex div with inline Tailwind classes
   - Target: The "Planning" heading and date-range label are wrapped in `.overview-section` / `.overview-section-heading` elements, matching the style used in `tablos.templ` and the detail page
   - Acceptance: The Planning page heading visually matches the heading style on the dashboard and tablo-detail pages

5. **Planning day separators**: Events are grouped under date-separator headers rather than showing the date as a column in each row.
   - Current: Events render as a flat list; `DateLabel` is a column inside each `<li>`
   - Target: A `PlanningShowDaySeparator` helper compares consecutive event `DateLabel` strings; where the date changes, a day-separator element is rendered above the first event for that date; `DateLabel` is removed from the event row body (it's now the separator header)
   - Acceptance: A 14-day window with events on 3 different dates renders 3 date separator headers, each followed by its events; events on the same date appear under one separator

6. **Handler tests pass unchanged**: All existing Go tests for discussion and planning handlers continue to pass without modification.
   - Current: `go test ./...` passes; handler tests reference `DiscussionMessagesFromRows`, `NewPlanningAgenda`, and related functions
   - Target: Any function signature changes (e.g. adding `currentUserID uuid.UUID` to `DiscussionMessagesFromRows`) are reflected at all call sites; no test is deleted or skipped to make tests pass
   - Acceptance: `go test ./... -count=1` exits 0 after all Phase 17 changes

## Boundaries

**In scope:**
- `DiscussionMessageView` — add `IsOwn bool` field
- `DiscussionMessagesFromRows` — add `currentUserID uuid.UUID` parameter; set `IsOwn` by comparing to each message's author
- `DiscussionMessageFromRow` — add `isOwn bool` parameter for the SSE path
- `DiscussionTabFragment` / `DiscussionMessageRow` — restyle as right/left-aligned chat bubbles; message container adopts `.ui-card` surface
- `PlanningPage` / `PlanningEventListItem` — adopt `.overview-section` heading; add `PlanningShowDaySeparator` helper; add day-separator element; remove `DateLabel` from event row body
- All call sites for changed function signatures (handlers, test files where necessary to compile)
- Browser walkthrough confirming visual consistency on both pages

**Out of scope:**
- Avatars or profile pictures in message rows — not in v3.0 requirements
- Message reactions or reply threading — not in v3.0 requirements
- Planning page sorting or filtering controls — navigation controls already exist; no new controls
- New database schema, migrations, or sqlc queries — restyling only
- New routes or HTTP handlers — no new endpoints

## Constraints

- All Go handler tests must pass unchanged (or with compile-only call-site updates, no logic changes)
- `PlanningShowDaySeparator` uses string comparison on `DateLabel` — no `Date time.Time` field added to `PlanningEventRow`
- Design tokens and CSS classes from the existing design system only — no new CSS files or utility classes introduced
- No new JavaScript added — HTMX + existing Sortable.js only

## Acceptance Criteria

- [ ] Discussion messages from the signed-in user render right-aligned with a distinct background color
- [ ] Discussion messages from other users render left-aligned
- [ ] Posting a new message via the composer renders the new row right-aligned immediately (SSE path)
- [ ] Discussion message container uses `.ui-card` surface (border-radius + shadow match Phase 16 tab panels)
- [ ] Planning page heading uses `.overview-section` / `.overview-section-heading` layout classes
- [ ] Planning events in a 14-day window are grouped under date-separator headers (not shown as a date column in each row)
- [ ] `go test ./... -count=1` exits 0 after all changes
- [ ] Browser walkthrough: both discussion and planning views look visually consistent with Phase 15–16 restyled surfaces

## Ambiguity Report

| Dimension          | Score | Min  | Status | Notes                                              |
|--------------------|-------|------|--------|----------------------------------------------------|
| Goal Clarity       | 0.92  | 0.75 | ✓      | Chat bubble style and planning grouping locked     |
| Boundary Clarity   | 0.90  | 0.70 | ✓      | Explicit in/out-of-scope confirmed by user         |
| Constraint Clarity | 0.80  | 0.65 | ✓      | Test constraint, string-compare grouping, no new CSS|
| Acceptance Criteria| 0.82  | 0.70 | ✓      | 8 pass/fail checkboxes                             |
| **Ambiguity**      | 0.13  | ≤0.20| ✓      |                                                    |

## Interview Log

| Round | Perspective      | Question summary                          | Decision locked                                                   |
|-------|------------------|-------------------------------------------|-------------------------------------------------------------------|
| 1     | Researcher       | How to differentiate own vs. others?      | Alignment (own right, others left) — classic chat bubble layout   |
| 1     | Researcher       | Event grouping on planning page?          | Group by date with day separators                                 |
| 2     | Researcher       | How to thread own-message detection?      | Add `IsOwn bool` to `DiscussionMessageView`                       |
| 2     | Simplifier       | String comparison vs. Date field for planning? | String comparison on DateLabel — no data model field added  |
| 3     | Boundary Keeper  | Does SSE stream path need own-alignment?  | Yes — stream handler also sets IsOwn for posting user             |
| 3     | Boundary Keeper  | What's explicitly out of scope?           | Avatars, reactions/threading, planning filter controls excluded   |

---

*Phase: 17-chat-planning*
*Spec created: 2026-05-17*
*Next step: /gsd-discuss-phase 17 — implementation decisions (bubble CSS, card wrapping, separator markup)*
