Skip to content

Ofrece una pregunta de muestra a invitados (prueba 50/50) - #330

Merged
alejooroncoy merged 7 commits into
mainfrom
codex/guest-sample-question
Nov 12, 2026
Merged

alejooroncoy merged 7 commits into
mainfrom
codex/guest-sample-question

Conversation

@alejooroncoy

Copy link
Copy Markdown
Owner

Qué hace

Desde #293 el asistente web exige cuenta. Con este PR, si el backend ofrece la muestra (session.guestSample.available), la mitad de los invitados nuevos puede hacer una pregunta sobre profesores o cursos y después ve una invitación a crear cuenta. La otra mitad mantiene el muro actual.

  • El brazo (sample / gate) se sortea una vez, se guarda en el navegador y se registra en campus_guest_sample_assigned. No se asigna mientras el backend no ofrezca la muestra, para no contaminar la medición.
  • Sin guestSample en la sesión, el comportamiento es idéntico al actual (cubierto por prueba).
  • Solo 2 ideas de inicio (profesores y cursos), sin reseñas ni universidad previa.
  • Tras la respuesta (usage.period === 'sample', sin cupo) el compositor se oculta y aparece el CTA; si el backend responde 401 se mantiene el flujo de login con borrador.

Depende de

Backend en campus-profes (sesión aparte): guestSample en /api/app/session, una pregunta por invitado/IP, tope diario e interruptor GUEST_SAMPLE_ENABLED (apagado por defecto). Este PR no cambia nada visible hasta que ese backend esté desplegado y encendido.

Medición

Eventos nuevos en el contrato: campus_guest_sample_assigned, campus_guest_sample_served, campus_guest_sample_cta_clicked, propiedad guest_sample_arm (sample/gate). El análisis por persona se une por el evento de asignación; el login (campus_auth_completed) se compara por brazo.

Pruebas

  • site/scripts/guest-sample-e2e.mjs (nuevo, también en CI): brazo muestra con una pregunta y CTA, brazo muro, backend sin muestra, muestra gastada y estabilidad del sorteo.
  • Siguen pasando account-required, first-question, guest-signup y test:analytics; npm run check sin errores.

No incluido

No se despliega nada. Falta la revisión con @codex review y /review.

🤖 Generated with Claude Code

The assistant requires an account since #293. When the backend offers a
guest sample (session.guestSample.available), half of new guests, chosen
once and stored in the browser, can ask one question about professors or
courses and then see an account call to action. The other half keeps the
current wall. Without the backend sample nothing changes.

Adds guest_sample_arm and three events (assigned, served, cta_clicked) to
the analytics contract, an e2e test and a CI step.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
landing Ready Ready Preview Nov 11, 2026 11:47pm UTC

@alejooroncoy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-11T23:49:09.243303Z 0c59f8e Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fefd7ba1af

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread site/src/components/ProfesChat.tsx Outdated
Comment on lines +901 to +903
const offered = guestSampleOffered(session, assignGuestSampleArm(session));
setSampleMode(offered);
setAccess(offered ? (session.aiReady ? "ready" : "unavailable") : "login");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve the sample conversation when session eligibility refreshes

After a guest consumes the sample, the next session response has guestSample.available: false, so this assignment clears sampleMode and the early login-wall return hides both the answer and the post-answer signup CTA. This happens without a reload: watchLiveCampusSession() in site/src/scripts/live-session.ts refreshes every 15 seconds and on window focus, and its campus:session-updated event calls this function. A refresh during a longer request can even hide the conversation before its answer appears. Preserve the active sample view after consumption while preventing further questions, rather than treating refreshed eligibility as a reason to replace the conversation with the login wall.

Useful? React with 👍 / 👎.

Once the sample is spent the backend stops offering it, so a session
refresh (live session, usage update) turned sampleMode off and replaced the
answer and the account call to action with the login wall. The mode now
sticks for the page lifetime and a test dispatches the refresh.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Runs the built site with the campus-profes handler (in-memory store, fake
agent): one answer, wall after use, per-IP limit, gate arm, kill switch,
daily cap and forged X-Forwarded-For. Skips when the backend repo with the
guest sample is not available, so it is not part of CI.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
With CAMPUS_E2E_DATABASE_URL (localhost only) the fixture uses the backend's
real store on a temporary schema with migrations 151-153 and 209, checks the
stored rows (hashed IP only, tokens, conversation) and adds a concurrency
scenario: simultaneous requests reserve a single sample.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@alejooroncoy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f5f61e7b7b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread site/src/components/ProfesChat.tsx Outdated

{!busy&&feedbackTrace&&messages.at(-1)?.role==='assistant' ? <AgentFeedback key={`feedback:${feedbackTrace}`} traceId={feedbackTrace}/> : null}
<div className="app-profes-ai__composer-dock">
{sampleUsed && !busy && messages.at(-1)?.role === 'assistant' ? (

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep the signup prompt visible after starting a new consultation

After a guest finishes the sample, clicking the still-enabled “Nueva consulta” button calls startNewConversation(), which clears the messages without resetting sampleUsed or sampleMode. The signup CTA then disappears because the last message is no longer an assistant message, while the composer remains hidden and the login wall remains bypassed. This leaves the main chat showing starters instead of either an input or the post-sample signup prompt. Handle the consumed-sample state independently of the currently selected conversation, or redirect new-consultation actions to signup once the sample is used.

Useful? React with 👍 / 👎.

Clicking Nueva consulta after the sample cleared the messages but kept
sampleMode, leaving starters with no composer and no signup prompt. With the
sample spent and no visible conversation the account wall returns; the
signup prompt now follows any visible conversation. Found by Codex review.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@alejooroncoy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2fc79f99ee

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

async function sendQuestion(raw: string, example?: (typeof suggestions[number] | typeof studySuggestions[number])["id"]) {
const question = raw.trim();
if (session?.authenticated === false) { markGuestDraftHandoff(); window.location.assign(getLoginUrl()); return; }
if (session?.authenticated === false && (!sampleMode || sampleUsed)) { markGuestDraftHandoff(); window.location.assign(getLoginUrl()); return; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve the sample question before redirecting on a 401

If the backend rejects an offered sample with a 401—for example, because its quota was consumed in another tab—the guest now enters sendMessage() instead of the previous immediate login handoff. sendQuestion() clears the input, and the input effect removes the persisted draft while the request is pending. The transport then calls markGuestDraftHandoff() before redirecting, so there is no question to transfer; restoring the input afterward cannot repair the missing handoff marker. Consequently, signing in loses the question instead of preserving the advertised login-with-draft fallback. Persist and mark the rejected question before navigating to login.

Useful? React with 👍 / 👎.

When the backend rejects an offered sample with 401 (spent in another tab),
sendQuestion has already cleared the field and its draft, so the handoff had
nothing to carry. The rejected question is now persisted as a guest draft
(never over an authenticated owner's drafts) before redirecting to login.
Found by Codex review.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@alejooroncoy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 0c59f8ec38

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@alejooroncoy
alejooroncoy merged commit 36b3c1c into main Nov 12, 2026
3 checks passed

This branch was successfully deployed

1 active deployment
Preview — 0c59f8ec Deployed Nov 11, 2026 by vercel[bot]
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