You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: 22 defects found by an adversarial review of the eight features
Every one was verified by a second pass that tried to refute it. Ordered by
what they cost.
SENDING A TRUNCATED MESSAGE, AND LOSING THE REST. The collision toast's "Send"
action called the `submit` closure captured when the warning was raised. Sonner
freezes that handler, so eight seconds of further typing was invisible to it:
it sent the older text, then cleared the field AND reset the draft dirty-check,
so the rest was destroyed in the composer and deleted server-side. It now goes
through a ref that always points at the current render.
THE COLLISION WARNING COULD SILENTLY DISARM ITSELF. The acknowledged flag was
set by SHOWING the warning rather than by acknowledging it, and never reset —
so ignoring one toast suppressed the confirmation for the next send, including
in a different conversation, since the composer instance is reused across
routes.
CITATIONS POINTED AT THE WRONG SOURCES. The answer says [3]; the source list
renumbered from 1. Every reference was off, which is worse than showing no
sources, because the entire promise of the feature is that you can check it.
Sources are now keyed by the number the model actually used, and each shows the
excerpt that was cited rather than the highest-ranked one in that conversation.
A SAVED VIEW OPENED UNFILTERED. viewHref never emitted the new `seen` or `has`
params, so a saved view built on either one showed everything while its sidebar
badge counted the filtered set.
CONTACT-NAME RETRIEVAL NEVER FIRED. `displayName % question` compares a short
name against a whole sentence with length-normalised trigram similarity, which
never clears the threshold. "What did Sarah say about the deposit" therefore
never looked at Sarah's conversations at all. Now matched word by word, with
stop words removed.
A YEAR PARSED AS A CLOCK TIME. "mar 4 2026" — the time regex took "2026" as
20:26. And in "mar 9:30" the day matcher rejected the 9 for having a colon,
then accepted the 30 as the day of the month.
PROTOTYPE KEYS RESOLVED AS WEEKDAYS. `'constructor' in WEEKDAYS` is true, so
"in 5 constructor" produced an Invalid Date that threw downstream in
toISOString(). The lookup tables are null-prototype now.
READ-NO-REPLY COUNTED OUR OWN TAPBACKS. An agent's reaction was treated as "a
message they read and ignored", flagging conversations where we owed the reply.
THE GHOST TEXT DID NOT LINE UP. The Textarea base carries `md:text-sm`, which
twMerge keeps alongside `text-[13.5px]` — so above 768px the real text was 14px
and the ghost 13.5px. A completion that wrapped was also clipped out of sight
while Tab still accepted all of it; the field now grows to fit it.
FIND COUNTED HITS IT COULD NOT SHOW YOU. System events and tapbacks matched,
but they render as centred pills with no ref and no highlighting, so those
stops scrolled nowhere. Overlapping matches were counted but collapsed by the
highlighter, making "3 of 5" a lie; the matcher and the renderer now agree, and
a test asserts they always will.
Also: the note/reply toggle was dropped by the pagehide flush, which compared
only the body — the one mechanism that exists to cover the debounce window
would have turned an internal note into a public reply. The date picker
committed on every keystroke that happened to form a valid value, discarded
past times with no feedback, and had no `min`. The person panel's primary
address had no ORDER BY, so an email sorting first silently removed the local
time.
9 new tests, 205 total.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RuKkB7AfSNCcwvubV99pDU
0 commit comments