spec(phase-17): add SPEC.md for Chat & Planning — 6 requirements (#2213)

This commit is contained in:
Arthur Belleville 2026-05-17 00:06:24 +02:00
parent d40909ac9b
commit 8fa490978b
No known key found for this signature in database

View file

@ -0,0 +1,112 @@
# 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 1516 restyled tablos, with own-vs-others message alignment and date-grouped planning events.
## Background
Phases 1516 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 1516 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)*