Repository navigation
feat(messages): show "<author> in #<channel>" for message links - #1969
Conversation
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 The new fallback-name assertion fails against current main and blocks required CI. Please rebase and update the test and redundant fragment filtering. Two documentation contracts also need correction.
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord’s automated source review via Wes’s account. Reviewed head 6576a15 against target base 36a283b (merge-base 9818f77).
One new P2 is inline: passive author lookups occupy foreground transport capacity and can delay opening another thread. I also corroborated the existing P2 fallback-name test finding: the target base excludes fallback profile names, so the new assertion at linked-message.test.tsx:252 contradicts that contract. The hosted JavaScript (2/3) log reports this exact assertion failure. Please update that assertion while preserving the unnamed-channel and named-agent behavior checks; no duplicate inline thread added.
The existing documentation note is a useful optional clarification of deletion and reconnect behavior; this review does not request changing the documented session-cache tradeoff. The public description, four attached fixture screenshots and commit messages showed no concrete disclosure issue.
Rocket, Mantis and Groot completed their independent source lanes; Star Lord checked and integrated the findings.
Validation limits: source-only review; no local tests, builds, app launches, live-relay requests or rendered/accessibility/performance validation. One hosted CI snapshot showed CI required failing (JavaScript 2/3, both Vitest flake checks and WebKit 8/12); the WebKit failure concerns closing an active thread, and its relationship to this change remains unestablished. No approval or merge authorization.
6576a15 to
2a00e50
Compare
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord’s automated source review via Wes’s account. Follow-up reviewed at head 2a00e50 against target base fb78d21 (merge-base 0944c1d), with independent Rocket, Mantis and Groot coverage.
No new actionable findings in the names-view cleanup. The prior four feature commits are patch-equivalent after rebase; the new two-file commit correctly delegates synthetic-name suppression to the shared names service and updates the fixture expectation. The service still subscribes to profile changes, so removing the local subscription preserves later name updates.
The existing P2 reader-admission finding remains unresolved at this head. Passive author lookups still enter the shared three-slot transport scheduler as foreground work and can delay an unrelated thread opening. That finding and its requested repair remain in the original thread; no duplicate inline finding is added here.
Reviewed the public description, all four attached screenshots and feature commit messages; no new disclosure finding. This is a bounded source-only follow-up, not fresh runtime acceptance of the whole rebased tree. No tests, builds or app execution were performed, and current CI, native behavior, keyboard/theme rendering and latency were not verified. This COMMENT is not approval or merge authorization.
2a00e50 to
a3c3079
Compare
A raw Buzz message or thread link now reads "<icon> <author> in #<channel>" instead of only the channel name, in both its visible label and its accessible name. The icon, styling, preview card, menu and click behaviour are unchanged, and selection copy still yields the raw URL. The author comes from the same bounded exact thread reader the hover preview uses; the session exposes no other single-message read. A session-scoped lookup borrows one reader per linked message, disposes it as soon as the author is known, remembers the result for the session, runs at most four at once so open threads and previews keep their capacity, and cancels a lookup when its last link unmounts. Names resolve through the existing identity names, profile names and workflow attribution. The preview now shares its ready/stopped check. The previous channel presentation stays while the author is unknown or unnamed, when the message is unavailable or no reader is free, and for DMs, Solo chats, unlisted channels, authored labels, and composer drafts and previews, which never read. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Matt Toohey <[email protected]>
Addresses the review of 1c81e00. A link's author never shows as a key fragment. A profile with no name (nameIsFallback) keeps the channel label even when the identity names view hands back its fragment, while an agent's library name still names it. The unit fixture now resolves through the app's own names view and agent directory, which return that fragment. A link in a channel whose membership is still cached waits for the relay to confirm it before reading. A deleted or unavailable message keeps the channel label and is remembered for the session, so virtualized remounts do not read it again. Any other failed read is retried when the live stream connects again, the session's own retry signal, or once every link to that message has unmounted; it never retries in a loop. A message its channel's timeline already holds takes its author from that row, without borrowing a reader. A workflow's message reads "Workflow in #<channel>", the name its row header shows, in both the visible label and the accessible name. Replies held only by an open thread panel still take the exact read: reaching them needs a lookup in the FOUNDATION relay session, which is left for explicit guidance. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Matt Toohey <[email protected]>
…ge rows Addresses the review of 6737fb8. An unavailable message is no longer remembered for the session. A read can be served by a replica that lags behind a message just posted, so an unavailable result now takes the same path as any other failed read: the link keeps the channel label, and the message is read again once every link to it has unmounted or the live stream connects again. It never retries in a loop. The separate set of missing messages is gone. The channel's timeline names an author only from a message row, as the exact reader does. Membership and huddle rows are read instead, and a timeline restored from disk is not trusted until it is revalidated. An author already found stays shown for the session, even once its message is deleted; the doc comment now says so. A lookup's cleanup and refresh now check that it is still the running lookup for its key, not just that some lookup holds the key, so they do not depend on lookups starting in a later microtask. New unit tests cover an unavailable message that a remount reads again and finds, a failed read retried once every link has unmounted while the stream stays connected, and the system-row and restored-timeline skips. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Matt Toohey <[email protected]>
Addresses the review of 76c5ffd. The comment on the linked-message timeline shortcut said a window restored from disk waits until it is revalidated. It does not wait: a cached window, whether restored from disk or marked cached after a stream drop, skips the local match and the exact reader decides. The comment now says so. Behaviour is unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Matt Toohey <[email protected]>
…now owns Rebasing onto main brought in #1927, which makes every identity-names resolver drop fallback (key-fragment) profile names. The link's own fragment comparison is dead, and the test premise that the names view hands back the fragment no longer holds. Co-Authored-By: Claude Fable 5.1 <[email protected]> Signed-off-by: Matt Toohey <[email protected]>
Addresses the review of a3c3079. A link's author lookup borrowed an exact thread reader whose reads took foreground admission, so three slow lookups could hold every transport slot and queue the read of a thread the person then opened. The thread view now takes a read priority, applied by its retrying read wrapper to every read it makes, and the session's thread() forwards it. Link lookups ask for background admission: the shared scheduler runs one background read at a time and starts a foreground read ahead of it, so opening or previewing a conversation reads first. The exact reader's access, cap and admission checks are unchanged, and a lookup that shares a filter with an opened thread still shares and promotes that read. A new thread-target test holds three background label reads and shows an opened thread's target, overlay and root reads start at once; it fails when the priority is not forwarded. The plugin-architecture doc now says an author once found stays shown for the session even after its message is deleted, that a message the lookup cannot find or read keeps the channel name, and that it is read again when a link to it mounts again or the live stream connects again. Co-Authored-By: Claude Fable 5.1 <[email protected]> Signed-off-by: Matt Toohey <[email protected]>
a3c3079 to
f61cd57
Compare
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord’s automated source follow-up via Wes’s account, integrating Rocket, Mantis and Groot reviews.
No required changes found. The prior P2 about passive message-author lookups consuming foreground read capacity is resolved: linked-message.ts requests background priority, session.ts forwards it, and threads.ts applies it to both read wrappers and their retries. The existing scheduler limits background work to one slot and prioritizes queued foreground work; preview callers retain foreground defaults. Access checks, shared-read cancellation and cleanup remain intact.
Reviewed head f61cd57 against target base 76803df (merge base e7ae7b1). Range-diff confirms the five earlier feature patches are unchanged from reviewed head 2a00e50; this follow-up covers the six-file repair and its relevant callers.
Optional wording only: in docs/plugin-architecture.md, “A live link’s lookup reads take background admission” would distinguish passive lookups more explicitly from foreground hover/focus previews.
Source-only review: no tests, builds or app runs performed. The new service-level regression test was inspected, not executed; this follow-up adds/removes no browser cases. A one-time hosted snapshot showed CI required successful and Windows native validation skipped. Real relay latency, cold/warm opening performance, native behavior, rendered focus and assistive-technology behavior remain unverified. All four PR images and the public description were inspected; the images show older fixture captures, not current runtime acceptance. This COMMENT is not approval or merge authorization.
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 Reviewed f61cd57. The passive-read scheduling issue is fixed: held background lookups no longer block unrelated thread opening. No actionable findings remain from our review; targeted tests and Chromium/WebKit workflow checks passed.
…2607) ## Problem The PR flake check repeated only the tests in files a pull request edited. If a product change made an unedited test racy, the check selected nothing. #2000 repeated one emoji journey and skipped the seven other specs that load `emoji.html`. Five of its flaky journeys were in those specs. ## What changes `scripts/flake-check.mjs select` now selects in two tiers: - **Tier 1, edited tests.** This is exactly the old rule: same repetitions, both engines. The budget never trims it, even when tier 1 alone goes over. - **Tier 2, related tests**, run as whole files: - Browser specs that import a changed helper, or that open a `tests/fixtures/*.html` page whose module graph holds a changed source file, stylesheet or patched package. One rolldown build of every spec and fixture page supplies the graph and writes nothing (1,027 modules in about 1 s). - Vitest files related to the changed modules through Vitest's module graph. This is the graph the pre-push `vitest related` uses. Picks are ranked by specificity: the smallest route that holds a changed file comes first, and the cheaper test wins a tie. A test named after a changed module ranks ahead of that order (`ComposerAttachments.tsx` → `composer-attachments.spec.mjs`). The step summary marks those rows as a naming heuristic, not graph evidence. Tier 2 adds picks in rank order while each lane's predicted wall time (`flake_browser` and `flake_vitest`) stays within **9 minutes** (`LANE_BUDGET_MINUTES`; `--budget=<minutes>` overrides it). The 40-journey and 20-Vitest-file caps still apply, and the pick that crosses a cap still runs. **Cost table.** `scripts/flake-check-costs.json` is checked in and written by the new `flake-check costs [run-id…]` subcommand. By default it reads the latest three green `main` push runs. It reads the required lanes' Playwright and Vitest reports and stores median passing seconds per journey title as [Chromium, WebKit], plus a median per Vitest file. A test missing from the table falls back to its file's median, then to the engine-wide median or the median of all Vitest files. I checked in the table instead of fetching timings in CI for three reasons: `select` stays reproducible from the commit, `flake_select` needs no token or network, and the artifacts are about 100 MB per run and expire after 7 days. The current table comes from runs 41990511962, 41980968364 and 41979442279 (Nov 5): 1,049 journeys and 964 Vitest files in 181 KB. **Lane model.** I fit the model to hosted PR runs from Nov 4–5. The median predicted/actual ratio is 0.95 for the browser lane and 1.02 for Vitest. - Browser shard: 105 s of overhead + 1.11 × the shard's summed test time × 10 repetitions / 2 workers, then × 1.22 for imbalance when there is more than one shard. - Vitest batch: 26 s + 5 × (5.7 s + 0.72 × max(sum / 2, slowest file)). The step summary gains a Tier column. It also shows each lane's predicted time against the budget, with the edited-only time beside it, and the related picks dropped for time and for the cap. `docs/contributing.md` describes the tiers and the budget. It also corrects "at most eight" shards to sixteen (`MAX_SHARDS`). ## For reviewers: the budget takes the longest fitting prefix Tier 2 does **not** stop at the first pick that would go over the budget. It takes the longest rank-order prefix whose predicted lane fits. Browser shards grow with the selection (one shard per five journeys), so a longer prefix can predict a *shorter* lane than a shorter prefix. In the 248-PR replay, stopping at the first overrun would have trimmed browser picks in 45 PRs. In 44 of those, the cap-only selection already fit, and 40 predicted a slower lane after trimming. #2000 would have kept 2 related journeys at 8.6 minutes instead of 46 at 6.2, and lost both of its flaky specs. Ranks are never skipped. The Vitest lane only grows with each pick, so both rules give the same result there. A unit test covers the non-monotonic case, and that test fails under a first-overrun loop. ## Validation Replays of `select <merge>^1 <merge>` in detached checkouts of each merge commit. Selection before this PR → after: | PR | Edited Vitest / journeys | Related journeys | Related Vitest | Browser lane (min) | Vitest lane (min) | Flaky targets kept | | --- | --- | --- | --- | --- | --- | --- | | #2000 0944c1d | 1 / 1 | 0 → 46 (12 specs, incl. reactions-polish, message-overlays) | 0 → 4 | 6.2 | 1.5 | yes | | #1361 5992e69 | 2 / 0 | 0 → 40 (incl. composer-attachments, by name) | 0 → 0 (budget) | 8.0 | 9.4 (edited alone 9.4) | yes | | #2291 83b72a3 | 2 / 153 | 0 → 0 (budget) | 0 → 18 | 15.3 (edited alone 15.3) | 6.6 | n/a | | #1910 e7ae7b1 | 3 / 0 | 0 → 53 | 0 → 10 | 5.7 | 9.0 | n/a | Lane times are this PR's predictions. Without the budget (the first commit alone), the Vitest lane would have been 9.8 min for #2000, 16.3 min for #1910 and 6.6 min for #2291, and #2291's browser lane 18.3 min. `--budget=Infinity` reproduces the first commit's output byte for byte on all four source PRs. In the first commit's replay, a spec-only PR (#2557) and a docs-only PR (#1694) selected exactly what the old rule selected. - `node --test tests/integration/flake-check.test.mjs`: 20 pass. Biome is clean, including the table. - Local `select` time on a laptop: #2000 takes 49 s with a cold Vitest cache and 6 s warm (13 s before); #1361 takes 63 s cold and 8 s warm (19 s before). CI runs cold, within the select job's 5-minute limit. These are local measurements, not hosted ones. ## Cost and known gaps - **Runner-minutes grow about 7.5×.** In a replay of the 248 PRs merged Nov 2–4, flake runner-minutes per run averaged about 11.4 under the old rule and about 84 with related selection. Almost every source PR fills the 40/20 caps, and the caps are what bound the cost. The budget limits wall time only: against the first commit it moves the mean from 84.6 to 84.0 and the max from 381 to 319 (#2291). Lane wall time stays about 6–7 minutes for most PRs, and the highest predicted lanes fall from 16.7 to 13.7 minutes (browser) and from 16.3 to 10.4 (Vitest). All 11 Vitest lanes still over 9 minutes are over on edited tests alone. The lanes stay advisory, and repetitions, timeouts and workers are unchanged. - **Not yet run in hosted CI.** This PR's own run will be the first. - **Cost table drift.** Timings go stale until someone reruns `flake-check costs`. - **Model error.** Predicted/actual ranges from 0.73 to 1.23 (p10–p90) for the browser lane and from 0.75 to 1.58 for Vitest. A Vitest `file:line` filter is charged for its whole file. - **Full-app journeys.** Journeys that load the full app rather than a fixture page are reached only through helpers. This misses #1729, #2108 and #1969, which a coverage-map follow-up would address. A patched package reaches browser specs but not Vitest files. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Matt Toohey <[email protected]> Co-authored-by: Claude Fable 5.1 <[email protected]>
Summary
A raw Buzz message or thread link now names the message's author. Before, it showed only the channel name (
Alpha). Now it reads<author> in #<channel>(Alice Fixture in #Alpha) in both the visible label and the accessible name. The icon, styling, hover preview card, menu, click behaviour and selection copy (which still yields the raw URL) are unchanged.Before and after
Captured with the real-app browser fixture behind
tests/browser/buzz-links.spec.mjs(WebKit, 1280×800 at 2×). "Before" is the merge base9818f778e. "After" is76c5ffd75; the only later commit,6576a15cc, changes a comment.Dark theme
When the old label stays
The link keeps its previous channel presentation when:
A workflow's message reads
Workflow in #<channel>, matching its row header.How the author is found
Names resolve through the existing identity names, profile names and workflow attribution.
BuzzLinkPreviewnow shares its ready/stopped check with the lookup.docs/plugin-architecture.mddescribes the new label and the reader use.Commits
6ec71482ffeat(messages): name the author in message links13cb363f4fix(messages): keep message link authors named, local and retryable6c555884bfix(messages): re-read unavailable message links and trust only message rowsca410f719docs(messages): say a cached timeline window defers to the exact reader2f2a9d8f5fix(messages): drop the message link's fragment guard the names view now ownsf61cd574ffix(messages): read message link authors in the backgroundValidation
Run locally during development:
design:checksrc/features/conversation/linked-message.test.tsx(new unit tests) and the dependent Vitest filessrc/features/relay/thread-target.test.ts: the new background-admission case fails when the thread view does not forward its priority (fail-before run), andthreads,reader,thread-windowandtraffic.integrationpassbuzz-links,nested-repliesandnavigation-thread-historyin Chromium and WebKitThe branch was pushed with
--no-verifybecause pre-push tests time out under load on the author's machine. Hosted CI is the broad check.Known trade-offs
<author> in #<channel>.🤖 Generated with Claude Code