Skip to content

feat(client): reach-out guide page linked from detail pages (draft for #5167) - #5156

Merged
quntao-z merged 5 commits into
betafrom
fix/student-copy-and-reach-out-guide
Oct 20, 2026
Merged

quntao-z merged 5 commits into
betafrom
fix/student-copy-and-reach-out-guide

Conversation

@quntao-z

@quntao-z quntao-z commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Draft, held for design review in #5167. Per the owner rule, the reach-out guide is a design-first feature: this PR is the reference implementation for that design and is not to be merged until #5167 is approved. The bug-fix half of #5099 (jargon, hero copy, join-label honesty) lands separately.

Intent

Make y/labs student-facing copy speak the student's language and give newcomers one generic, accurate guide to reaching out (issue #5099). The /research hero should invite every field, not only labs. Detail pages should stop showing internal labels (lead contribution chip, title-cased access-signal enums, "opened above", "Lead identity under review", bare funder acronyms, "Best fit for" over topics) and should explain what a principal investigator is. A new /getting-started page answers can first-years join, what a PI is, and how to write the first email, linked from every How to get involved block, including a minimal block where the lead card is the only way in. A served join route whose address is not a join page must not be labelled as one. Serve-time client copy only: no stored data, no per-entity generated text. PR body rule: describe the regression tests by behaviour only and never quote a test fixture string, slug, or name from the diff, because the guard scans the body and a quoted fixture reads as a real person.

What Changed

  • Added a public /getting-started page that covers whether first-years can join, what a PI is, how to write a first email, pay and credit, and other ways in. It has its own page-shell title. ScrollToTop now lets a #section hash on a route change scroll to that section instead of jumping to the top. Every "How to get involved" block links to the guide. That includes a new minimal block shown when the lead card is the only way in. Principal Investigator headings now carry a one-line explanation that links to the guide's PI section.
  • Replaced internal labels on detail pages with student language:
    • The /research hero now invites labs, centers, and faculty research in every field.
    • "Best fit for" becomes "Topics".
    • Access-signal source contexts use plain labels instead of title-cased enums with an "evidence" suffix.
    • "opened above" becomes "also linked above".
    • "Lead identity under review" becomes "Lead not confirmed yet".
    • The served lead contribution label "Lead identity" becomes "Who leads it".
    • Grant summaries spell out each funder's full name next to its acronym.
  • A join or apply link whose URL path does not look like a join page is labelled "Read what they say about joining" rather than "See how to join". Regression tests cover the guide page, the minimal block, the PI explanation, join-link labelling, plain access-signal contexts, and funder name expansion. Docs, the interaction-design skill, and the student-journey smoke script are updated to the new copy.

Refs #5099, #5167

Risk Assessment

✅ Low: The fix round correctly resolves all four round-1 findings with narrow, well-tested changes: ScrollToTop skips the top reset when the hash names a committed element, the malformed hash is caught, roster tokens are dropped from JOIN_SHAPED_PATH, and the vacuous assertion now queries the renamed chip.

Testing

The Test agent exceeded its invocation budget before live validation completed; no evidence was gathered for this head.

  • Outcome: ⚠️ 1 warning across 1 run (30m4s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 4 issues found → auto-fixed ✅
  • ⚠️ client/src/pages/gettingStarted.tsx:42 - The 'What a PI does' link may not land on the PI section. Clicking it from a detail page is an in-app PUSH to /getting-started#what-is-a-pi, which counts as a route change. The global ScrollToTop (client/src/components/shared/ScrollToTop.tsx) then sets targetScrollTop=0. Its first requestAnimationFrame callback calls applyTargetScrollTop() unconditionally, and that frame runs after this page's passive effect has called scrollIntoView. So once the lazy chunk is already loaded (any visit after the first), the section scroll is reset to the top. Focus still moves to the heading while the view stays at the top of the page. The new test renders MemoryRouter without ScrollToTop, so it never exercises this. Fix at the shared boundary: have ScrollToTop skip the scroll-to-top target when location.hash names an element, rather than adding a retry in the page.
  • ⚠️ client/src/pages/__tests__/labDetail.test.tsx:1448 - expect(screen.queryByText('opened above')).toBeNull() now always passes, because labDetail.tsx:850 renames that chip to 'also linked above'. The regression test ('does not mark an official profile opened above when a join page takes the only action') no longer guards anything. Change the assertion to query 'also linked above'.
  • ⚠️ client/src/utils/researchDetailSources.ts:548 - JOIN_SHAPED_PATH is a second, wider copy of the existing APPLY_OR_JOIN_PATH (line 495). It adds tokens such as students?, undergrad(?:uate)?s?, careers?, jobs?, positions? and apply. A vetted APPLICATION_FORM_EXISTS route on a member-roster page like https://lab.example.test/students or /members/undergraduates (not under a profile-like prefix) therefore still gets the 'See how to join' label. The intent requires that 'A served join route whose address is not a join page must not be labelled as one', and a roster page is not a join page. Narrower option: extend APPLY_OR_JOIN_PATH with only the invitation-shaped tokens (opportunities, openings, positions, prospective) and drop the roster-shaped students/undergrad tokens, so one join-path definition remains. Whether staff-job tokens (careers, jobs) count as join pages is a product call.
  • ℹ️ client/src/pages/gettingStarted.tsx:37 - decodeURIComponent(hash...) throws URIError on a malformed escape such as /getting-started#%E0. The error is thrown inside an effect and reaches the error boundary, so a mistyped or shared link crashes the guide page. Wrap the decode in try/catch and return early on failure, as decodePathSegment does on the server.

🔧 Fix applied.
✅ Re-checked - no issues remain.

⚠️ **Test** - 1 warning
  • ⚠️ The Test agent did not finish within its invocation budget. Reported: agent run tests timed out after 30m0s: agent last produced output 454ms ago (122 observed); agent reported: claude parse events: context deadline exceeded. This is a budget or provider-slowness cut, not a code failure. Re-running the same request costs another full budget, so no further attempt is made automatically. If this repository's targeted tests or evidence gathering routinely approach the default 30m0s, raise test_agent_timeout in global config. Respond with fix to spend another budget: a repair turn runs only for selected findings other than this budget cut, then validation re-runs. Or abort and retry after raising the budget.
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

The /research hero now names labs, centers, and faculty research in every
field instead of labs alone. Detail pages drop internal labels: Sources chips
use student wording for access signals and the lead contribution, the
lead-under-review notice reads plainly, grant funders are spelled out, and
the topic chips are headed "Topics". A principal investigator heading gains
a one-line explanation.

A new generic /getting-started guide answers whether first-years can join,
what a PI is, and how to write a first email, pointing to Yale College's own
advice. Every How to get involved block links to it, including a minimal
block where the lead card is the only way in. A served join route whose
address is not a join page is labelled for what it is.

Closes #5099

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved automatically: the author holds the Admin repository role (#4512).

@quntao-z
quntao-z marked this pull request as draft October 18, 2026 19:09
@quntao-z quntao-z changed the title fix(client): plain student copy and a reach-out guide on research pages feat(client): reach-out guide page linked from detail pages (draft for #5167) Oct 18, 2026
…a's copy fixes and re-apply the reach-out guide
# Conflicts:
#	client/src/pages/labDetail.tsx
@quntao-z
quntao-z marked this pull request as ready for review October 20, 2026 16:44
@quntao-z
quntao-z added this pull request to the merge queue Oct 20, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved automatically: the author holds the Admin repository role (#4512).

Merged via the queue into beta with commit 5076bc1 Oct 20, 2026
10 checks passed
@quntao-z
quntao-z deleted the fix/student-copy-and-reach-out-guide branch October 20, 2026 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant