4.7 KiB
created, status, requirements, system_design, legacy_specs
| created | status | requirements | system_design | legacy_specs | ||
|---|---|---|---|---|---|---|
| 2026-09-05 | done |
|
|
Implementation Plan: Suppress invalid task timestamps
Overview
Prevent the task transcript from displaying the browser's Invalid Date text
when it renders the frontend-only task-description fallback. The fallback has
content but no persisted message timestamp, so the timestamp action is omitted;
the shared legacy relative formatter also returns an empty label for malformed
input. The implementation is one sequential frontend slice with focused unit
regressions.
Root cause
useProcessedMessages creates TASK_DESCRIPTION_SYNTHETIC_ID with
created_at: "" when history is exhausted without a stored user prompt.
MessageActions always renders MessageTimestamp, and the legacy
formatRelativeTime helper treats the invalid Date as though its numeric
comparisons were valid before falling through to date.toLocaleDateString().
The browser therefore supplies the visible string Invalid Date.
Scope
In scope
- Validate a message timestamp before rendering the timestamp action and its absolute-time disclosure.
- Make the shared legacy relative formatter return an empty string for empty or malformed input.
- Add unit coverage for the observed synthetic fallback path and the shared formatter contract.
Out of scope
- Changing task-description fallback eligibility, message persistence, or API timestamp fields.
- Adding a new mobile composition or changing action-row sizing, touch targets, navigation, or scrolling.
- Reworking the separate locale-aware formatter in
lib/i18n/formats.ts.
Technical approach
apps/web/lib/utils.ts: return""immediately when the parsed date is invalid informatRelativeTime, using the shared strict parser.apps/web/lib/utils/strict-timestamp.ts: centralize strict RFC3339 calendar, clock, offset, and fractional-second validation for timestamp consumers.apps/web/components/task/chat/messages/message-actions.tsx: validatecreatedAtinMessageTimestampwith the shared parser before deriving the absolute label or mounting the<time>/Drawer surface. Invalid timestamps keep content actions visible but omit only the timestamp affordance.apps/web/lib/state/slices/session/turn-actions.ts: delegate the existing nanosecond parser API to the shared implementation so session reconciliation and UI formatting enforce the same wire contract.- Keep the existing
formatRelativeTimeimport and action-row presentation so valid message timestamps and desktop/mobile interaction behavior are unchanged.
Tests
apps/web/lib/utils.test.ts: add an invalid and empty input regression forformatRelativeTime, including values thatDate.parsewould normalize.apps/web/components/task/chat/messages/message-actions.test.tsx: add a synthetic-fallback timestamp case asserting no<time>element orInvalid Datetext/disclosure is rendered for empty, malformed, and normalized-malformed values. This coversAC-UI-TASK-PROMPT-TRANSCRIPT-VISIBILITY-001.15.
E2E tests
No new Playwright scenario is required. This repair changes only timestamp normalization and conditionally removes an affordance from an existing inline message row; it does not change mobile composition, touch behavior, navigation, scrolling, or viewport geometry. The focused message-action test covers the shared desktop/mobile rendering path, and existing task-chat mobile flows remain the rendered transcript smoke coverage.
Work orders
Verification results
Passed:
pnpm --filter @kandev/web test -- --run lib/utils.test.ts components/task/chat/messages/message-actions.test.tsx: 51 tests passed.pnpm --filter @kandev/web test -- --run lib/state/slices/session/turn-actions.test.ts: 54 tests passed.- ESLint passed for the four changed frontend source and test files.
pnpm run typecheckpassed fromapps/web.python3 scripts/lint-spec-files.py --allpassed.git diff --checkpassed.- Managed Chromium and Pixel 5 capture specs passed with synthetic task data; both screenshots contain no
Invalid Datetext. Temporary capture specs were removed after capture.
Risks
- A malformed timestamp supplied by a persisted message will lose its timestamp affordance instead of showing a misleading value; message content and other actions remain available.
- The focused test command may regenerate frontend release-note/changelog artifacts as part of the package pretest hook; unrelated generated changes must not be included.